2 UEFI handle & protocol handling.
4 Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
20 // mProtocolDatabase - A list of all protocols in the system. (simple list for now)
21 // gHandleList - A list of all the handles in the system
22 // gProtocolDatabaseLock - Lock to protect the mProtocolDatabase
23 // gHandleDatabaseKey - The Key to show that the handle has been created/modified
25 LIST_ENTRY mProtocolDatabase
= INITIALIZE_LIST_HEAD_VARIABLE (mProtocolDatabase
);
26 LIST_ENTRY gHandleList
= INITIALIZE_LIST_HEAD_VARIABLE (gHandleList
);
27 EFI_LOCK gProtocolDatabaseLock
= EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY
);
28 UINT64 gHandleDatabaseKey
= 0;
33 Acquire lock on gProtocolDatabaseLock.
37 CoreAcquireProtocolLock (
41 CoreAcquireLock (&gProtocolDatabaseLock
);
47 Release lock on gProtocolDatabaseLock.
51 CoreReleaseProtocolLock (
55 CoreReleaseLock (&gProtocolDatabaseLock
);
61 Check whether a handle is a valid EFI_HANDLE
63 @param UserHandle The handle to check
65 @retval EFI_INVALID_PARAMETER The handle is NULL or not a valid EFI_HANDLE.
66 @retval EFI_SUCCESS The handle is valid EFI_HANDLE.
71 IN EFI_HANDLE UserHandle
76 Handle
= (IHANDLE
*)UserHandle
;
78 return EFI_INVALID_PARAMETER
;
80 if (Handle
->Signature
!= EFI_HANDLE_SIGNATURE
) {
81 return EFI_INVALID_PARAMETER
;
89 Finds the protocol entry for the requested protocol.
90 The gProtocolDatabaseLock must be owned
92 @param Protocol The ID of the protocol
93 @param Create Create a new entry if not found
95 @return Protocol entry
99 CoreFindProtocolEntry (
100 IN EFI_GUID
*Protocol
,
105 PROTOCOL_ENTRY
*Item
;
106 PROTOCOL_ENTRY
*ProtEntry
;
108 ASSERT_LOCKED(&gProtocolDatabaseLock
);
111 // Search the database for the matching GUID
115 for (Link
= mProtocolDatabase
.ForwardLink
;
116 Link
!= &mProtocolDatabase
;
117 Link
= Link
->ForwardLink
) {
119 Item
= CR(Link
, PROTOCOL_ENTRY
, AllEntries
, PROTOCOL_ENTRY_SIGNATURE
);
120 if (CompareGuid (&Item
->ProtocolID
, Protocol
)) {
123 // This is the protocol entry
132 // If the protocol entry was not found and Create is TRUE, then
133 // allocate a new entry
135 if ((ProtEntry
== NULL
) && Create
) {
136 ProtEntry
= AllocatePool (sizeof(PROTOCOL_ENTRY
));
138 if (ProtEntry
!= NULL
) {
140 // Initialize new protocol entry structure
142 ProtEntry
->Signature
= PROTOCOL_ENTRY_SIGNATURE
;
143 CopyGuid ((VOID
*)&ProtEntry
->ProtocolID
, Protocol
);
144 InitializeListHead (&ProtEntry
->Protocols
);
145 InitializeListHead (&ProtEntry
->Notify
);
148 // Add it to protocol database
150 InsertTailList (&mProtocolDatabase
, &ProtEntry
->AllEntries
);
160 Finds the protocol instance for the requested handle and protocol.
161 Note: This function doesn't do parameters checking, it's caller's responsibility
162 to pass in valid parameters.
164 @param Handle The handle to search the protocol on
165 @param Protocol GUID of the protocol
166 @param Interface The interface for the protocol being searched
168 @return Protocol instance (NULL: Not found)
172 CoreFindProtocolInterface (
174 IN EFI_GUID
*Protocol
,
178 PROTOCOL_INTERFACE
*Prot
;
179 PROTOCOL_ENTRY
*ProtEntry
;
182 ASSERT_LOCKED(&gProtocolDatabaseLock
);
186 // Lookup the protocol entry for this protocol ID
189 ProtEntry
= CoreFindProtocolEntry (Protocol
, FALSE
);
190 if (ProtEntry
!= NULL
) {
193 // Look at each protocol interface for any matches
195 for (Link
= Handle
->Protocols
.ForwardLink
; Link
!= &Handle
->Protocols
; Link
=Link
->ForwardLink
) {
198 // If this protocol interface matches, remove it
200 Prot
= CR(Link
, PROTOCOL_INTERFACE
, Link
, PROTOCOL_INTERFACE_SIGNATURE
);
201 if (Prot
->Interface
== Interface
&& Prot
->Protocol
== ProtEntry
) {
214 Removes an event from a register protocol notify list on a protocol.
216 @param Event The event to search for in the protocol
219 @return EFI_SUCCESS if the event was found and removed.
220 @return EFI_NOT_FOUND if the event was not found in the protocl database.
224 CoreUnregisterProtocolNotifyEvent (
229 PROTOCOL_ENTRY
*ProtEntry
;
230 LIST_ENTRY
*NotifyLink
;
231 PROTOCOL_NOTIFY
*ProtNotify
;
233 CoreAcquireProtocolLock ();
235 for ( Link
= mProtocolDatabase
.ForwardLink
;
236 Link
!= &mProtocolDatabase
;
237 Link
= Link
->ForwardLink
) {
239 ProtEntry
= CR(Link
, PROTOCOL_ENTRY
, AllEntries
, PROTOCOL_ENTRY_SIGNATURE
);
241 for ( NotifyLink
= ProtEntry
->Notify
.ForwardLink
;
242 NotifyLink
!= &ProtEntry
->Notify
;
243 NotifyLink
= NotifyLink
->ForwardLink
) {
245 ProtNotify
= CR(NotifyLink
, PROTOCOL_NOTIFY
, Link
, PROTOCOL_NOTIFY_SIGNATURE
);
247 if (ProtNotify
->Event
== Event
) {
248 RemoveEntryList(&ProtNotify
->Link
);
249 CoreFreePool(ProtNotify
);
250 CoreReleaseProtocolLock ();
256 CoreReleaseProtocolLock ();
257 return EFI_NOT_FOUND
;
263 Removes all the events in the protocol database that match Event.
265 @param Event The event to search for in the protocol
268 @return EFI_SUCCESS when done searching the entire database.
272 CoreUnregisterProtocolNotify (
279 Status
= CoreUnregisterProtocolNotifyEvent (Event
);
280 } while (!EFI_ERROR (Status
));
289 Wrapper function to CoreInstallProtocolInterfaceNotify. This is the public API which
290 Calls the private one which contains a BOOLEAN parameter for notifications
292 @param UserHandle The handle to install the protocol handler on,
293 or NULL if a new handle is to be allocated
294 @param Protocol The protocol to add to the handle
295 @param InterfaceType Indicates whether Interface is supplied in
297 @param Interface The interface for the protocol being added
304 CoreInstallProtocolInterface (
305 IN OUT EFI_HANDLE
*UserHandle
,
306 IN EFI_GUID
*Protocol
,
307 IN EFI_INTERFACE_TYPE InterfaceType
,
311 return CoreInstallProtocolInterfaceNotify (
322 Installs a protocol interface into the boot services environment.
324 @param UserHandle The handle to install the protocol handler on,
325 or NULL if a new handle is to be allocated
326 @param Protocol The protocol to add to the handle
327 @param InterfaceType Indicates whether Interface is supplied in
329 @param Interface The interface for the protocol being added
330 @param Notify indicates whether notify the notification list
333 @retval EFI_INVALID_PARAMETER Invalid parameter
334 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
335 @retval EFI_SUCCESS Protocol interface successfully installed
339 CoreInstallProtocolInterfaceNotify (
340 IN OUT EFI_HANDLE
*UserHandle
,
341 IN EFI_GUID
*Protocol
,
342 IN EFI_INTERFACE_TYPE InterfaceType
,
347 PROTOCOL_INTERFACE
*Prot
;
348 PROTOCOL_ENTRY
*ProtEntry
;
351 VOID
*ExistingInterface
;
354 // returns EFI_INVALID_PARAMETER if InterfaceType is invalid.
355 // Also added check for invalid UserHandle and Protocol pointers.
357 if (UserHandle
== NULL
|| Protocol
== NULL
) {
358 return EFI_INVALID_PARAMETER
;
361 if (InterfaceType
!= EFI_NATIVE_INTERFACE
) {
362 return EFI_INVALID_PARAMETER
;
366 // Print debug message
368 DEBUG((DEBUG_INFO
, "InstallProtocolInterface: %g %p\n", Protocol
, Interface
));
370 Status
= EFI_OUT_OF_RESOURCES
;
374 if (*UserHandle
!= NULL
) {
375 Status
= CoreHandleProtocol (*UserHandle
, Protocol
, (VOID
**)&ExistingInterface
);
376 if (!EFI_ERROR (Status
)) {
377 return EFI_INVALID_PARAMETER
;
382 // Lock the protocol database
384 CoreAcquireProtocolLock ();
387 // Lookup the Protocol Entry for the requested protocol
389 ProtEntry
= CoreFindProtocolEntry (Protocol
, TRUE
);
390 if (ProtEntry
== NULL
) {
395 // Allocate a new protocol interface structure
397 Prot
= AllocateZeroPool (sizeof(PROTOCOL_INTERFACE
));
399 Status
= EFI_OUT_OF_RESOURCES
;
404 // If caller didn't supply a handle, allocate a new one
406 Handle
= (IHANDLE
*)*UserHandle
;
407 if (Handle
== NULL
) {
408 Handle
= AllocateZeroPool (sizeof(IHANDLE
));
409 if (Handle
== NULL
) {
410 Status
= EFI_OUT_OF_RESOURCES
;
415 // Initialize new handler structure
417 Handle
->Signature
= EFI_HANDLE_SIGNATURE
;
418 InitializeListHead (&Handle
->Protocols
);
421 // Initialize the Key to show that the handle has been created/modified
423 gHandleDatabaseKey
++;
424 Handle
->Key
= gHandleDatabaseKey
;
427 // Add this handle to the list global list of all handles
430 InsertTailList (&gHandleList
, &Handle
->AllHandles
);
432 Status
= CoreValidateHandle (Handle
);
433 if (EFI_ERROR (Status
)) {
434 DEBUG((DEBUG_ERROR
, "InstallProtocolInterface: input handle at 0x%x is invalid\n", Handle
));
440 // Each interface that is added must be unique
442 ASSERT (CoreFindProtocolInterface (Handle
, Protocol
, Interface
) == NULL
);
445 // Initialize the protocol interface structure
447 Prot
->Signature
= PROTOCOL_INTERFACE_SIGNATURE
;
448 Prot
->Handle
= Handle
;
449 Prot
->Protocol
= ProtEntry
;
450 Prot
->Interface
= Interface
;
453 // Initalize OpenProtocol Data base
455 InitializeListHead (&Prot
->OpenList
);
456 Prot
->OpenListCount
= 0;
459 // Add this protocol interface to the head of the supported
460 // protocol list for this handle
462 InsertHeadList (&Handle
->Protocols
, &Prot
->Link
);
465 // Add this protocol interface to the tail of the
468 InsertTailList (&ProtEntry
->Protocols
, &Prot
->ByProtocol
);
471 // Notify the notification list for this protocol
474 CoreNotifyProtocolEntry (ProtEntry
);
476 Status
= EFI_SUCCESS
;
480 // Done, unlock the database and return
482 CoreReleaseProtocolLock ();
483 if (!EFI_ERROR (Status
)) {
485 // Return the new handle back to the caller
487 *UserHandle
= Handle
;
490 // There was an error, clean up
495 DEBUG((DEBUG_ERROR
, "InstallProtocolInterface: %g %p failed with %r\n", Protocol
, Interface
, Status
));
505 Installs a list of protocol interface into the boot services environment.
506 This function calls InstallProtocolInterface() in a loop. If any error
507 occures all the protocols added by this function are removed. This is
508 basically a lib function to save space.
510 @param Handle The pointer to a handle to install the new
511 protocol interfaces on, or a pointer to NULL
512 if a new handle is to be allocated.
513 @param ... EFI_GUID followed by protocol instance. A NULL
514 terminates the list. The pairs are the
515 arguments to InstallProtocolInterface(). All the
516 protocols are added to Handle.
518 @retval EFI_SUCCESS All the protocol interface was installed.
519 @retval EFI_OUT_OF_RESOURCES There was not enough memory in pool to install all the protocols.
520 @retval EFI_ALREADY_STARTED A Device Path Protocol instance was passed in that is already present in
522 @retval EFI_INVALID_PARAMETER Handle is NULL.
523 @retval EFI_INVALID_PARAMETER Protocol is already installed on the handle specified by Handle.
528 CoreInstallMultipleProtocolInterfaces (
529 IN OUT EFI_HANDLE
*Handle
,
539 EFI_HANDLE OldHandle
;
540 EFI_HANDLE DeviceHandle
;
541 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
543 if (Handle
== NULL
) {
544 return EFI_INVALID_PARAMETER
;
548 // Syncronize with notifcations.
550 OldTpl
= CoreRaiseTpl (TPL_NOTIFY
);
554 // Check for duplicate device path and install the protocol interfaces
556 VA_START (Args
, Handle
);
557 for (Index
= 0, Status
= EFI_SUCCESS
; !EFI_ERROR (Status
); Index
++) {
559 // If protocol is NULL, then it's the end of the list
561 Protocol
= VA_ARG (Args
, EFI_GUID
*);
562 if (Protocol
== NULL
) {
566 Interface
= VA_ARG (Args
, VOID
*);
569 // Make sure you are installing on top a device path that has already been added.
571 if (CompareGuid (Protocol
, &gEfiDevicePathProtocolGuid
)) {
573 DevicePath
= Interface
;
574 Status
= CoreLocateDevicePath (&gEfiDevicePathProtocolGuid
, &DevicePath
, &DeviceHandle
);
575 if (!EFI_ERROR (Status
) && (DeviceHandle
!= NULL
) && IsDevicePathEnd(DevicePath
)) {
576 Status
= EFI_ALREADY_STARTED
;
584 Status
= CoreInstallProtocolInterface (Handle
, Protocol
, EFI_NATIVE_INTERFACE
, Interface
);
589 // If there was an error, remove all the interfaces that were installed without any errors
591 if (EFI_ERROR (Status
)) {
593 // Reset the va_arg back to the first argument.
595 VA_START (Args
, Handle
);
596 for (; Index
> 1; Index
--) {
597 Protocol
= VA_ARG (Args
, EFI_GUID
*);
598 Interface
= VA_ARG (Args
, VOID
*);
599 CoreUninstallProtocolInterface (*Handle
, Protocol
, Interface
);
609 CoreRestoreTpl (OldTpl
);
615 Attempts to disconnect all drivers that are using the protocol interface being queried.
616 If failed, reconnect all drivers disconnected.
617 Note: This function doesn't do parameters checking, it's caller's responsibility
618 to pass in valid parameters.
620 @param UserHandle The handle on which the protocol is installed
621 @param Prot The protocol to disconnect drivers from
623 @retval EFI_SUCCESS Drivers using the protocol interface are all
625 @retval EFI_ACCESS_DENIED Failed to disconnect one or all of the drivers
629 CoreDisconnectControllersUsingProtocolInterface (
630 IN EFI_HANDLE UserHandle
,
631 IN PROTOCOL_INTERFACE
*Prot
637 OPEN_PROTOCOL_DATA
*OpenData
;
639 Status
= EFI_SUCCESS
;
642 // Attempt to disconnect all drivers from this protocol interface
646 for ( Link
= Prot
->OpenList
.ForwardLink
;
647 (Link
!= &Prot
->OpenList
) && !ItemFound
;
648 Link
= Link
->ForwardLink
) {
649 OpenData
= CR (Link
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
650 if ((OpenData
->Attributes
& EFI_OPEN_PROTOCOL_BY_DRIVER
) != 0) {
652 CoreReleaseProtocolLock ();
653 Status
= CoreDisconnectController (UserHandle
, OpenData
->AgentHandle
, NULL
);
654 CoreAcquireProtocolLock ();
655 if (EFI_ERROR (Status
)) {
663 if (!EFI_ERROR (Status
)) {
665 // Attempt to remove BY_HANDLE_PROTOOCL and GET_PROTOCOL and TEST_PROTOCOL Open List items
669 for ( Link
= Prot
->OpenList
.ForwardLink
;
670 (Link
!= &Prot
->OpenList
) && !ItemFound
;
671 Link
= Link
->ForwardLink
) {
672 OpenData
= CR (Link
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
673 if ((OpenData
->Attributes
&
674 (EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
| EFI_OPEN_PROTOCOL_GET_PROTOCOL
| EFI_OPEN_PROTOCOL_TEST_PROTOCOL
)) != 0) {
676 RemoveEntryList (&OpenData
->Link
);
677 Prot
->OpenListCount
--;
678 CoreFreePool (OpenData
);
685 // If there are errors or still has open items in the list, then reconnect all the drivers and return an error
687 if (EFI_ERROR (Status
) || (Prot
->OpenListCount
> 0)) {
688 CoreReleaseProtocolLock ();
689 CoreConnectController (UserHandle
, NULL
, NULL
, TRUE
);
690 CoreAcquireProtocolLock ();
691 Status
= EFI_ACCESS_DENIED
;
700 Uninstalls all instances of a protocol:interfacer from a handle.
701 If the last protocol interface is remove from the handle, the
704 @param UserHandle The handle to remove the protocol handler from
705 @param Protocol The protocol, of protocol:interface, to remove
706 @param Interface The interface, of protocol:interface, to remove
708 @retval EFI_INVALID_PARAMETER Protocol is NULL.
709 @retval EFI_SUCCESS Protocol interface successfully uninstalled.
714 CoreUninstallProtocolInterface (
715 IN EFI_HANDLE UserHandle
,
716 IN EFI_GUID
*Protocol
,
722 PROTOCOL_INTERFACE
*Prot
;
725 // Check that Protocol is valid
727 if (Protocol
== NULL
) {
728 return EFI_INVALID_PARAMETER
;
732 // Check that UserHandle is a valid handle
734 Status
= CoreValidateHandle (UserHandle
);
735 if (EFI_ERROR (Status
)) {
740 // Lock the protocol database
742 CoreAcquireProtocolLock ();
745 // Check that Protocol exists on UserHandle, and Interface matches the interface in the database
747 Prot
= CoreFindProtocolInterface (UserHandle
, Protocol
, Interface
);
749 Status
= EFI_NOT_FOUND
;
754 // Attempt to disconnect all drivers that are using the protocol interface that is about to be removed
756 Status
= CoreDisconnectControllersUsingProtocolInterface (
760 if (EFI_ERROR (Status
)) {
762 // One or more drivers refused to release, so return the error
768 // Remove the protocol interface from the protocol
770 Status
= EFI_NOT_FOUND
;
771 Handle
= (IHANDLE
*)UserHandle
;
772 Prot
= CoreRemoveInterfaceFromProtocol (Handle
, Protocol
, Interface
);
776 // Update the Key to show that the handle has been created/modified
778 gHandleDatabaseKey
++;
779 Handle
->Key
= gHandleDatabaseKey
;
782 // Remove the protocol interface from the handle
784 RemoveEntryList (&Prot
->Link
);
791 Status
= EFI_SUCCESS
;
795 // If there are no more handlers for the handle, free the handle
797 if (IsListEmpty (&Handle
->Protocols
)) {
798 Handle
->Signature
= 0;
799 RemoveEntryList (&Handle
->AllHandles
);
800 CoreFreePool (Handle
);
805 // Done, unlock the database and return
807 CoreReleaseProtocolLock ();
815 Uninstalls a list of protocol interface in the boot services environment.
816 This function calls UnisatllProtocolInterface() in a loop. This is
817 basically a lib function to save space.
819 @param Handle The handle to uninstall the protocol
820 @param ... EFI_GUID followed by protocol instance. A NULL
821 terminates the list. The pairs are the
822 arguments to UninstallProtocolInterface(). All
823 the protocols are added to Handle.
830 CoreUninstallMultipleProtocolInterfaces (
831 IN EFI_HANDLE Handle
,
841 VA_START (Args
, Handle
);
842 for (Index
= 0, Status
= EFI_SUCCESS
; !EFI_ERROR (Status
); Index
++) {
844 // If protocol is NULL, then it's the end of the list
846 Protocol
= VA_ARG (Args
, EFI_GUID
*);
847 if (Protocol
== NULL
) {
851 Interface
= VA_ARG (Args
, VOID
*);
856 Status
= CoreUninstallProtocolInterface (Handle
, Protocol
, Interface
);
861 // If there was an error, add all the interfaces that were
862 // uninstalled without any errors
864 if (EFI_ERROR (Status
)) {
866 // Reset the va_arg back to the first argument.
868 VA_START (Args
, Handle
);
869 for (; Index
> 1; Index
--) {
870 Protocol
= VA_ARG(Args
, EFI_GUID
*);
871 Interface
= VA_ARG(Args
, VOID
*);
872 CoreInstallProtocolInterface (&Handle
, Protocol
, EFI_NATIVE_INTERFACE
, Interface
);
882 Locate a certain GUID protocol interface in a Handle's protocols.
884 @param UserHandle The handle to obtain the protocol interface on
885 @param Protocol The GUID of the protocol
887 @return The requested protocol interface for the handle
891 CoreGetProtocolInterface (
892 IN EFI_HANDLE UserHandle
,
893 IN EFI_GUID
*Protocol
897 PROTOCOL_ENTRY
*ProtEntry
;
898 PROTOCOL_INTERFACE
*Prot
;
902 Status
= CoreValidateHandle (UserHandle
);
903 if (EFI_ERROR (Status
)) {
907 Handle
= (IHANDLE
*)UserHandle
;
910 // Look at each protocol interface for a match
912 for (Link
= Handle
->Protocols
.ForwardLink
; Link
!= &Handle
->Protocols
; Link
= Link
->ForwardLink
) {
913 Prot
= CR(Link
, PROTOCOL_INTERFACE
, Link
, PROTOCOL_INTERFACE_SIGNATURE
);
914 ProtEntry
= Prot
->Protocol
;
915 if (CompareGuid (&ProtEntry
->ProtocolID
, Protocol
)) {
925 Queries a handle to determine if it supports a specified protocol.
927 @param UserHandle The handle being queried.
928 @param Protocol The published unique identifier of the protocol.
929 @param Interface Supplies the address where a pointer to the
930 corresponding Protocol Interface is returned.
932 @retval EFI_SUCCESS The interface information for the specified protocol was returned.
933 @retval EFI_UNSUPPORTED The device does not support the specified protocol.
934 @retval EFI_INVALID_PARAMETER Handle is NULL..
935 @retval EFI_INVALID_PARAMETER Protocol is NULL.
936 @retval EFI_INVALID_PARAMETER Interface is NULL.
942 IN EFI_HANDLE UserHandle
,
943 IN EFI_GUID
*Protocol
,
947 return CoreOpenProtocol (
953 EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
960 Locates the installed protocol handler for the handle, and
961 invokes it to obtain the protocol interface. Usage information
962 is registered in the protocol data base.
964 @param UserHandle The handle to obtain the protocol interface on
965 @param Protocol The ID of the protocol
966 @param Interface The location to return the protocol interface
967 @param ImageHandle The handle of the Image that is opening the
968 protocol interface specified by Protocol and
970 @param ControllerHandle The controller handle that is requiring this
972 @param Attributes The open mode of the protocol interface
973 specified by Handle and Protocol.
975 @retval EFI_INVALID_PARAMETER Protocol is NULL.
976 @retval EFI_SUCCESS Get the protocol interface.
982 IN EFI_HANDLE UserHandle
,
983 IN EFI_GUID
*Protocol
,
984 OUT VOID
**Interface OPTIONAL
,
985 IN EFI_HANDLE ImageHandle
,
986 IN EFI_HANDLE ControllerHandle
,
991 PROTOCOL_INTERFACE
*Prot
;
993 OPEN_PROTOCOL_DATA
*OpenData
;
1000 // Check for invalid Protocol
1002 if (Protocol
== NULL
) {
1003 return EFI_INVALID_PARAMETER
;
1007 // Check for invalid Interface
1009 if (Attributes
!= EFI_OPEN_PROTOCOL_TEST_PROTOCOL
) {
1010 if (Interface
== NULL
) {
1011 return EFI_INVALID_PARAMETER
;
1018 // Check for invalid UserHandle
1020 Status
= CoreValidateHandle (UserHandle
);
1021 if (EFI_ERROR (Status
)) {
1026 // Check for invalid Attributes
1028 switch (Attributes
) {
1029 case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
:
1030 Status
= CoreValidateHandle (ImageHandle
);
1031 if (EFI_ERROR (Status
)) {
1034 Status
= CoreValidateHandle (ControllerHandle
);
1035 if (EFI_ERROR (Status
)) {
1038 if (UserHandle
== ControllerHandle
) {
1039 return EFI_INVALID_PARAMETER
;
1042 case EFI_OPEN_PROTOCOL_BY_DRIVER
:
1043 case EFI_OPEN_PROTOCOL_BY_DRIVER
| EFI_OPEN_PROTOCOL_EXCLUSIVE
:
1044 Status
= CoreValidateHandle (ImageHandle
);
1045 if (EFI_ERROR (Status
)) {
1048 Status
= CoreValidateHandle (ControllerHandle
);
1049 if (EFI_ERROR (Status
)) {
1053 case EFI_OPEN_PROTOCOL_EXCLUSIVE
:
1054 Status
= CoreValidateHandle (ImageHandle
);
1055 if (EFI_ERROR (Status
)) {
1059 case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
:
1060 case EFI_OPEN_PROTOCOL_GET_PROTOCOL
:
1061 case EFI_OPEN_PROTOCOL_TEST_PROTOCOL
:
1064 return EFI_INVALID_PARAMETER
;
1068 // Lock the protocol database
1070 CoreAcquireProtocolLock ();
1073 // Look at each protocol interface for a match
1075 Prot
= CoreGetProtocolInterface (UserHandle
, Protocol
);
1077 Status
= EFI_UNSUPPORTED
;
1082 // This is the protocol interface entry for this protocol
1084 if (Attributes
!= EFI_OPEN_PROTOCOL_TEST_PROTOCOL
) {
1085 *Interface
= Prot
->Interface
;
1087 Status
= EFI_SUCCESS
;
1091 for ( Link
= Prot
->OpenList
.ForwardLink
; Link
!= &Prot
->OpenList
; Link
= Link
->ForwardLink
) {
1092 OpenData
= CR (Link
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
1093 ExactMatch
= (BOOLEAN
)((OpenData
->AgentHandle
== ImageHandle
) &&
1094 (OpenData
->Attributes
== Attributes
) &&
1095 (OpenData
->ControllerHandle
== ControllerHandle
));
1096 if ((OpenData
->Attributes
& EFI_OPEN_PROTOCOL_BY_DRIVER
) != 0) {
1099 Status
= EFI_ALREADY_STARTED
;
1103 if ((OpenData
->Attributes
& EFI_OPEN_PROTOCOL_EXCLUSIVE
) != 0) {
1105 } else if (ExactMatch
) {
1106 OpenData
->OpenCount
++;
1107 Status
= EFI_SUCCESS
;
1113 // ByDriver TRUE -> A driver is managing (UserHandle, Protocol)
1114 // ByDriver FALSE -> There are no drivers managing (UserHandle, Protocol)
1115 // Exclusive TRUE -> Something has exclusive access to (UserHandle, Protocol)
1116 // Exclusive FALSE -> Nothing has exclusive access to (UserHandle, Protocol)
1119 switch (Attributes
) {
1120 case EFI_OPEN_PROTOCOL_BY_DRIVER
:
1121 if (Exclusive
|| ByDriver
) {
1122 Status
= EFI_ACCESS_DENIED
;
1126 case EFI_OPEN_PROTOCOL_BY_DRIVER
| EFI_OPEN_PROTOCOL_EXCLUSIVE
:
1127 case EFI_OPEN_PROTOCOL_EXCLUSIVE
:
1129 Status
= EFI_ACCESS_DENIED
;
1135 for ( Link
= Prot
->OpenList
.ForwardLink
; (Link
!= &Prot
->OpenList
) && (!Disconnect
); Link
= Link
->ForwardLink
) {
1136 OpenData
= CR (Link
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
1137 if ((OpenData
->Attributes
& EFI_OPEN_PROTOCOL_BY_DRIVER
) != 0) {
1139 CoreReleaseProtocolLock ();
1140 Status
= CoreDisconnectController (UserHandle
, OpenData
->AgentHandle
, NULL
);
1141 CoreAcquireProtocolLock ();
1142 if (EFI_ERROR (Status
)) {
1143 Status
= EFI_ACCESS_DENIED
;
1148 } while (Disconnect
);
1151 case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
:
1152 case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
:
1153 case EFI_OPEN_PROTOCOL_GET_PROTOCOL
:
1154 case EFI_OPEN_PROTOCOL_TEST_PROTOCOL
:
1158 if (ImageHandle
== NULL
) {
1159 Status
= EFI_SUCCESS
;
1165 OpenData
= AllocatePool (sizeof(OPEN_PROTOCOL_DATA
));
1166 if (OpenData
== NULL
) {
1167 Status
= EFI_OUT_OF_RESOURCES
;
1169 OpenData
->Signature
= OPEN_PROTOCOL_DATA_SIGNATURE
;
1170 OpenData
->AgentHandle
= ImageHandle
;
1171 OpenData
->ControllerHandle
= ControllerHandle
;
1172 OpenData
->Attributes
= Attributes
;
1173 OpenData
->OpenCount
= 1;
1174 InsertTailList (&Prot
->OpenList
, &OpenData
->Link
);
1175 Prot
->OpenListCount
++;
1176 Status
= EFI_SUCCESS
;
1181 // Done. Release the database lock are return
1183 CoreReleaseProtocolLock ();
1190 Closes a protocol on a handle that was opened using OpenProtocol().
1192 @param UserHandle The handle for the protocol interface that was
1193 previously opened with OpenProtocol(), and is
1195 @param Protocol The published unique identifier of the protocol.
1196 It is the caller's responsibility to pass in a
1198 @param AgentHandle The handle of the agent that is closing the
1200 @param ControllerHandle If the agent that opened a protocol is a driver
1201 that follows the EFI Driver Model, then this
1202 parameter is the controller handle that required
1203 the protocol interface. If the agent does not
1204 follow the EFI Driver Model, then this parameter
1205 is optional and may be NULL.
1207 @retval EFI_SUCCESS The protocol instance was closed.
1208 @retval EFI_INVALID_PARAMETER Handle, AgentHandle or ControllerHandle is not a
1210 @retval EFI_NOT_FOUND Can not find the specified protocol or
1217 IN EFI_HANDLE UserHandle
,
1218 IN EFI_GUID
*Protocol
,
1219 IN EFI_HANDLE AgentHandle
,
1220 IN EFI_HANDLE ControllerHandle
1224 PROTOCOL_INTERFACE
*ProtocolInterface
;
1226 OPEN_PROTOCOL_DATA
*OpenData
;
1229 // Check for invalid parameters
1231 Status
= CoreValidateHandle (UserHandle
);
1232 if (EFI_ERROR (Status
)) {
1235 Status
= CoreValidateHandle (AgentHandle
);
1236 if (EFI_ERROR (Status
)) {
1239 if (ControllerHandle
!= NULL
) {
1240 Status
= CoreValidateHandle (ControllerHandle
);
1241 if (EFI_ERROR (Status
)) {
1245 if (Protocol
== NULL
) {
1246 return EFI_INVALID_PARAMETER
;
1250 // Lock the protocol database
1252 CoreAcquireProtocolLock ();
1255 // Look at each protocol interface for a match
1257 Status
= EFI_NOT_FOUND
;
1258 ProtocolInterface
= CoreGetProtocolInterface (UserHandle
, Protocol
);
1259 if (ProtocolInterface
== NULL
) {
1264 // Walk the Open data base looking for AgentHandle
1266 Link
= ProtocolInterface
->OpenList
.ForwardLink
;
1267 while (Link
!= &ProtocolInterface
->OpenList
) {
1268 OpenData
= CR (Link
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
1269 Link
= Link
->ForwardLink
;
1270 if ((OpenData
->AgentHandle
== AgentHandle
) && (OpenData
->ControllerHandle
== ControllerHandle
)) {
1271 RemoveEntryList (&OpenData
->Link
);
1272 ProtocolInterface
->OpenListCount
--;
1273 CoreFreePool (OpenData
);
1274 Status
= EFI_SUCCESS
;
1280 // Done. Release the database lock and return.
1282 CoreReleaseProtocolLock ();
1290 Return information about Opened protocols in the system
1292 @param UserHandle The handle to close the protocol interface on
1293 @param Protocol The ID of the protocol
1294 @param EntryBuffer A pointer to a buffer of open protocol information in the
1295 form of EFI_OPEN_PROTOCOL_INFORMATION_ENTRY structures.
1296 @param EntryCount Number of EntryBuffer entries
1298 @retval EFI_SUCCESS The open protocol information was returned in EntryBuffer,
1299 and the number of entries was returned EntryCount.
1300 @retval EFI_NOT_FOUND Handle does not support the protocol specified by Protocol.
1301 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to allocate EntryBuffer.
1306 CoreOpenProtocolInformation (
1307 IN EFI_HANDLE UserHandle
,
1308 IN EFI_GUID
*Protocol
,
1309 OUT EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
**EntryBuffer
,
1310 OUT UINTN
*EntryCount
1314 PROTOCOL_INTERFACE
*ProtocolInterface
;
1316 OPEN_PROTOCOL_DATA
*OpenData
;
1317 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*Buffer
;
1321 *EntryBuffer
= NULL
;
1325 // Lock the protocol database
1327 CoreAcquireProtocolLock ();
1330 // Look at each protocol interface for a match
1332 Status
= EFI_NOT_FOUND
;
1333 ProtocolInterface
= CoreGetProtocolInterface (UserHandle
, Protocol
);
1334 if (ProtocolInterface
== NULL
) {
1339 // Count the number of Open Entries
1341 for ( Link
= ProtocolInterface
->OpenList
.ForwardLink
, Count
= 0;
1342 (Link
!= &ProtocolInterface
->OpenList
) ;
1343 Link
= Link
->ForwardLink
) {
1347 ASSERT (Count
== ProtocolInterface
->OpenListCount
);
1350 Size
= sizeof(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
);
1352 Size
= Count
* sizeof(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
);
1355 Buffer
= AllocatePool (Size
);
1356 if (Buffer
== NULL
) {
1357 Status
= EFI_OUT_OF_RESOURCES
;
1361 Status
= EFI_SUCCESS
;
1362 for ( Link
= ProtocolInterface
->OpenList
.ForwardLink
, Count
= 0;
1363 (Link
!= &ProtocolInterface
->OpenList
);
1364 Link
= Link
->ForwardLink
, Count
++ ) {
1365 OpenData
= CR (Link
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
1367 Buffer
[Count
].AgentHandle
= OpenData
->AgentHandle
;
1368 Buffer
[Count
].ControllerHandle
= OpenData
->ControllerHandle
;
1369 Buffer
[Count
].Attributes
= OpenData
->Attributes
;
1370 Buffer
[Count
].OpenCount
= OpenData
->OpenCount
;
1373 *EntryBuffer
= Buffer
;
1374 *EntryCount
= Count
;
1378 // Done. Release the database lock.
1380 CoreReleaseProtocolLock ();
1388 Retrieves the list of protocol interface GUIDs that are installed on a handle in a buffer allocated
1391 @param UserHandle The handle from which to retrieve the list of
1392 protocol interface GUIDs.
1393 @param ProtocolBuffer A pointer to the list of protocol interface GUID
1394 pointers that are installed on Handle.
1395 @param ProtocolBufferCount A pointer to the number of GUID pointers present
1398 @retval EFI_SUCCESS The list of protocol interface GUIDs installed
1399 on Handle was returned in ProtocolBuffer. The
1400 number of protocol interface GUIDs was returned
1401 in ProtocolBufferCount.
1402 @retval EFI_INVALID_PARAMETER Handle is NULL.
1403 @retval EFI_INVALID_PARAMETER Handle is not a valid EFI_HANDLE.
1404 @retval EFI_INVALID_PARAMETER ProtocolBuffer is NULL.
1405 @retval EFI_INVALID_PARAMETER ProtocolBufferCount is NULL.
1406 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the
1412 CoreProtocolsPerHandle (
1413 IN EFI_HANDLE UserHandle
,
1414 OUT EFI_GUID
***ProtocolBuffer
,
1415 OUT UINTN
*ProtocolBufferCount
1420 PROTOCOL_INTERFACE
*Prot
;
1422 UINTN ProtocolCount
;
1425 Status
= CoreValidateHandle (UserHandle
);
1426 if (EFI_ERROR (Status
)) {
1430 Handle
= (IHANDLE
*)UserHandle
;
1432 if (ProtocolBuffer
== NULL
) {
1433 return EFI_INVALID_PARAMETER
;
1436 if (ProtocolBufferCount
== NULL
) {
1437 return EFI_INVALID_PARAMETER
;
1440 *ProtocolBufferCount
= 0;
1444 CoreAcquireProtocolLock ();
1446 for (Link
= Handle
->Protocols
.ForwardLink
; Link
!= &Handle
->Protocols
; Link
= Link
->ForwardLink
) {
1451 // If there are no protocol interfaces installed on Handle, then Handle is not a valid EFI_HANDLE
1453 if (ProtocolCount
== 0) {
1454 Status
= EFI_INVALID_PARAMETER
;
1458 Buffer
= AllocatePool (sizeof (EFI_GUID
*) * ProtocolCount
);
1459 if (Buffer
== NULL
) {
1460 Status
= EFI_OUT_OF_RESOURCES
;
1464 *ProtocolBuffer
= Buffer
;
1465 *ProtocolBufferCount
= ProtocolCount
;
1467 for ( Link
= Handle
->Protocols
.ForwardLink
, ProtocolCount
= 0;
1468 Link
!= &Handle
->Protocols
;
1469 Link
= Link
->ForwardLink
, ProtocolCount
++) {
1470 Prot
= CR(Link
, PROTOCOL_INTERFACE
, Link
, PROTOCOL_INTERFACE_SIGNATURE
);
1471 Buffer
[ProtocolCount
] = &(Prot
->Protocol
->ProtocolID
);
1473 Status
= EFI_SUCCESS
;
1476 CoreReleaseProtocolLock ();
1483 return handle database key.
1486 @return Handle database key.
1490 CoreGetHandleDatabaseKey (
1494 return gHandleDatabaseKey
;
1500 Go connect any handles that were created or modified while a image executed.
1502 @param Key The Key to show that the handle has been
1507 CoreConnectHandlesByKey (
1513 EFI_HANDLE
*HandleBuffer
;
1518 // Lock the protocol database
1520 CoreAcquireProtocolLock ();
1522 for (Link
= gHandleList
.ForwardLink
, Count
= 0; Link
!= &gHandleList
; Link
= Link
->ForwardLink
) {
1523 Handle
= CR (Link
, IHANDLE
, AllHandles
, EFI_HANDLE_SIGNATURE
);
1524 if (Handle
->Key
> Key
) {
1529 HandleBuffer
= AllocatePool (Count
* sizeof (EFI_HANDLE
));
1530 if (HandleBuffer
== NULL
) {
1531 CoreReleaseProtocolLock ();
1535 for (Link
= gHandleList
.ForwardLink
, Count
= 0; Link
!= &gHandleList
; Link
= Link
->ForwardLink
) {
1536 Handle
= CR (Link
, IHANDLE
, AllHandles
, EFI_HANDLE_SIGNATURE
);
1537 if (Handle
->Key
> Key
) {
1538 HandleBuffer
[Count
++] = Handle
;
1543 // Unlock the protocol database
1545 CoreReleaseProtocolLock ();
1548 // Connect all handles whose Key value is greater than Key
1550 for (Index
= 0; Index
< Count
; Index
++) {
1551 CoreConnectController (HandleBuffer
[Index
], NULL
, NULL
, TRUE
);
1554 CoreFreePool(HandleBuffer
);