]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdeModulePkg/Core/Dxe/Hand/Handle.c
Clean up DxeCore to remove duplicate memory allocation & device path utility services...
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Hand / Handle.c
... / ...
CommitLineData
1/** @file\r
2 UEFI handle & protocol handling.\r
3\r
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
12\r
13**/\r
14\r
15#include "DxeMain.h"\r
16\r
17\r
18//\r
19// mProtocolDatabase - A list of all protocols in the system. (simple list for now)\r
20// gHandleList - A list of all the handles in the system\r
21// gProtocolDatabaseLock - Lock to protect the mProtocolDatabase\r
22// gHandleDatabaseKey - The Key to show that the handle has been created/modified\r
23//\r
24LIST_ENTRY mProtocolDatabase = INITIALIZE_LIST_HEAD_VARIABLE (mProtocolDatabase);\r
25LIST_ENTRY gHandleList = INITIALIZE_LIST_HEAD_VARIABLE (gHandleList);\r
26EFI_LOCK gProtocolDatabaseLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY);\r
27UINT64 gHandleDatabaseKey = 0;\r
28\r
29\r
30\r
31/**\r
32 Acquire lock on gProtocolDatabaseLock.\r
33\r
34**/\r
35VOID\r
36CoreAcquireProtocolLock (\r
37 VOID\r
38 )\r
39{\r
40 CoreAcquireLock (&gProtocolDatabaseLock);\r
41}\r
42\r
43\r
44\r
45/**\r
46 Release lock on gProtocolDatabaseLock.\r
47\r
48**/\r
49VOID\r
50CoreReleaseProtocolLock (\r
51 VOID\r
52 )\r
53{\r
54 CoreReleaseLock (&gProtocolDatabaseLock);\r
55}\r
56\r
57\r
58\r
59/**\r
60 Check whether a handle is a valid EFI_HANDLE\r
61\r
62 @param UserHandle The handle to check\r
63\r
64 @retval EFI_INVALID_PARAMETER The handle is NULL or not a valid EFI_HANDLE.\r
65 @retval EFI_SUCCESS The handle is valid EFI_HANDLE.\r
66\r
67**/\r
68EFI_STATUS\r
69CoreValidateHandle (\r
70 IN EFI_HANDLE UserHandle\r
71 )\r
72{\r
73 IHANDLE *Handle;\r
74\r
75 Handle = (IHANDLE *)UserHandle;\r
76 if (Handle == NULL) {\r
77 return EFI_INVALID_PARAMETER;\r
78 }\r
79 if (Handle->Signature != EFI_HANDLE_SIGNATURE) {\r
80 return EFI_INVALID_PARAMETER;\r
81 }\r
82 return EFI_SUCCESS;\r
83}\r
84\r
85\r
86\r
87/**\r
88 Finds the protocol entry for the requested protocol.\r
89 The gProtocolDatabaseLock must be owned\r
90\r
91 @param Protocol The ID of the protocol\r
92 @param Create Create a new entry if not found\r
93\r
94 @return Protocol entry\r
95\r
96**/\r
97PROTOCOL_ENTRY *\r
98CoreFindProtocolEntry (\r
99 IN EFI_GUID *Protocol,\r
100 IN BOOLEAN Create\r
101 )\r
102{\r
103 LIST_ENTRY *Link;\r
104 PROTOCOL_ENTRY *Item;\r
105 PROTOCOL_ENTRY *ProtEntry;\r
106\r
107 ASSERT_LOCKED(&gProtocolDatabaseLock);\r
108\r
109 //\r
110 // Search the database for the matching GUID\r
111 //\r
112\r
113 ProtEntry = NULL;\r
114 for (Link = mProtocolDatabase.ForwardLink;\r
115 Link != &mProtocolDatabase;\r
116 Link = Link->ForwardLink) {\r
117\r
118 Item = CR(Link, PROTOCOL_ENTRY, AllEntries, PROTOCOL_ENTRY_SIGNATURE);\r
119 if (CompareGuid (&Item->ProtocolID, Protocol)) {\r
120\r
121 //\r
122 // This is the protocol entry\r
123 //\r
124\r
125 ProtEntry = Item;\r
126 break;\r
127 }\r
128 }\r
129\r
130 //\r
131 // If the protocol entry was not found and Create is TRUE, then\r
132 // allocate a new entry\r
133 //\r
134 if ((ProtEntry == NULL) && Create) {\r
135 ProtEntry = AllocatePool (sizeof(PROTOCOL_ENTRY));\r
136\r
137 if (ProtEntry != NULL) {\r
138 //\r
139 // Initialize new protocol entry structure\r
140 //\r
141 ProtEntry->Signature = PROTOCOL_ENTRY_SIGNATURE;\r
142 CopyGuid ((VOID *)&ProtEntry->ProtocolID, Protocol);\r
143 InitializeListHead (&ProtEntry->Protocols);\r
144 InitializeListHead (&ProtEntry->Notify);\r
145\r
146 //\r
147 // Add it to protocol database\r
148 //\r
149 InsertTailList (&mProtocolDatabase, &ProtEntry->AllEntries);\r
150 }\r
151 }\r
152\r
153 return ProtEntry;\r
154}\r
155\r
156\r
157\r
158/**\r
159 Finds the protocol instance for the requested handle and protocol.\r
160 Note: This function doesn't do parameters checking, it's caller's responsibility\r
161 to pass in valid parameters.\r
162\r
163 @param Handle The handle to search the protocol on\r
164 @param Protocol GUID of the protocol\r
165 @param Interface The interface for the protocol being searched\r
166\r
167 @return Protocol instance (NULL: Not found)\r
168\r
169**/\r
170PROTOCOL_INTERFACE *\r
171CoreFindProtocolInterface (\r
172 IN IHANDLE *Handle,\r
173 IN EFI_GUID *Protocol,\r
174 IN VOID *Interface\r
175 )\r
176{\r
177 PROTOCOL_INTERFACE *Prot;\r
178 PROTOCOL_ENTRY *ProtEntry;\r
179 LIST_ENTRY *Link;\r
180\r
181 ASSERT_LOCKED(&gProtocolDatabaseLock);\r
182 Prot = NULL;\r
183\r
184 //\r
185 // Lookup the protocol entry for this protocol ID\r
186 //\r
187\r
188 ProtEntry = CoreFindProtocolEntry (Protocol, FALSE);\r
189 if (ProtEntry != NULL) {\r
190\r
191 //\r
192 // Look at each protocol interface for any matches\r
193 //\r
194 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link=Link->ForwardLink) {\r
195\r
196 //\r
197 // If this protocol interface matches, remove it\r
198 //\r
199 Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);\r
200 if (Prot->Interface == Interface && Prot->Protocol == ProtEntry) {\r
201 break;\r
202 }\r
203\r
204 Prot = NULL;\r
205 }\r
206 }\r
207\r
208 return Prot;\r
209}\r
210\r
211\r
212/**\r
213 Removes an event from a register protocol notify list on a protocol.\r
214\r
215 @param Event The event to search for in the protocol\r
216 database.\r
217\r
218 @return EFI_SUCCESS if the event was found and removed.\r
219 @return EFI_NOT_FOUND if the event was not found in the protocl database.\r
220\r
221**/\r
222EFI_STATUS\r
223CoreUnregisterProtocolNotifyEvent (\r
224 IN EFI_EVENT Event\r
225 )\r
226{\r
227 LIST_ENTRY *Link;\r
228 PROTOCOL_ENTRY *ProtEntry;\r
229 LIST_ENTRY *NotifyLink;\r
230 PROTOCOL_NOTIFY *ProtNotify;\r
231\r
232 CoreAcquireProtocolLock ();\r
233\r
234 for ( Link = mProtocolDatabase.ForwardLink;\r
235 Link != &mProtocolDatabase;\r
236 Link = Link->ForwardLink) {\r
237\r
238 ProtEntry = CR(Link, PROTOCOL_ENTRY, AllEntries, PROTOCOL_ENTRY_SIGNATURE);\r
239\r
240 for ( NotifyLink = ProtEntry->Notify.ForwardLink;\r
241 NotifyLink != &ProtEntry->Notify;\r
242 NotifyLink = NotifyLink->ForwardLink) {\r
243\r
244 ProtNotify = CR(NotifyLink, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);\r
245\r
246 if (ProtNotify->Event == Event) {\r
247 RemoveEntryList(&ProtNotify->Link);\r
248 CoreFreePool(ProtNotify);\r
249 CoreReleaseProtocolLock ();\r
250 return EFI_SUCCESS;\r
251 }\r
252 }\r
253 }\r
254\r
255 CoreReleaseProtocolLock ();\r
256 return EFI_NOT_FOUND;\r
257}\r
258\r
259\r
260\r
261/**\r
262 Removes all the events in the protocol database that match Event.\r
263\r
264 @param Event The event to search for in the protocol\r
265 database.\r
266\r
267 @return EFI_SUCCESS when done searching the entire database.\r
268\r
269**/\r
270EFI_STATUS\r
271CoreUnregisterProtocolNotify (\r
272 IN EFI_EVENT Event\r
273 )\r
274{\r
275 EFI_STATUS Status;\r
276\r
277 do {\r
278 Status = CoreUnregisterProtocolNotifyEvent (Event);\r
279 } while (!EFI_ERROR (Status));\r
280\r
281 return EFI_SUCCESS;\r
282}\r
283\r
284\r
285\r
286\r
287/**\r
288 Wrapper function to CoreInstallProtocolInterfaceNotify. This is the public API which\r
289 Calls the private one which contains a BOOLEAN parameter for notifications\r
290\r
291 @param UserHandle The handle to install the protocol handler on,\r
292 or NULL if a new handle is to be allocated\r
293 @param Protocol The protocol to add to the handle\r
294 @param InterfaceType Indicates whether Interface is supplied in\r
295 native form.\r
296 @param Interface The interface for the protocol being added\r
297\r
298 @return Status code\r
299\r
300**/\r
301EFI_STATUS\r
302EFIAPI\r
303CoreInstallProtocolInterface (\r
304 IN OUT EFI_HANDLE *UserHandle,\r
305 IN EFI_GUID *Protocol,\r
306 IN EFI_INTERFACE_TYPE InterfaceType,\r
307 IN VOID *Interface\r
308 )\r
309{\r
310 return CoreInstallProtocolInterfaceNotify (\r
311 UserHandle,\r
312 Protocol,\r
313 InterfaceType,\r
314 Interface,\r
315 TRUE\r
316 );\r
317}\r
318\r
319\r
320/**\r
321 Installs a protocol interface into the boot services environment.\r
322\r
323 @param UserHandle The handle to install the protocol handler on,\r
324 or NULL if a new handle is to be allocated\r
325 @param Protocol The protocol to add to the handle\r
326 @param InterfaceType Indicates whether Interface is supplied in\r
327 native form.\r
328 @param Interface The interface for the protocol being added\r
329 @param Notify indicates whether notify the notification list\r
330 for this protocol\r
331\r
332 @retval EFI_INVALID_PARAMETER Invalid parameter\r
333 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate\r
334 @retval EFI_SUCCESS Protocol interface successfully installed\r
335\r
336**/\r
337EFI_STATUS\r
338CoreInstallProtocolInterfaceNotify (\r
339 IN OUT EFI_HANDLE *UserHandle,\r
340 IN EFI_GUID *Protocol,\r
341 IN EFI_INTERFACE_TYPE InterfaceType,\r
342 IN VOID *Interface,\r
343 IN BOOLEAN Notify\r
344 )\r
345{\r
346 PROTOCOL_INTERFACE *Prot;\r
347 PROTOCOL_ENTRY *ProtEntry;\r
348 IHANDLE *Handle;\r
349 EFI_STATUS Status;\r
350 VOID *ExistingInterface;\r
351\r
352 //\r
353 // returns EFI_INVALID_PARAMETER if InterfaceType is invalid.\r
354 // Also added check for invalid UserHandle and Protocol pointers.\r
355 //\r
356 if (UserHandle == NULL || Protocol == NULL) {\r
357 return EFI_INVALID_PARAMETER;\r
358 }\r
359\r
360 if (InterfaceType != EFI_NATIVE_INTERFACE) {\r
361 return EFI_INVALID_PARAMETER;\r
362 }\r
363\r
364 //\r
365 // Print debug message\r
366 //\r
367 DEBUG((DEBUG_LOAD | DEBUG_INFO, "InstallProtocolInterface: %g %p\n", Protocol, Interface));\r
368\r
369 Status = EFI_OUT_OF_RESOURCES;\r
370 Prot = NULL;\r
371 Handle = NULL;\r
372\r
373 if (*UserHandle != NULL_HANDLE) {\r
374 Status = CoreHandleProtocol (*UserHandle, Protocol, (VOID **)&ExistingInterface);\r
375 if (!EFI_ERROR (Status)) {\r
376 return EFI_INVALID_PARAMETER;\r
377 }\r
378 }\r
379\r
380 //\r
381 // Lock the protocol database\r
382 //\r
383 CoreAcquireProtocolLock ();\r
384\r
385 //\r
386 // Lookup the Protocol Entry for the requested protocol\r
387 //\r
388 ProtEntry = CoreFindProtocolEntry (Protocol, TRUE);\r
389 if (ProtEntry == NULL) {\r
390 goto Done;\r
391 }\r
392\r
393 //\r
394 // Allocate a new protocol interface structure\r
395 //\r
396 Prot = AllocateZeroPool (sizeof(PROTOCOL_INTERFACE));\r
397 if (Prot == NULL) {\r
398 Status = EFI_OUT_OF_RESOURCES;\r
399 goto Done;\r
400 }\r
401\r
402 //\r
403 // If caller didn't supply a handle, allocate a new one\r
404 //\r
405 Handle = (IHANDLE *)*UserHandle;\r
406 if (Handle == NULL) {\r
407 Handle = AllocateZeroPool (sizeof(IHANDLE));\r
408 if (Handle == NULL) {\r
409 Status = EFI_OUT_OF_RESOURCES;\r
410 goto Done;\r
411 }\r
412\r
413 //\r
414 // Initialize new handler structure\r
415 //\r
416 Handle->Signature = EFI_HANDLE_SIGNATURE;\r
417 InitializeListHead (&Handle->Protocols);\r
418\r
419 //\r
420 // Initialize the Key to show that the handle has been created/modified\r
421 //\r
422 gHandleDatabaseKey++;\r
423 Handle->Key = gHandleDatabaseKey;\r
424\r
425 //\r
426 // Add this handle to the list global list of all handles\r
427 // in the system\r
428 //\r
429 InsertTailList (&gHandleList, &Handle->AllHandles);\r
430 }\r
431\r
432 Status = CoreValidateHandle (Handle);\r
433 if (EFI_ERROR (Status)) {\r
434 goto Done;\r
435 }\r
436\r
437 //\r
438 // Each interface that is added must be unique\r
439 //\r
440 ASSERT (CoreFindProtocolInterface (Handle, Protocol, Interface) == NULL);\r
441\r
442 //\r
443 // Initialize the protocol interface structure\r
444 //\r
445 Prot->Signature = PROTOCOL_INTERFACE_SIGNATURE;\r
446 Prot->Handle = Handle;\r
447 Prot->Protocol = ProtEntry;\r
448 Prot->Interface = Interface;\r
449\r
450 //\r
451 // Initalize OpenProtocol Data base\r
452 //\r
453 InitializeListHead (&Prot->OpenList);\r
454 Prot->OpenListCount = 0;\r
455\r
456 //\r
457 // Add this protocol interface to the head of the supported\r
458 // protocol list for this handle\r
459 //\r
460 InsertHeadList (&Handle->Protocols, &Prot->Link);\r
461\r
462 //\r
463 // Add this protocol interface to the tail of the\r
464 // protocol entry\r
465 //\r
466 InsertTailList (&ProtEntry->Protocols, &Prot->ByProtocol);\r
467\r
468 //\r
469 // Notify the notification list for this protocol\r
470 //\r
471 if (Notify) {\r
472 CoreNotifyProtocolEntry (ProtEntry);\r
473 }\r
474 Status = EFI_SUCCESS;\r
475\r
476Done:\r
477 //\r
478 // Done, unlock the database and return\r
479 //\r
480 CoreReleaseProtocolLock ();\r
481 if (!EFI_ERROR (Status)) {\r
482 //\r
483 // Return the new handle back to the caller\r
484 //\r
485 *UserHandle = Handle;\r
486 } else {\r
487 //\r
488 // There was an error, clean up\r
489 //\r
490 if (Prot != NULL) {\r
491 CoreFreePool (Prot);\r
492 }\r
493 }\r
494\r
495 return Status;\r
496}\r
497\r
498\r
499\r
500\r
501/**\r
502 Installs a list of protocol interface into the boot services environment.\r
503 This function calls InstallProtocolInterface() in a loop. If any error\r
504 occures all the protocols added by this function are removed. This is\r
505 basically a lib function to save space.\r
506\r
507 @param Handle The handle to install the protocol handlers on,\r
508 or NULL if a new handle is to be allocated\r
509 @param ... EFI_GUID followed by protocol instance. A NULL\r
510 terminates the list. The pairs are the\r
511 arguments to InstallProtocolInterface(). All the\r
512 protocols are added to Handle.\r
513\r
514 @retval EFI_INVALID_PARAMETER Handle is NULL.\r
515 @retval EFI_SUCCESS Protocol interfaces successfully installed.\r
516\r
517**/\r
518EFI_STATUS\r
519EFIAPI\r
520CoreInstallMultipleProtocolInterfaces (\r
521 IN OUT EFI_HANDLE *Handle,\r
522 ...\r
523 )\r
524{\r
525 VA_LIST Args;\r
526 EFI_STATUS Status;\r
527 EFI_GUID *Protocol;\r
528 VOID *Interface;\r
529 EFI_TPL OldTpl;\r
530 UINTN Index;\r
531 EFI_HANDLE OldHandle;\r
532 EFI_HANDLE DeviceHandle;\r
533 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
534\r
535 if (Handle == NULL) {\r
536 return EFI_INVALID_PARAMETER;\r
537 }\r
538\r
539 //\r
540 // Syncronize with notifcations.\r
541 //\r
542 OldTpl = CoreRaiseTpl (TPL_NOTIFY);\r
543 OldHandle = *Handle;\r
544\r
545 //\r
546 // Check for duplicate device path and install the protocol interfaces\r
547 //\r
548 VA_START (Args, Handle);\r
549 for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) {\r
550 //\r
551 // If protocol is NULL, then it's the end of the list\r
552 //\r
553 Protocol = VA_ARG (Args, EFI_GUID *);\r
554 if (Protocol == NULL) {\r
555 break;\r
556 }\r
557\r
558 Interface = VA_ARG (Args, VOID *);\r
559\r
560 //\r
561 // Make sure you are installing on top a device path that has already been added.\r
562 //\r
563 if (CompareGuid (Protocol, &gEfiDevicePathProtocolGuid)) {\r
564 DeviceHandle = NULL;\r
565 DevicePath = Interface;\r
566 Status = CoreLocateDevicePath (&gEfiDevicePathProtocolGuid, &DevicePath, &DeviceHandle);\r
567 if (!EFI_ERROR (Status) && (DeviceHandle != NULL_HANDLE) && IsDevicePathEnd(DevicePath)) {\r
568 Status = EFI_ALREADY_STARTED;\r
569 continue;\r
570 }\r
571 }\r
572\r
573 //\r
574 // Install it\r
575 //\r
576 Status = CoreInstallProtocolInterface (Handle, Protocol, EFI_NATIVE_INTERFACE, Interface);\r
577 }\r
578\r
579 //\r
580 // If there was an error, remove all the interfaces that were installed without any errors\r
581 //\r
582 if (EFI_ERROR (Status)) {\r
583 //\r
584 // Reset the va_arg back to the first argument.\r
585 //\r
586 VA_START (Args, Handle);\r
587 for (; Index > 1; Index--) {\r
588 Protocol = VA_ARG (Args, EFI_GUID *);\r
589 Interface = VA_ARG (Args, VOID *);\r
590 CoreUninstallProtocolInterface (*Handle, Protocol, Interface);\r
591 }\r
592 *Handle = OldHandle;\r
593 }\r
594\r
595 //\r
596 // Done\r
597 //\r
598 CoreRestoreTpl (OldTpl);\r
599 return Status;\r
600}\r
601\r
602\r
603/**\r
604 Attempts to disconnect all drivers that are using the protocol interface being queried.\r
605 If failed, reconnect all drivers disconnected.\r
606 Note: This function doesn't do parameters checking, it's caller's responsibility\r
607 to pass in valid parameters.\r
608\r
609 @param UserHandle The handle on which the protocol is installed\r
610 @param Prot The protocol to disconnect drivers from\r
611\r
612 @retval EFI_SUCCESS Drivers using the protocol interface are all\r
613 disconnected\r
614 @retval EFI_ACCESS_DENIED Failed to disconnect one or all of the drivers\r
615\r
616**/\r
617EFI_STATUS\r
618CoreDisconnectControllersUsingProtocolInterface (\r
619 IN EFI_HANDLE UserHandle,\r
620 IN PROTOCOL_INTERFACE *Prot\r
621 )\r
622{\r
623 EFI_STATUS Status;\r
624 BOOLEAN ItemFound;\r
625 LIST_ENTRY *Link;\r
626 OPEN_PROTOCOL_DATA *OpenData;\r
627\r
628 Status = EFI_SUCCESS;\r
629\r
630 //\r
631 // Attempt to disconnect all drivers from this protocol interface\r
632 //\r
633 do {\r
634 ItemFound = FALSE;\r
635 for ( Link = Prot->OpenList.ForwardLink;\r
636 (Link != &Prot->OpenList) && !ItemFound;\r
637 Link = Link->ForwardLink ) {\r
638 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
639 if (OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) {\r
640 ItemFound = TRUE;\r
641 CoreReleaseProtocolLock ();\r
642 Status = CoreDisconnectController (UserHandle, OpenData->AgentHandle, NULL);\r
643 CoreAcquireProtocolLock ();\r
644 if (EFI_ERROR (Status)) {\r
645 ItemFound = FALSE;\r
646 break;\r
647 }\r
648 }\r
649 }\r
650 } while (ItemFound);\r
651\r
652 if (!EFI_ERROR (Status)) {\r
653 //\r
654 // Attempt to remove BY_HANDLE_PROTOOCL and GET_PROTOCOL and TEST_PROTOCOL Open List items\r
655 //\r
656 do {\r
657 ItemFound = FALSE;\r
658 for ( Link = Prot->OpenList.ForwardLink;\r
659 (Link != &Prot->OpenList) && !ItemFound;\r
660 Link = Link->ForwardLink ) {\r
661 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
662 if (OpenData->Attributes &\r
663 (EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL | EFI_OPEN_PROTOCOL_GET_PROTOCOL | EFI_OPEN_PROTOCOL_TEST_PROTOCOL)) {\r
664 ItemFound = TRUE;\r
665 RemoveEntryList (&OpenData->Link);\r
666 Prot->OpenListCount--;\r
667 CoreFreePool (OpenData);\r
668 }\r
669 }\r
670 } while (ItemFound);\r
671 }\r
672\r
673 //\r
674 // If there are errors or still has open items in the list, then reconnect all the drivers and return an error\r
675 //\r
676 if (EFI_ERROR (Status) || (Prot->OpenListCount > 0)) {\r
677 CoreReleaseProtocolLock ();\r
678 CoreConnectController (UserHandle, NULL, NULL, TRUE);\r
679 CoreAcquireProtocolLock ();\r
680 Status = EFI_ACCESS_DENIED;\r
681 }\r
682\r
683 return Status;\r
684}\r
685\r
686\r
687\r
688/**\r
689 Uninstalls all instances of a protocol:interfacer from a handle.\r
690 If the last protocol interface is remove from the handle, the\r
691 handle is freed.\r
692\r
693 @param UserHandle The handle to remove the protocol handler from\r
694 @param Protocol The protocol, of protocol:interface, to remove\r
695 @param Interface The interface, of protocol:interface, to remove\r
696\r
697 @retval EFI_INVALID_PARAMETER Protocol is NULL.\r
698 @retval EFI_SUCCESS Protocol interface successfully uninstalled.\r
699\r
700**/\r
701EFI_STATUS\r
702EFIAPI\r
703CoreUninstallProtocolInterface (\r
704 IN EFI_HANDLE UserHandle,\r
705 IN EFI_GUID *Protocol,\r
706 IN VOID *Interface\r
707 )\r
708{\r
709 EFI_STATUS Status;\r
710 IHANDLE *Handle;\r
711 PROTOCOL_INTERFACE *Prot;\r
712\r
713 //\r
714 // Check that Protocol is valid\r
715 //\r
716 if (Protocol == NULL) {\r
717 return EFI_INVALID_PARAMETER;\r
718 }\r
719\r
720 //\r
721 // Check that UserHandle is a valid handle\r
722 //\r
723 Status = CoreValidateHandle (UserHandle);\r
724 if (EFI_ERROR (Status)) {\r
725 return Status;\r
726 }\r
727\r
728 //\r
729 // Lock the protocol database\r
730 //\r
731 CoreAcquireProtocolLock ();\r
732\r
733 //\r
734 // Check that Protocol exists on UserHandle, and Interface matches the interface in the database\r
735 //\r
736 Prot = CoreFindProtocolInterface (UserHandle, Protocol, Interface);\r
737 if (Prot == NULL) {\r
738 Status = EFI_NOT_FOUND;\r
739 goto Done;\r
740 }\r
741\r
742 //\r
743 // Attempt to disconnect all drivers that are using the protocol interface that is about to be removed\r
744 //\r
745 Status = CoreDisconnectControllersUsingProtocolInterface (\r
746 UserHandle,\r
747 Prot\r
748 );\r
749 if (EFI_ERROR (Status)) {\r
750 //\r
751 // One or more drivers refused to release, so return the error\r
752 //\r
753 goto Done;\r
754 }\r
755\r
756 //\r
757 // Remove the protocol interface from the protocol\r
758 //\r
759 Status = EFI_NOT_FOUND;\r
760 Handle = (IHANDLE *)UserHandle;\r
761 Prot = CoreRemoveInterfaceFromProtocol (Handle, Protocol, Interface);\r
762\r
763 if (Prot != NULL) {\r
764 //\r
765 // Update the Key to show that the handle has been created/modified\r
766 //\r
767 gHandleDatabaseKey++;\r
768 Handle->Key = gHandleDatabaseKey;\r
769\r
770 //\r
771 // Remove the protocol interface from the handle\r
772 //\r
773 RemoveEntryList (&Prot->Link);\r
774\r
775 //\r
776 // Free the memory\r
777 //\r
778 Prot->Signature = 0;\r
779 CoreFreePool (Prot);\r
780 Status = EFI_SUCCESS;\r
781 }\r
782\r
783 //\r
784 // If there are no more handlers for the handle, free the handle\r
785 //\r
786 if (IsListEmpty (&Handle->Protocols)) {\r
787 Handle->Signature = 0;\r
788 RemoveEntryList (&Handle->AllHandles);\r
789 CoreFreePool (Handle);\r
790 }\r
791\r
792Done:\r
793 //\r
794 // Done, unlock the database and return\r
795 //\r
796 CoreReleaseProtocolLock ();\r
797 return Status;\r
798}\r
799\r
800\r
801\r
802\r
803/**\r
804 Uninstalls a list of protocol interface in the boot services environment.\r
805 This function calls UnisatllProtocolInterface() in a loop. This is\r
806 basically a lib function to save space.\r
807\r
808 @param Handle The handle to uninstall the protocol\r
809 @param ... EFI_GUID followed by protocol instance. A NULL\r
810 terminates the list. The pairs are the\r
811 arguments to UninstallProtocolInterface(). All\r
812 the protocols are added to Handle.\r
813\r
814 @return Status code\r
815\r
816**/\r
817EFI_STATUS\r
818EFIAPI\r
819CoreUninstallMultipleProtocolInterfaces (\r
820 IN EFI_HANDLE Handle,\r
821 ...\r
822 )\r
823{\r
824 EFI_STATUS Status;\r
825 VA_LIST Args;\r
826 EFI_GUID *Protocol;\r
827 VOID *Interface;\r
828 UINTN Index;\r
829\r
830 VA_START (Args, Handle);\r
831 for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) {\r
832 //\r
833 // If protocol is NULL, then it's the end of the list\r
834 //\r
835 Protocol = VA_ARG (Args, EFI_GUID *);\r
836 if (Protocol == NULL) {\r
837 break;\r
838 }\r
839\r
840 Interface = VA_ARG (Args, VOID *);\r
841\r
842 //\r
843 // Uninstall it\r
844 //\r
845 Status = CoreUninstallProtocolInterface (Handle, Protocol, Interface);\r
846 }\r
847\r
848 //\r
849 // If there was an error, add all the interfaces that were\r
850 // uninstalled without any errors\r
851 //\r
852 if (EFI_ERROR (Status)) {\r
853 //\r
854 // Reset the va_arg back to the first argument.\r
855 //\r
856 VA_START (Args, Handle);\r
857 for (; Index > 1; Index--) {\r
858 Protocol = VA_ARG(Args, EFI_GUID *);\r
859 Interface = VA_ARG(Args, VOID *);\r
860 CoreInstallProtocolInterface (&Handle, Protocol, EFI_NATIVE_INTERFACE, Interface);\r
861 }\r
862 }\r
863\r
864 return Status;\r
865}\r
866\r
867\r
868/**\r
869 Locate a certain GUID protocol interface in a Handle's protocols.\r
870\r
871 @param UserHandle The handle to obtain the protocol interface on\r
872 @param Protocol The GUID of the protocol\r
873\r
874 @return The requested protocol interface for the handle\r
875\r
876**/\r
877PROTOCOL_INTERFACE *\r
878CoreGetProtocolInterface (\r
879 IN EFI_HANDLE UserHandle,\r
880 IN EFI_GUID *Protocol\r
881 )\r
882{\r
883 EFI_STATUS Status;\r
884 PROTOCOL_ENTRY *ProtEntry;\r
885 PROTOCOL_INTERFACE *Prot;\r
886 IHANDLE *Handle;\r
887 LIST_ENTRY *Link;\r
888\r
889 Status = CoreValidateHandle (UserHandle);\r
890 if (EFI_ERROR (Status)) {\r
891 return NULL;\r
892 }\r
893\r
894 Handle = (IHANDLE *)UserHandle;\r
895\r
896 //\r
897 // Look at each protocol interface for a match\r
898 //\r
899 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {\r
900 Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);\r
901 ProtEntry = Prot->Protocol;\r
902 if (CompareGuid (&ProtEntry->ProtocolID, Protocol)) {\r
903 return Prot;\r
904 }\r
905 }\r
906 return NULL;\r
907}\r
908\r
909\r
910\r
911/**\r
912 Queries a handle to determine if it supports a specified protocol.\r
913\r
914 @param UserHandle The handle being queried.\r
915 @param Protocol The published unique identifier of the protocol.\r
916 @param Interface Supplies the address where a pointer to the\r
917 corresponding Protocol Interface is returned.\r
918\r
919 @return The requested protocol interface for the handle\r
920\r
921**/\r
922EFI_STATUS\r
923EFIAPI\r
924CoreHandleProtocol (\r
925 IN EFI_HANDLE UserHandle,\r
926 IN EFI_GUID *Protocol,\r
927 OUT VOID **Interface\r
928 )\r
929{\r
930 return CoreOpenProtocol (\r
931 UserHandle,\r
932 Protocol,\r
933 Interface,\r
934 gDxeCoreImageHandle,\r
935 NULL,\r
936 EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL\r
937 );\r
938}\r
939\r
940\r
941\r
942/**\r
943 Locates the installed protocol handler for the handle, and\r
944 invokes it to obtain the protocol interface. Usage information\r
945 is registered in the protocol data base.\r
946\r
947 @param UserHandle The handle to obtain the protocol interface on\r
948 @param Protocol The ID of the protocol\r
949 @param Interface The location to return the protocol interface\r
950 @param ImageHandle The handle of the Image that is opening the\r
951 protocol interface specified by Protocol and\r
952 Interface.\r
953 @param ControllerHandle The controller handle that is requiring this\r
954 interface.\r
955 @param Attributes The open mode of the protocol interface\r
956 specified by Handle and Protocol.\r
957\r
958 @retval EFI_INVALID_PARAMETER Protocol is NULL.\r
959 @retval EFI_SUCCESS Get the protocol interface.\r
960\r
961**/\r
962EFI_STATUS\r
963EFIAPI\r
964CoreOpenProtocol (\r
965 IN EFI_HANDLE UserHandle,\r
966 IN EFI_GUID *Protocol,\r
967 OUT VOID **Interface OPTIONAL,\r
968 IN EFI_HANDLE ImageHandle,\r
969 IN EFI_HANDLE ControllerHandle,\r
970 IN UINT32 Attributes\r
971 )\r
972{\r
973 EFI_STATUS Status;\r
974 PROTOCOL_INTERFACE *Prot;\r
975 LIST_ENTRY *Link;\r
976 OPEN_PROTOCOL_DATA *OpenData;\r
977 BOOLEAN ByDriver;\r
978 BOOLEAN Exclusive;\r
979 BOOLEAN Disconnect;\r
980 BOOLEAN ExactMatch;\r
981\r
982 //\r
983 // Check for invalid Protocol\r
984 //\r
985 if (Protocol == NULL) {\r
986 return EFI_INVALID_PARAMETER;\r
987 }\r
988\r
989 //\r
990 // Check for invalid Interface\r
991 //\r
992 if (Attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL) {\r
993 if (Interface == NULL) {\r
994 return EFI_INVALID_PARAMETER;\r
995 } else {\r
996 *Interface = NULL;\r
997 }\r
998 }\r
999\r
1000 //\r
1001 // Check for invalid UserHandle\r
1002 //\r
1003 Status = CoreValidateHandle (UserHandle);\r
1004 if (EFI_ERROR (Status)) {\r
1005 return Status;\r
1006 }\r
1007\r
1008 //\r
1009 // Check for invalid Attributes\r
1010 //\r
1011 switch (Attributes) {\r
1012 case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER :\r
1013 Status = CoreValidateHandle (ImageHandle);\r
1014 if (EFI_ERROR (Status)) {\r
1015 return Status;\r
1016 }\r
1017 Status = CoreValidateHandle (ControllerHandle);\r
1018 if (EFI_ERROR (Status)) {\r
1019 return Status;\r
1020 }\r
1021 if (UserHandle == ControllerHandle) {\r
1022 return EFI_INVALID_PARAMETER;\r
1023 }\r
1024 break;\r
1025 case EFI_OPEN_PROTOCOL_BY_DRIVER :\r
1026 case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE :\r
1027 Status = CoreValidateHandle (ImageHandle);\r
1028 if (EFI_ERROR (Status)) {\r
1029 return Status;\r
1030 }\r
1031 Status = CoreValidateHandle (ControllerHandle);\r
1032 if (EFI_ERROR (Status)) {\r
1033 return Status;\r
1034 }\r
1035 break;\r
1036 case EFI_OPEN_PROTOCOL_EXCLUSIVE :\r
1037 Status = CoreValidateHandle (ImageHandle);\r
1038 if (EFI_ERROR (Status)) {\r
1039 return Status;\r
1040 }\r
1041 break;\r
1042 case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL :\r
1043 case EFI_OPEN_PROTOCOL_GET_PROTOCOL :\r
1044 case EFI_OPEN_PROTOCOL_TEST_PROTOCOL :\r
1045 break;\r
1046 default:\r
1047 return EFI_INVALID_PARAMETER;\r
1048 }\r
1049\r
1050 //\r
1051 // Lock the protocol database\r
1052 //\r
1053 CoreAcquireProtocolLock ();\r
1054\r
1055 //\r
1056 // Look at each protocol interface for a match\r
1057 //\r
1058 Prot = CoreGetProtocolInterface (UserHandle, Protocol);\r
1059 if (Prot == NULL) {\r
1060 Status = EFI_UNSUPPORTED;\r
1061 goto Done;\r
1062 }\r
1063\r
1064 //\r
1065 // This is the protocol interface entry for this protocol\r
1066 //\r
1067 if (Attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL) {\r
1068 *Interface = Prot->Interface;\r
1069 }\r
1070 Status = EFI_SUCCESS;\r
1071\r
1072 ByDriver = FALSE;\r
1073 Exclusive = FALSE;\r
1074 for ( Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList; Link = Link->ForwardLink) {\r
1075 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
1076 ExactMatch = (BOOLEAN)((OpenData->AgentHandle == ImageHandle) &&\r
1077 (OpenData->Attributes == Attributes) &&\r
1078 (OpenData->ControllerHandle == ControllerHandle));\r
1079 if (OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) {\r
1080 ByDriver = TRUE;\r
1081 if (ExactMatch) {\r
1082 Status = EFI_ALREADY_STARTED;\r
1083 goto Done;\r
1084 }\r
1085 }\r
1086 if (OpenData->Attributes & EFI_OPEN_PROTOCOL_EXCLUSIVE) {\r
1087 Exclusive = TRUE;\r
1088 } else if (ExactMatch) {\r
1089 OpenData->OpenCount++;\r
1090 Status = EFI_SUCCESS;\r
1091 goto Done;\r
1092 }\r
1093 }\r
1094\r
1095 //\r
1096 // ByDriver TRUE -> A driver is managing (UserHandle, Protocol)\r
1097 // ByDriver FALSE -> There are no drivers managing (UserHandle, Protocol)\r
1098 // Exclusive TRUE -> Something has exclusive access to (UserHandle, Protocol)\r
1099 // Exclusive FALSE -> Nothing has exclusive access to (UserHandle, Protocol)\r
1100 //\r
1101\r
1102 switch (Attributes) {\r
1103 case EFI_OPEN_PROTOCOL_BY_DRIVER :\r
1104 if (Exclusive || ByDriver) {\r
1105 Status = EFI_ACCESS_DENIED;\r
1106 goto Done;\r
1107 }\r
1108 break;\r
1109 case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE :\r
1110 case EFI_OPEN_PROTOCOL_EXCLUSIVE :\r
1111 if (Exclusive) {\r
1112 Status = EFI_ACCESS_DENIED;\r
1113 goto Done;\r
1114 }\r
1115 if (ByDriver) {\r
1116 do {\r
1117 Disconnect = FALSE;\r
1118 for ( Link = Prot->OpenList.ForwardLink; (Link != &Prot->OpenList) && (!Disconnect); Link = Link->ForwardLink) {\r
1119 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
1120 if (OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) {\r
1121 Disconnect = TRUE;\r
1122 CoreReleaseProtocolLock ();\r
1123 Status = CoreDisconnectController (UserHandle, OpenData->AgentHandle, NULL);\r
1124 CoreAcquireProtocolLock ();\r
1125 if (EFI_ERROR (Status)) {\r
1126 Status = EFI_ACCESS_DENIED;\r
1127 goto Done;\r
1128 }\r
1129 }\r
1130 }\r
1131 } while (Disconnect);\r
1132 }\r
1133 break;\r
1134 case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER :\r
1135 case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL :\r
1136 case EFI_OPEN_PROTOCOL_GET_PROTOCOL :\r
1137 case EFI_OPEN_PROTOCOL_TEST_PROTOCOL :\r
1138 break;\r
1139 }\r
1140\r
1141 if (ImageHandle == NULL) {\r
1142 Status = EFI_SUCCESS;\r
1143 goto Done;\r
1144 }\r
1145 //\r
1146 // Create new entry\r
1147 //\r
1148 OpenData = AllocatePool (sizeof(OPEN_PROTOCOL_DATA));\r
1149 if (OpenData == NULL) {\r
1150 Status = EFI_OUT_OF_RESOURCES;\r
1151 } else {\r
1152 OpenData->Signature = OPEN_PROTOCOL_DATA_SIGNATURE;\r
1153 OpenData->AgentHandle = ImageHandle;\r
1154 OpenData->ControllerHandle = ControllerHandle;\r
1155 OpenData->Attributes = Attributes;\r
1156 OpenData->OpenCount = 1;\r
1157 InsertTailList (&Prot->OpenList, &OpenData->Link);\r
1158 Prot->OpenListCount++;\r
1159 Status = EFI_SUCCESS;\r
1160 }\r
1161\r
1162Done:\r
1163 //\r
1164 // Done. Release the database lock are return\r
1165 //\r
1166 CoreReleaseProtocolLock ();\r
1167 return Status;\r
1168}\r
1169\r
1170\r
1171\r
1172/**\r
1173 Closes a protocol on a handle that was opened using OpenProtocol().\r
1174\r
1175 @param UserHandle The handle for the protocol interface that was\r
1176 previously opened with OpenProtocol(), and is\r
1177 now being closed.\r
1178 @param Protocol The published unique identifier of the protocol.\r
1179 It is the caller's responsibility to pass in a\r
1180 valid GUID.\r
1181 @param AgentHandle The handle of the agent that is closing the\r
1182 protocol interface.\r
1183 @param ControllerHandle If the agent that opened a protocol is a driver\r
1184 that follows the EFI Driver Model, then this\r
1185 parameter is the controller handle that required\r
1186 the protocol interface. If the agent does not\r
1187 follow the EFI Driver Model, then this parameter\r
1188 is optional and may be NULL.\r
1189\r
1190 @retval EFI_SUCCESS The protocol instance was closed.\r
1191 @retval EFI_INVALID_PARAMETER Handle, AgentHandle or ControllerHandle is not a\r
1192 valid EFI_HANDLE.\r
1193 @retval EFI_NOT_FOUND Can not find the specified protocol or\r
1194 AgentHandle.\r
1195\r
1196**/\r
1197EFI_STATUS\r
1198EFIAPI\r
1199CoreCloseProtocol (\r
1200 IN EFI_HANDLE UserHandle,\r
1201 IN EFI_GUID *Protocol,\r
1202 IN EFI_HANDLE AgentHandle,\r
1203 IN EFI_HANDLE ControllerHandle\r
1204 )\r
1205{\r
1206 EFI_STATUS Status;\r
1207 PROTOCOL_INTERFACE *ProtocolInterface;\r
1208 LIST_ENTRY *Link;\r
1209 OPEN_PROTOCOL_DATA *OpenData;\r
1210\r
1211 //\r
1212 // Check for invalid parameters\r
1213 //\r
1214 Status = CoreValidateHandle (UserHandle);\r
1215 if (EFI_ERROR (Status)) {\r
1216 return Status;\r
1217 }\r
1218 Status = CoreValidateHandle (AgentHandle);\r
1219 if (EFI_ERROR (Status)) {\r
1220 return Status;\r
1221 }\r
1222 if (ControllerHandle != NULL_HANDLE) {\r
1223 Status = CoreValidateHandle (ControllerHandle);\r
1224 if (EFI_ERROR (Status)) {\r
1225 return Status;\r
1226 }\r
1227 }\r
1228 if (Protocol == NULL) {\r
1229 return EFI_INVALID_PARAMETER;\r
1230 }\r
1231\r
1232 //\r
1233 // Lock the protocol database\r
1234 //\r
1235 CoreAcquireProtocolLock ();\r
1236\r
1237 //\r
1238 // Look at each protocol interface for a match\r
1239 //\r
1240 Status = EFI_NOT_FOUND;\r
1241 ProtocolInterface = CoreGetProtocolInterface (UserHandle, Protocol);\r
1242 if (ProtocolInterface == NULL) {\r
1243 goto Done;\r
1244 }\r
1245\r
1246 //\r
1247 // Walk the Open data base looking for AgentHandle\r
1248 //\r
1249 Link = ProtocolInterface->OpenList.ForwardLink;\r
1250 while (Link != &ProtocolInterface->OpenList) {\r
1251 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
1252 Link = Link->ForwardLink;\r
1253 if ((OpenData->AgentHandle == AgentHandle) && (OpenData->ControllerHandle == ControllerHandle)) {\r
1254 RemoveEntryList (&OpenData->Link);\r
1255 ProtocolInterface->OpenListCount--;\r
1256 CoreFreePool (OpenData);\r
1257 Status = EFI_SUCCESS;\r
1258 }\r
1259 }\r
1260\r
1261Done:\r
1262 //\r
1263 // Done. Release the database lock and return.\r
1264 //\r
1265 CoreReleaseProtocolLock ();\r
1266 return Status;\r
1267}\r
1268\r
1269\r
1270\r
1271\r
1272/**\r
1273 Return information about Opened protocols in the system\r
1274\r
1275 @param UserHandle The handle to close the protocol interface on\r
1276 @param Protocol The ID of the protocol\r
1277 @param EntryBuffer A pointer to a buffer of open protocol\r
1278 information in the form of\r
1279 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY structures.\r
1280 @param EntryCount Number of EntryBuffer entries\r
1281\r
1282**/\r
1283EFI_STATUS\r
1284EFIAPI\r
1285CoreOpenProtocolInformation (\r
1286 IN EFI_HANDLE UserHandle,\r
1287 IN EFI_GUID *Protocol,\r
1288 OUT EFI_OPEN_PROTOCOL_INFORMATION_ENTRY **EntryBuffer,\r
1289 OUT UINTN *EntryCount\r
1290 )\r
1291{\r
1292 EFI_STATUS Status;\r
1293 PROTOCOL_INTERFACE *ProtocolInterface;\r
1294 LIST_ENTRY *Link;\r
1295 OPEN_PROTOCOL_DATA *OpenData;\r
1296 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *Buffer;\r
1297 UINTN Count;\r
1298 UINTN Size;\r
1299\r
1300 *EntryBuffer = NULL;\r
1301 *EntryCount = 0;\r
1302\r
1303 //\r
1304 // Lock the protocol database\r
1305 //\r
1306 CoreAcquireProtocolLock ();\r
1307\r
1308 //\r
1309 // Look at each protocol interface for a match\r
1310 //\r
1311 Status = EFI_NOT_FOUND;\r
1312 ProtocolInterface = CoreGetProtocolInterface (UserHandle, Protocol);\r
1313 if (ProtocolInterface == NULL) {\r
1314 goto Done;\r
1315 }\r
1316\r
1317 //\r
1318 // Count the number of Open Entries\r
1319 //\r
1320 for ( Link = ProtocolInterface->OpenList.ForwardLink, Count = 0;\r
1321 (Link != &ProtocolInterface->OpenList) ;\r
1322 Link = Link->ForwardLink ) {\r
1323 Count++;\r
1324 }\r
1325\r
1326 ASSERT (Count == ProtocolInterface->OpenListCount);\r
1327\r
1328 if (Count == 0) {\r
1329 Size = sizeof(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY);\r
1330 } else {\r
1331 Size = Count * sizeof(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY);\r
1332 }\r
1333\r
1334 Buffer = AllocatePool (Size);\r
1335 if (Buffer == NULL) {\r
1336 Status = EFI_OUT_OF_RESOURCES;\r
1337 goto Done;\r
1338 }\r
1339\r
1340 Status = EFI_SUCCESS;\r
1341 for ( Link = ProtocolInterface->OpenList.ForwardLink, Count = 0;\r
1342 (Link != &ProtocolInterface->OpenList);\r
1343 Link = Link->ForwardLink, Count++ ) {\r
1344 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
1345\r
1346 Buffer[Count].AgentHandle = OpenData->AgentHandle;\r
1347 Buffer[Count].ControllerHandle = OpenData->ControllerHandle;\r
1348 Buffer[Count].Attributes = OpenData->Attributes;\r
1349 Buffer[Count].OpenCount = OpenData->OpenCount;\r
1350 }\r
1351\r
1352 *EntryBuffer = Buffer;\r
1353 *EntryCount = Count;\r
1354\r
1355Done:\r
1356 //\r
1357 // Done. Release the database lock.\r
1358 //\r
1359 CoreReleaseProtocolLock ();\r
1360 return Status;\r
1361}\r
1362\r
1363\r
1364\r
1365\r
1366/**\r
1367 Retrieves the list of protocol interface GUIDs that are installed on a handle in a buffer allocated\r
1368 from pool.\r
1369\r
1370 @param UserHandle The handle from which to retrieve the list of\r
1371 protocol interface GUIDs.\r
1372 @param ProtocolBuffer A pointer to the list of protocol interface GUID\r
1373 pointers that are installed on Handle.\r
1374 @param ProtocolBufferCount A pointer to the number of GUID pointers present\r
1375 in ProtocolBuffer.\r
1376\r
1377 @retval EFI_SUCCESS The list of protocol interface GUIDs installed\r
1378 on Handle was returned in ProtocolBuffer. The\r
1379 number of protocol interface GUIDs was returned\r
1380 in ProtocolBufferCount.\r
1381 @retval EFI_INVALID_PARAMETER Handle is NULL.\r
1382 @retval EFI_INVALID_PARAMETER Handle is not a valid EFI_HANDLE.\r
1383 @retval EFI_INVALID_PARAMETER ProtocolBuffer is NULL.\r
1384 @retval EFI_INVALID_PARAMETER ProtocolBufferCount is NULL.\r
1385 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the\r
1386 results.\r
1387\r
1388**/\r
1389EFI_STATUS\r
1390EFIAPI\r
1391CoreProtocolsPerHandle (\r
1392 IN EFI_HANDLE UserHandle,\r
1393 OUT EFI_GUID ***ProtocolBuffer,\r
1394 OUT UINTN *ProtocolBufferCount\r
1395 )\r
1396{\r
1397 EFI_STATUS Status;\r
1398 IHANDLE *Handle;\r
1399 PROTOCOL_INTERFACE *Prot;\r
1400 LIST_ENTRY *Link;\r
1401 UINTN ProtocolCount;\r
1402 EFI_GUID **Buffer;\r
1403\r
1404 Status = CoreValidateHandle (UserHandle);\r
1405 if (EFI_ERROR (Status)) {\r
1406 return Status;\r
1407 }\r
1408\r
1409 Handle = (IHANDLE *)UserHandle;\r
1410\r
1411 if (ProtocolBuffer == NULL) {\r
1412 return EFI_INVALID_PARAMETER;\r
1413 }\r
1414\r
1415 if (ProtocolBufferCount == NULL) {\r
1416 return EFI_INVALID_PARAMETER;\r
1417 }\r
1418\r
1419 *ProtocolBufferCount = 0;\r
1420\r
1421 ProtocolCount = 0;\r
1422\r
1423 CoreAcquireProtocolLock ();\r
1424\r
1425 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {\r
1426 ProtocolCount++;\r
1427 }\r
1428\r
1429 //\r
1430 // If there are no protocol interfaces installed on Handle, then Handle is not a valid EFI_HANDLE\r
1431 //\r
1432 if (ProtocolCount == 0) {\r
1433 Status = EFI_INVALID_PARAMETER;\r
1434 goto Done;\r
1435 }\r
1436\r
1437 Buffer = AllocatePool (sizeof (EFI_GUID *) * ProtocolCount);\r
1438 if (Buffer == NULL) {\r
1439 Status = EFI_OUT_OF_RESOURCES;\r
1440 goto Done;\r
1441 }\r
1442\r
1443 *ProtocolBuffer = Buffer;\r
1444 *ProtocolBufferCount = ProtocolCount;\r
1445\r
1446 for ( Link = Handle->Protocols.ForwardLink, ProtocolCount = 0;\r
1447 Link != &Handle->Protocols;\r
1448 Link = Link->ForwardLink, ProtocolCount++) {\r
1449 Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);\r
1450 Buffer[ProtocolCount] = &(Prot->Protocol->ProtocolID);\r
1451 }\r
1452 Status = EFI_SUCCESS;\r
1453\r
1454Done:\r
1455 CoreReleaseProtocolLock ();\r
1456 return Status;\r
1457}\r
1458\r
1459\r
1460\r
1461/**\r
1462 return handle database key.\r
1463\r
1464\r
1465 @return Handle database key.\r
1466\r
1467**/\r
1468UINT64\r
1469CoreGetHandleDatabaseKey (\r
1470 VOID\r
1471 )\r
1472{\r
1473 return gHandleDatabaseKey;\r
1474}\r
1475\r
1476\r
1477\r
1478/**\r
1479 Go connect any handles that were created or modified while a image executed.\r
1480\r
1481 @param Key The Key to show that the handle has been\r
1482 created/modified\r
1483\r
1484**/\r
1485VOID\r
1486CoreConnectHandlesByKey (\r
1487 UINT64 Key\r
1488 )\r
1489{\r
1490 UINTN Count;\r
1491 LIST_ENTRY *Link;\r
1492 EFI_HANDLE *HandleBuffer;\r
1493 IHANDLE *Handle;\r
1494 UINTN Index;\r
1495\r
1496 //\r
1497 // Lock the protocol database\r
1498 //\r
1499 CoreAcquireProtocolLock ();\r
1500\r
1501 for (Link = gHandleList.ForwardLink, Count = 0; Link != &gHandleList; Link = Link->ForwardLink) {\r
1502 Handle = CR (Link, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);\r
1503 if (Handle->Key > Key) {\r
1504 Count++;\r
1505 }\r
1506 }\r
1507\r
1508 HandleBuffer = AllocatePool (Count * sizeof (EFI_HANDLE));\r
1509 if (HandleBuffer == NULL) {\r
1510 CoreReleaseProtocolLock ();\r
1511 return;\r
1512 }\r
1513\r
1514 for (Link = gHandleList.ForwardLink, Count = 0; Link != &gHandleList; Link = Link->ForwardLink) {\r
1515 Handle = CR (Link, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);\r
1516 if (Handle->Key > Key) {\r
1517 HandleBuffer[Count++] = Handle;\r
1518 }\r
1519 }\r
1520\r
1521 //\r
1522 // Unlock the protocol database\r
1523 //\r
1524 CoreReleaseProtocolLock ();\r
1525\r
1526 //\r
1527 // Connect all handles whose Key value is greater than Key\r
1528 //\r
1529 for (Index = 0; Index < Count; Index++) {\r
1530 CoreConnectController (HandleBuffer[Index], NULL, NULL, TRUE);\r
1531 }\r
1532\r
1533 CoreFreePool(HandleBuffer);\r
1534}\r