2 UEFI handle & protocol handling.
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
13 // mProtocolDatabase - A list of all protocols in the system. (simple list for now)
14 // gHandleList - A list of all the handles in the system
15 // gProtocolDatabaseLock - Lock to protect the mProtocolDatabase
16 // gHandleDatabaseKey - The Key to show that the handle has been created/modified
18 LIST_ENTRY mProtocolDatabase
= INITIALIZE_LIST_HEAD_VARIABLE (mProtocolDatabase
);
19 LIST_ENTRY gHandleList
= INITIALIZE_LIST_HEAD_VARIABLE (gHandleList
);
20 EFI_LOCK gProtocolDatabaseLock
= EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY
);
21 UINT64 gHandleDatabaseKey
= 0;
24 Acquire lock on gProtocolDatabaseLock.
28 CoreAcquireProtocolLock (
32 CoreAcquireLock (&gProtocolDatabaseLock
);
36 Release lock on gProtocolDatabaseLock.
40 CoreReleaseProtocolLock (
44 CoreReleaseLock (&gProtocolDatabaseLock
);
48 Check whether a handle is a valid EFI_HANDLE
49 The gProtocolDatabaseLock must be owned
51 @param UserHandle The handle to check
53 @retval EFI_INVALID_PARAMETER The handle is NULL or not a valid EFI_HANDLE.
54 @retval EFI_SUCCESS The handle is valid EFI_HANDLE.
59 IN EFI_HANDLE UserHandle
65 if (UserHandle
== NULL
) {
66 return EFI_INVALID_PARAMETER
;
69 ASSERT_LOCKED (&gProtocolDatabaseLock
);
71 for (Link
= gHandleList
.BackLink
; Link
!= &gHandleList
; Link
= Link
->BackLink
) {
72 Handle
= CR (Link
, IHANDLE
, AllHandles
, EFI_HANDLE_SIGNATURE
);
73 if (Handle
== (IHANDLE
*)UserHandle
) {
78 return EFI_INVALID_PARAMETER
;
82 Finds the protocol entry for the requested protocol.
83 The gProtocolDatabaseLock must be owned
85 @param Protocol The ID of the protocol
86 @param Create Create a new entry if not found
88 @return Protocol entry
92 CoreFindProtocolEntry (
93 IN EFI_GUID
*Protocol
,
99 PROTOCOL_ENTRY
*ProtEntry
;
101 ASSERT_LOCKED (&gProtocolDatabaseLock
);
104 // Search the database for the matching GUID
108 for (Link
= mProtocolDatabase
.ForwardLink
;
109 Link
!= &mProtocolDatabase
;
110 Link
= Link
->ForwardLink
)
112 Item
= CR (Link
, PROTOCOL_ENTRY
, AllEntries
, PROTOCOL_ENTRY_SIGNATURE
);
113 if (CompareGuid (&Item
->ProtocolID
, Protocol
)) {
115 // This is the protocol entry
124 // If the protocol entry was not found and Create is TRUE, then
125 // allocate a new entry
127 if ((ProtEntry
== NULL
) && Create
) {
128 ProtEntry
= AllocatePool (sizeof (PROTOCOL_ENTRY
));
130 if (ProtEntry
!= NULL
) {
132 // Initialize new protocol entry structure
134 ProtEntry
->Signature
= PROTOCOL_ENTRY_SIGNATURE
;
135 CopyGuid ((VOID
*)&ProtEntry
->ProtocolID
, Protocol
);
136 InitializeListHead (&ProtEntry
->Protocols
);
137 InitializeListHead (&ProtEntry
->Notify
);
140 // Add it to protocol database
142 InsertTailList (&mProtocolDatabase
, &ProtEntry
->AllEntries
);
150 Finds the protocol instance for the requested handle and protocol.
151 Note: This function doesn't do parameters checking, it's caller's responsibility
152 to pass in valid parameters.
154 @param Handle The handle to search the protocol on
155 @param Protocol GUID of the protocol
156 @param Interface The interface for the protocol being searched
158 @return Protocol instance (NULL: Not found)
162 CoreFindProtocolInterface (
164 IN EFI_GUID
*Protocol
,
168 PROTOCOL_INTERFACE
*Prot
;
169 PROTOCOL_ENTRY
*ProtEntry
;
172 ASSERT_LOCKED (&gProtocolDatabaseLock
);
176 // Lookup the protocol entry for this protocol ID
179 ProtEntry
= CoreFindProtocolEntry (Protocol
, FALSE
);
180 if (ProtEntry
!= NULL
) {
182 // Look at each protocol interface for any matches
184 for (Link
= Handle
->Protocols
.ForwardLink
; Link
!= &Handle
->Protocols
; Link
= Link
->ForwardLink
) {
186 // If this protocol interface matches, remove it
188 Prot
= CR (Link
, PROTOCOL_INTERFACE
, Link
, PROTOCOL_INTERFACE_SIGNATURE
);
189 if ((Prot
->Interface
== Interface
) && (Prot
->Protocol
== ProtEntry
)) {
201 Removes an event from a register protocol notify list on a protocol.
203 @param Event The event to search for in the protocol
206 @return EFI_SUCCESS if the event was found and removed.
207 @return EFI_NOT_FOUND if the event was not found in the protocl database.
211 CoreUnregisterProtocolNotifyEvent (
216 PROTOCOL_ENTRY
*ProtEntry
;
217 LIST_ENTRY
*NotifyLink
;
218 PROTOCOL_NOTIFY
*ProtNotify
;
220 CoreAcquireProtocolLock ();
222 for ( Link
= mProtocolDatabase
.ForwardLink
;
223 Link
!= &mProtocolDatabase
;
224 Link
= Link
->ForwardLink
)
226 ProtEntry
= CR (Link
, PROTOCOL_ENTRY
, AllEntries
, PROTOCOL_ENTRY_SIGNATURE
);
228 for ( NotifyLink
= ProtEntry
->Notify
.ForwardLink
;
229 NotifyLink
!= &ProtEntry
->Notify
;
230 NotifyLink
= NotifyLink
->ForwardLink
)
232 ProtNotify
= CR (NotifyLink
, PROTOCOL_NOTIFY
, Link
, PROTOCOL_NOTIFY_SIGNATURE
);
234 if (ProtNotify
->Event
== Event
) {
235 RemoveEntryList (&ProtNotify
->Link
);
236 CoreFreePool (ProtNotify
);
237 CoreReleaseProtocolLock ();
243 CoreReleaseProtocolLock ();
244 return EFI_NOT_FOUND
;
248 Removes all the events in the protocol database that match Event.
250 @param Event The event to search for in the protocol
253 @return EFI_SUCCESS when done searching the entire database.
257 CoreUnregisterProtocolNotify (
264 Status
= CoreUnregisterProtocolNotifyEvent (Event
);
265 } while (!EFI_ERROR (Status
));
271 Wrapper function to CoreInstallProtocolInterfaceNotify. This is the public API which
272 Calls the private one which contains a BOOLEAN parameter for notifications
274 @param UserHandle The handle to install the protocol handler on,
275 or NULL if a new handle is to be allocated
276 @param Protocol The protocol to add to the handle
277 @param InterfaceType Indicates whether Interface is supplied in
279 @param Interface The interface for the protocol being added
286 CoreInstallProtocolInterface (
287 IN OUT EFI_HANDLE
*UserHandle
,
288 IN EFI_GUID
*Protocol
,
289 IN EFI_INTERFACE_TYPE InterfaceType
,
293 return CoreInstallProtocolInterfaceNotify (
303 Installs a protocol interface into the boot services environment.
305 @param UserHandle The handle to install the protocol handler on,
306 or NULL if a new handle is to be allocated
307 @param Protocol The protocol to add to the handle
308 @param InterfaceType Indicates whether Interface is supplied in
310 @param Interface The interface for the protocol being added
311 @param Notify indicates whether notify the notification list
314 @retval EFI_INVALID_PARAMETER Invalid parameter
315 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
316 @retval EFI_SUCCESS Protocol interface successfully installed
320 CoreInstallProtocolInterfaceNotify (
321 IN OUT EFI_HANDLE
*UserHandle
,
322 IN EFI_GUID
*Protocol
,
323 IN EFI_INTERFACE_TYPE InterfaceType
,
328 PROTOCOL_INTERFACE
*Prot
;
329 PROTOCOL_ENTRY
*ProtEntry
;
332 VOID
*ExistingInterface
;
335 // returns EFI_INVALID_PARAMETER if InterfaceType is invalid.
336 // Also added check for invalid UserHandle and Protocol pointers.
338 if ((UserHandle
== NULL
) || (Protocol
== NULL
)) {
339 return EFI_INVALID_PARAMETER
;
342 if (InterfaceType
!= EFI_NATIVE_INTERFACE
) {
343 return EFI_INVALID_PARAMETER
;
347 // Print debug message
349 DEBUG ((DEBUG_INFO
, "InstallProtocolInterface: %g %p\n", Protocol
, Interface
));
351 Status
= EFI_OUT_OF_RESOURCES
;
355 if (*UserHandle
!= NULL
) {
356 Status
= CoreHandleProtocol (*UserHandle
, Protocol
, (VOID
**)&ExistingInterface
);
357 if (!EFI_ERROR (Status
)) {
358 return EFI_INVALID_PARAMETER
;
363 // Lock the protocol database
365 CoreAcquireProtocolLock ();
368 // Lookup the Protocol Entry for the requested protocol
370 ProtEntry
= CoreFindProtocolEntry (Protocol
, TRUE
);
371 if (ProtEntry
== NULL
) {
376 // Allocate a new protocol interface structure
378 Prot
= AllocateZeroPool (sizeof (PROTOCOL_INTERFACE
));
380 Status
= EFI_OUT_OF_RESOURCES
;
385 // If caller didn't supply a handle, allocate a new one
387 Handle
= (IHANDLE
*)*UserHandle
;
388 if (Handle
== NULL
) {
389 Handle
= AllocateZeroPool (sizeof (IHANDLE
));
390 if (Handle
== NULL
) {
391 Status
= EFI_OUT_OF_RESOURCES
;
396 // Initialize new handler structure
398 Handle
->Signature
= EFI_HANDLE_SIGNATURE
;
399 InitializeListHead (&Handle
->Protocols
);
402 // Initialize the Key to show that the handle has been created/modified
404 gHandleDatabaseKey
++;
405 Handle
->Key
= gHandleDatabaseKey
;
408 // Add this handle to the list global list of all handles
411 InsertTailList (&gHandleList
, &Handle
->AllHandles
);
413 Status
= CoreValidateHandle (Handle
);
414 if (EFI_ERROR (Status
)) {
415 DEBUG ((DEBUG_ERROR
, "InstallProtocolInterface: input handle at 0x%x is invalid\n", Handle
));
421 // Each interface that is added must be unique
423 ASSERT (CoreFindProtocolInterface (Handle
, Protocol
, Interface
) == NULL
);
426 // Initialize the protocol interface structure
428 Prot
->Signature
= PROTOCOL_INTERFACE_SIGNATURE
;
429 Prot
->Handle
= Handle
;
430 Prot
->Protocol
= ProtEntry
;
431 Prot
->Interface
= Interface
;
434 // Initalize OpenProtocol Data base
436 InitializeListHead (&Prot
->OpenList
);
437 Prot
->OpenListCount
= 0;
440 // Add this protocol interface to the head of the supported
441 // protocol list for this handle
443 InsertHeadList (&Handle
->Protocols
, &Prot
->Link
);
446 // Add this protocol interface to the tail of the
449 InsertTailList (&ProtEntry
->Protocols
, &Prot
->ByProtocol
);
452 // Notify the notification list for this protocol
455 CoreNotifyProtocolEntry (ProtEntry
);
458 Status
= EFI_SUCCESS
;
462 // Done, unlock the database and return
464 CoreReleaseProtocolLock ();
465 if (!EFI_ERROR (Status
)) {
467 // Return the new handle back to the caller
469 *UserHandle
= Handle
;
472 // There was an error, clean up
478 DEBUG ((DEBUG_ERROR
, "InstallProtocolInterface: %g %p failed with %r\n", Protocol
, Interface
, Status
));
485 Installs a list of protocol interface into the boot services environment.
486 This function calls InstallProtocolInterface() in a loop. If any error
487 occures all the protocols added by this function are removed. This is
488 basically a lib function to save space.
490 @param Handle The pointer to a handle to install the new
491 protocol interfaces on, or a pointer to NULL
492 if a new handle is to be allocated.
493 @param ... EFI_GUID followed by protocol instance. A NULL
494 terminates the list. The pairs are the
495 arguments to InstallProtocolInterface(). All the
496 protocols are added to Handle.
498 @retval EFI_SUCCESS All the protocol interface was installed.
499 @retval EFI_OUT_OF_RESOURCES There was not enough memory in pool to install all the protocols.
500 @retval EFI_ALREADY_STARTED A Device Path Protocol instance was passed in that is already present in
502 @retval EFI_INVALID_PARAMETER Handle is NULL.
503 @retval EFI_INVALID_PARAMETER Protocol is already installed on the handle specified by Handle.
508 CoreInstallMultipleProtocolInterfaces (
509 IN OUT EFI_HANDLE
*Handle
,
519 EFI_HANDLE OldHandle
;
520 EFI_HANDLE DeviceHandle
;
521 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
523 if (Handle
== NULL
) {
524 return EFI_INVALID_PARAMETER
;
528 // Syncronize with notifcations.
530 OldTpl
= CoreRaiseTpl (TPL_NOTIFY
);
534 // Check for duplicate device path and install the protocol interfaces
536 VA_START (Args
, Handle
);
537 for (Index
= 0, Status
= EFI_SUCCESS
; !EFI_ERROR (Status
); Index
++) {
539 // If protocol is NULL, then it's the end of the list
541 Protocol
= VA_ARG (Args
, EFI_GUID
*);
542 if (Protocol
== NULL
) {
546 Interface
= VA_ARG (Args
, VOID
*);
549 // Make sure you are installing on top a device path that has already been added.
551 if (CompareGuid (Protocol
, &gEfiDevicePathProtocolGuid
)) {
553 DevicePath
= Interface
;
554 Status
= CoreLocateDevicePath (&gEfiDevicePathProtocolGuid
, &DevicePath
, &DeviceHandle
);
555 if (!EFI_ERROR (Status
) && (DeviceHandle
!= NULL
) && IsDevicePathEnd (DevicePath
)) {
556 Status
= EFI_ALREADY_STARTED
;
564 Status
= CoreInstallProtocolInterface (Handle
, Protocol
, EFI_NATIVE_INTERFACE
, Interface
);
570 // If there was an error, remove all the interfaces that were installed without any errors
572 if (EFI_ERROR (Status
)) {
574 // Reset the va_arg back to the first argument.
576 VA_START (Args
, Handle
);
577 for ( ; Index
> 1; Index
--) {
578 Protocol
= VA_ARG (Args
, EFI_GUID
*);
579 Interface
= VA_ARG (Args
, VOID
*);
580 CoreUninstallProtocolInterface (*Handle
, Protocol
, Interface
);
591 CoreRestoreTpl (OldTpl
);
596 Attempts to disconnect all drivers that are using the protocol interface being queried.
597 If failed, reconnect all drivers disconnected.
598 Note: This function doesn't do parameters checking, it's caller's responsibility
599 to pass in valid parameters.
601 @param UserHandle The handle on which the protocol is installed
602 @param Prot The protocol to disconnect drivers from
604 @retval EFI_SUCCESS Drivers using the protocol interface are all
606 @retval EFI_ACCESS_DENIED Failed to disconnect one or all of the drivers
610 CoreDisconnectControllersUsingProtocolInterface (
611 IN EFI_HANDLE UserHandle
,
612 IN PROTOCOL_INTERFACE
*Prot
618 OPEN_PROTOCOL_DATA
*OpenData
;
620 Status
= EFI_SUCCESS
;
623 // Attempt to disconnect all drivers from this protocol interface
627 for (Link
= Prot
->OpenList
.ForwardLink
; Link
!= &Prot
->OpenList
; Link
= Link
->ForwardLink
) {
628 OpenData
= CR (Link
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
629 if ((OpenData
->Attributes
& EFI_OPEN_PROTOCOL_BY_DRIVER
) != 0) {
630 CoreReleaseProtocolLock ();
631 Status
= CoreDisconnectController (UserHandle
, OpenData
->AgentHandle
, NULL
);
632 CoreAcquireProtocolLock ();
633 if (!EFI_ERROR (Status
)) {
642 if (!EFI_ERROR (Status
)) {
644 // Attempt to remove BY_HANDLE_PROTOOCL and GET_PROTOCOL and TEST_PROTOCOL Open List items
646 for (Link
= Prot
->OpenList
.ForwardLink
; Link
!= &Prot
->OpenList
;) {
647 OpenData
= CR (Link
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
648 if ((OpenData
->Attributes
&
649 (EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
| EFI_OPEN_PROTOCOL_GET_PROTOCOL
| EFI_OPEN_PROTOCOL_TEST_PROTOCOL
)) != 0)
651 Link
= RemoveEntryList (&OpenData
->Link
);
652 Prot
->OpenListCount
--;
653 CoreFreePool (OpenData
);
655 Link
= Link
->ForwardLink
;
661 // If there are errors or still has open items in the list, then reconnect all the drivers and return an error
663 if (EFI_ERROR (Status
) || (Prot
->OpenListCount
> 0)) {
664 CoreReleaseProtocolLock ();
665 CoreConnectController (UserHandle
, NULL
, NULL
, TRUE
);
666 CoreAcquireProtocolLock ();
667 Status
= EFI_ACCESS_DENIED
;
674 Uninstalls all instances of a protocol:interfacer from a handle.
675 If the last protocol interface is remove from the handle, the
678 @param UserHandle The handle to remove the protocol handler from
679 @param Protocol The protocol, of protocol:interface, to remove
680 @param Interface The interface, of protocol:interface, to remove
682 @retval EFI_INVALID_PARAMETER Protocol is NULL.
683 @retval EFI_SUCCESS Protocol interface successfully uninstalled.
688 CoreUninstallProtocolInterface (
689 IN EFI_HANDLE UserHandle
,
690 IN EFI_GUID
*Protocol
,
696 PROTOCOL_INTERFACE
*Prot
;
699 // Check that Protocol is valid
701 if (Protocol
== NULL
) {
702 return EFI_INVALID_PARAMETER
;
706 // Lock the protocol database
708 CoreAcquireProtocolLock ();
711 // Check that UserHandle is a valid handle
713 Status
= CoreValidateHandle (UserHandle
);
714 if (EFI_ERROR (Status
)) {
719 // Check that Protocol exists on UserHandle, and Interface matches the interface in the database
721 Prot
= CoreFindProtocolInterface (UserHandle
, Protocol
, Interface
);
723 Status
= EFI_NOT_FOUND
;
728 // Attempt to disconnect all drivers that are using the protocol interface that is about to be removed
730 Status
= CoreDisconnectControllersUsingProtocolInterface (
734 if (EFI_ERROR (Status
)) {
736 // One or more drivers refused to release, so return the error
742 // Remove the protocol interface from the protocol
744 Status
= EFI_NOT_FOUND
;
745 Handle
= (IHANDLE
*)UserHandle
;
746 Prot
= CoreRemoveInterfaceFromProtocol (Handle
, Protocol
, Interface
);
750 // Update the Key to show that the handle has been created/modified
752 gHandleDatabaseKey
++;
753 Handle
->Key
= gHandleDatabaseKey
;
756 // Remove the protocol interface from the handle
758 RemoveEntryList (&Prot
->Link
);
765 Status
= EFI_SUCCESS
;
769 // If there are no more handlers for the handle, free the handle
771 if (IsListEmpty (&Handle
->Protocols
)) {
772 Handle
->Signature
= 0;
773 RemoveEntryList (&Handle
->AllHandles
);
774 CoreFreePool (Handle
);
779 // Done, unlock the database and return
781 CoreReleaseProtocolLock ();
786 Uninstalls a list of protocol interface in the boot services environment.
787 This function calls UninstallProtocolInterface() in a loop. This is
788 basically a lib function to save space.
790 If any errors are generated while the protocol interfaces are being
791 uninstalled, then the protocol interfaces uninstalled prior to the error will
792 be reinstalled and EFI_INVALID_PARAMETER will be returned.
794 @param Handle The handle to uninstall the protocol interfaces
796 @param ... EFI_GUID followed by protocol instance. A NULL
797 terminates the list. The pairs are the
798 arguments to UninstallProtocolInterface(). All
799 the protocols are added to Handle.
801 @retval EFI_SUCCESS if all protocol interfaces where uninstalled.
802 @retval EFI_INVALID_PARAMETER if any protocol interface could not be
803 uninstalled and an attempt was made to
804 reinstall previously uninstalled protocol
809 CoreUninstallMultipleProtocolInterfaces (
810 IN EFI_HANDLE Handle
,
820 VA_START (Args
, Handle
);
821 for (Index
= 0, Status
= EFI_SUCCESS
; !EFI_ERROR (Status
); Index
++) {
823 // If protocol is NULL, then it's the end of the list
825 Protocol
= VA_ARG (Args
, EFI_GUID
*);
826 if (Protocol
== NULL
) {
830 Interface
= VA_ARG (Args
, VOID
*);
835 Status
= CoreUninstallProtocolInterface (Handle
, Protocol
, Interface
);
841 // If there was an error, add all the interfaces that were
842 // uninstalled without any errors
844 if (EFI_ERROR (Status
)) {
846 // Reset the va_arg back to the first argument.
848 VA_START (Args
, Handle
);
849 for ( ; Index
> 1; Index
--) {
850 Protocol
= VA_ARG (Args
, EFI_GUID
*);
851 Interface
= VA_ARG (Args
, VOID
*);
852 CoreInstallProtocolInterface (&Handle
, Protocol
, EFI_NATIVE_INTERFACE
, Interface
);
856 Status
= EFI_INVALID_PARAMETER
;
863 Locate a certain GUID protocol interface in a Handle's protocols.
865 @param UserHandle The handle to obtain the protocol interface on
866 @param Protocol The GUID of the protocol
868 @return The requested protocol interface for the handle
872 CoreGetProtocolInterface (
873 IN EFI_HANDLE UserHandle
,
874 IN EFI_GUID
*Protocol
878 PROTOCOL_ENTRY
*ProtEntry
;
879 PROTOCOL_INTERFACE
*Prot
;
883 Status
= CoreValidateHandle (UserHandle
);
884 if (EFI_ERROR (Status
)) {
888 Handle
= (IHANDLE
*)UserHandle
;
891 // Look at each protocol interface for a match
893 for (Link
= Handle
->Protocols
.ForwardLink
; Link
!= &Handle
->Protocols
; Link
= Link
->ForwardLink
) {
894 Prot
= CR (Link
, PROTOCOL_INTERFACE
, Link
, PROTOCOL_INTERFACE_SIGNATURE
);
895 ProtEntry
= Prot
->Protocol
;
896 if (CompareGuid (&ProtEntry
->ProtocolID
, Protocol
)) {
905 Queries a handle to determine if it supports a specified protocol.
907 @param UserHandle The handle being queried.
908 @param Protocol The published unique identifier of the protocol.
909 @param Interface Supplies the address where a pointer to the
910 corresponding Protocol Interface is returned.
912 @retval EFI_SUCCESS The interface information for the specified protocol was returned.
913 @retval EFI_UNSUPPORTED The device does not support the specified protocol.
914 @retval EFI_INVALID_PARAMETER Handle is NULL..
915 @retval EFI_INVALID_PARAMETER Protocol is NULL.
916 @retval EFI_INVALID_PARAMETER Interface is NULL.
922 IN EFI_HANDLE UserHandle
,
923 IN EFI_GUID
*Protocol
,
927 return CoreOpenProtocol (
933 EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
938 Locates the installed protocol handler for the handle, and
939 invokes it to obtain the protocol interface. Usage information
940 is registered in the protocol data base.
942 @param UserHandle The handle to obtain the protocol interface on
943 @param Protocol The ID of the protocol
944 @param Interface The location to return the protocol interface
945 @param ImageHandle The handle of the Image that is opening the
946 protocol interface specified by Protocol and
948 @param ControllerHandle The controller handle that is requiring this
950 @param Attributes The open mode of the protocol interface
951 specified by Handle and Protocol.
953 @retval EFI_INVALID_PARAMETER Protocol is NULL.
954 @retval EFI_SUCCESS Get the protocol interface.
960 IN EFI_HANDLE UserHandle
,
961 IN EFI_GUID
*Protocol
,
962 OUT VOID
**Interface OPTIONAL
,
963 IN EFI_HANDLE ImageHandle
,
964 IN EFI_HANDLE ControllerHandle
,
969 PROTOCOL_INTERFACE
*Prot
;
971 OPEN_PROTOCOL_DATA
*OpenData
;
978 // Check for invalid Protocol
980 if (Protocol
== NULL
) {
981 return EFI_INVALID_PARAMETER
;
985 // Check for invalid Interface
987 if ((Attributes
!= EFI_OPEN_PROTOCOL_TEST_PROTOCOL
) && (Interface
== NULL
)) {
988 return EFI_INVALID_PARAMETER
;
992 // Lock the protocol database
994 CoreAcquireProtocolLock ();
997 // Check for invalid UserHandle
999 Status
= CoreValidateHandle (UserHandle
);
1000 if (EFI_ERROR (Status
)) {
1005 // Check for invalid Attributes
1007 switch (Attributes
) {
1008 case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
:
1009 Status
= CoreValidateHandle (ImageHandle
);
1010 if (EFI_ERROR (Status
)) {
1014 Status
= CoreValidateHandle (ControllerHandle
);
1015 if (EFI_ERROR (Status
)) {
1019 if (UserHandle
== ControllerHandle
) {
1020 Status
= EFI_INVALID_PARAMETER
;
1025 case EFI_OPEN_PROTOCOL_BY_DRIVER
:
1026 case EFI_OPEN_PROTOCOL_BY_DRIVER
| EFI_OPEN_PROTOCOL_EXCLUSIVE
:
1027 Status
= CoreValidateHandle (ImageHandle
);
1028 if (EFI_ERROR (Status
)) {
1032 Status
= CoreValidateHandle (ControllerHandle
);
1033 if (EFI_ERROR (Status
)) {
1038 case EFI_OPEN_PROTOCOL_EXCLUSIVE
:
1039 Status
= CoreValidateHandle (ImageHandle
);
1040 if (EFI_ERROR (Status
)) {
1045 case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
:
1046 case EFI_OPEN_PROTOCOL_GET_PROTOCOL
:
1047 case EFI_OPEN_PROTOCOL_TEST_PROTOCOL
:
1050 Status
= EFI_INVALID_PARAMETER
;
1055 // Look at each protocol interface for a match
1057 Prot
= CoreGetProtocolInterface (UserHandle
, Protocol
);
1059 Status
= EFI_UNSUPPORTED
;
1063 Status
= EFI_SUCCESS
;
1067 for ( Link
= Prot
->OpenList
.ForwardLink
; Link
!= &Prot
->OpenList
; Link
= Link
->ForwardLink
) {
1068 OpenData
= CR (Link
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
1069 ExactMatch
= (BOOLEAN
)((OpenData
->AgentHandle
== ImageHandle
) &&
1070 (OpenData
->Attributes
== Attributes
) &&
1071 (OpenData
->ControllerHandle
== ControllerHandle
));
1072 if ((OpenData
->Attributes
& EFI_OPEN_PROTOCOL_BY_DRIVER
) != 0) {
1075 Status
= EFI_ALREADY_STARTED
;
1080 if ((OpenData
->Attributes
& EFI_OPEN_PROTOCOL_EXCLUSIVE
) != 0) {
1082 } else if (ExactMatch
) {
1083 OpenData
->OpenCount
++;
1084 Status
= EFI_SUCCESS
;
1090 // ByDriver TRUE -> A driver is managing (UserHandle, Protocol)
1091 // ByDriver FALSE -> There are no drivers managing (UserHandle, Protocol)
1092 // Exclusive TRUE -> Something has exclusive access to (UserHandle, Protocol)
1093 // Exclusive FALSE -> Nothing has exclusive access to (UserHandle, Protocol)
1096 switch (Attributes
) {
1097 case EFI_OPEN_PROTOCOL_BY_DRIVER
:
1098 if (Exclusive
|| ByDriver
) {
1099 Status
= EFI_ACCESS_DENIED
;
1104 case EFI_OPEN_PROTOCOL_BY_DRIVER
| EFI_OPEN_PROTOCOL_EXCLUSIVE
:
1105 case EFI_OPEN_PROTOCOL_EXCLUSIVE
:
1107 Status
= EFI_ACCESS_DENIED
;
1114 for (Link
= Prot
->OpenList
.ForwardLink
; Link
!= &Prot
->OpenList
; Link
= Link
->ForwardLink
) {
1115 OpenData
= CR (Link
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
1116 if ((OpenData
->Attributes
& EFI_OPEN_PROTOCOL_BY_DRIVER
) != 0) {
1118 CoreReleaseProtocolLock ();
1119 Status
= CoreDisconnectController (UserHandle
, OpenData
->AgentHandle
, NULL
);
1120 CoreAcquireProtocolLock ();
1121 if (EFI_ERROR (Status
)) {
1122 Status
= EFI_ACCESS_DENIED
;
1129 } while (Disconnect
);
1133 case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
:
1134 case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
:
1135 case EFI_OPEN_PROTOCOL_GET_PROTOCOL
:
1136 case EFI_OPEN_PROTOCOL_TEST_PROTOCOL
:
1140 if (ImageHandle
== NULL
) {
1141 Status
= EFI_SUCCESS
;
1148 OpenData
= AllocatePool (sizeof (OPEN_PROTOCOL_DATA
));
1149 if (OpenData
== NULL
) {
1150 Status
= EFI_OUT_OF_RESOURCES
;
1152 OpenData
->Signature
= OPEN_PROTOCOL_DATA_SIGNATURE
;
1153 OpenData
->AgentHandle
= ImageHandle
;
1154 OpenData
->ControllerHandle
= ControllerHandle
;
1155 OpenData
->Attributes
= Attributes
;
1156 OpenData
->OpenCount
= 1;
1157 InsertTailList (&Prot
->OpenList
, &OpenData
->Link
);
1158 Prot
->OpenListCount
++;
1159 Status
= EFI_SUCCESS
;
1164 if (Attributes
!= EFI_OPEN_PROTOCOL_TEST_PROTOCOL
) {
1166 // Keep Interface unmodified in case of any Error
1167 // except EFI_ALREADY_STARTED and EFI_UNSUPPORTED.
1169 if (!EFI_ERROR (Status
) || (Status
== EFI_ALREADY_STARTED
)) {
1171 // According to above logic, if 'Prot' is NULL, then the 'Status' must be
1172 // EFI_UNSUPPORTED. Here the 'Status' is not EFI_UNSUPPORTED, so 'Prot'
1173 // must be not NULL.
1175 // The ASSERT here is for addressing a false positive NULL pointer
1176 // dereference issue raised from static analysis.
1178 ASSERT (Prot
!= NULL
);
1180 // EFI_ALREADY_STARTED is not an error for bus driver.
1181 // Return the corresponding protocol interface.
1183 *Interface
= Prot
->Interface
;
1184 } else if (Status
== EFI_UNSUPPORTED
) {
1186 // Return NULL Interface if Unsupported Protocol.
1193 // Done. Release the database lock and return
1195 CoreReleaseProtocolLock ();
1200 Closes a protocol on a handle that was opened using OpenProtocol().
1202 @param UserHandle The handle for the protocol interface that was
1203 previously opened with OpenProtocol(), and is
1205 @param Protocol The published unique identifier of the protocol.
1206 It is the caller's responsibility to pass in a
1208 @param AgentHandle The handle of the agent that is closing the
1210 @param ControllerHandle If the agent that opened a protocol is a driver
1211 that follows the EFI Driver Model, then this
1212 parameter is the controller handle that required
1213 the protocol interface. If the agent does not
1214 follow the EFI Driver Model, then this parameter
1215 is optional and may be NULL.
1217 @retval EFI_SUCCESS The protocol instance was closed.
1218 @retval EFI_INVALID_PARAMETER Handle, AgentHandle or ControllerHandle is not a
1220 @retval EFI_NOT_FOUND Can not find the specified protocol or
1227 IN EFI_HANDLE UserHandle
,
1228 IN EFI_GUID
*Protocol
,
1229 IN EFI_HANDLE AgentHandle
,
1230 IN EFI_HANDLE ControllerHandle
1234 PROTOCOL_INTERFACE
*ProtocolInterface
;
1236 OPEN_PROTOCOL_DATA
*OpenData
;
1239 // Lock the protocol database
1241 CoreAcquireProtocolLock ();
1244 // Check for invalid parameters
1246 Status
= CoreValidateHandle (UserHandle
);
1247 if (EFI_ERROR (Status
)) {
1251 Status
= CoreValidateHandle (AgentHandle
);
1252 if (EFI_ERROR (Status
)) {
1256 if (ControllerHandle
!= NULL
) {
1257 Status
= CoreValidateHandle (ControllerHandle
);
1258 if (EFI_ERROR (Status
)) {
1263 if (Protocol
== NULL
) {
1264 Status
= EFI_INVALID_PARAMETER
;
1269 // Look at each protocol interface for a match
1271 Status
= EFI_NOT_FOUND
;
1272 ProtocolInterface
= CoreGetProtocolInterface (UserHandle
, Protocol
);
1273 if (ProtocolInterface
== NULL
) {
1278 // Walk the Open data base looking for AgentHandle
1280 Link
= ProtocolInterface
->OpenList
.ForwardLink
;
1281 while (Link
!= &ProtocolInterface
->OpenList
) {
1282 OpenData
= CR (Link
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
1283 Link
= Link
->ForwardLink
;
1284 if ((OpenData
->AgentHandle
== AgentHandle
) && (OpenData
->ControllerHandle
== ControllerHandle
)) {
1285 RemoveEntryList (&OpenData
->Link
);
1286 ProtocolInterface
->OpenListCount
--;
1287 CoreFreePool (OpenData
);
1288 Status
= EFI_SUCCESS
;
1294 // Done. Release the database lock and return.
1296 CoreReleaseProtocolLock ();
1301 Return information about Opened protocols in the system
1303 @param UserHandle The handle to close the protocol interface on
1304 @param Protocol The ID of the protocol
1305 @param EntryBuffer A pointer to a buffer of open protocol information in the
1306 form of EFI_OPEN_PROTOCOL_INFORMATION_ENTRY structures.
1307 @param EntryCount Number of EntryBuffer entries
1309 @retval EFI_SUCCESS The open protocol information was returned in EntryBuffer,
1310 and the number of entries was returned EntryCount.
1311 @retval EFI_NOT_FOUND Handle does not support the protocol specified by Protocol.
1312 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to allocate EntryBuffer.
1317 CoreOpenProtocolInformation (
1318 IN EFI_HANDLE UserHandle
,
1319 IN EFI_GUID
*Protocol
,
1320 OUT EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
**EntryBuffer
,
1321 OUT UINTN
*EntryCount
1325 PROTOCOL_INTERFACE
*ProtocolInterface
;
1327 OPEN_PROTOCOL_DATA
*OpenData
;
1328 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*Buffer
;
1332 *EntryBuffer
= NULL
;
1336 // Lock the protocol database
1338 CoreAcquireProtocolLock ();
1341 // Look at each protocol interface for a match
1343 Status
= EFI_NOT_FOUND
;
1344 ProtocolInterface
= CoreGetProtocolInterface (UserHandle
, Protocol
);
1345 if (ProtocolInterface
== NULL
) {
1350 // Count the number of Open Entries
1352 for ( Link
= ProtocolInterface
->OpenList
.ForwardLink
, Count
= 0;
1353 (Link
!= &ProtocolInterface
->OpenList
);
1354 Link
= Link
->ForwardLink
)
1359 ASSERT (Count
== ProtocolInterface
->OpenListCount
);
1362 Size
= sizeof (EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
);
1364 Size
= Count
* sizeof (EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
);
1367 Buffer
= AllocatePool (Size
);
1368 if (Buffer
== NULL
) {
1369 Status
= EFI_OUT_OF_RESOURCES
;
1373 Status
= EFI_SUCCESS
;
1374 for ( Link
= ProtocolInterface
->OpenList
.ForwardLink
, Count
= 0;
1375 (Link
!= &ProtocolInterface
->OpenList
);
1376 Link
= Link
->ForwardLink
, Count
++ )
1378 OpenData
= CR (Link
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
1380 Buffer
[Count
].AgentHandle
= OpenData
->AgentHandle
;
1381 Buffer
[Count
].ControllerHandle
= OpenData
->ControllerHandle
;
1382 Buffer
[Count
].Attributes
= OpenData
->Attributes
;
1383 Buffer
[Count
].OpenCount
= OpenData
->OpenCount
;
1386 *EntryBuffer
= Buffer
;
1387 *EntryCount
= Count
;
1391 // Done. Release the database lock.
1393 CoreReleaseProtocolLock ();
1398 Retrieves the list of protocol interface GUIDs that are installed on a handle in a buffer allocated
1401 @param UserHandle The handle from which to retrieve the list of
1402 protocol interface GUIDs.
1403 @param ProtocolBuffer A pointer to the list of protocol interface GUID
1404 pointers that are installed on Handle.
1405 @param ProtocolBufferCount A pointer to the number of GUID pointers present
1408 @retval EFI_SUCCESS The list of protocol interface GUIDs installed
1409 on Handle was returned in ProtocolBuffer. The
1410 number of protocol interface GUIDs was returned
1411 in ProtocolBufferCount.
1412 @retval EFI_INVALID_PARAMETER Handle is NULL.
1413 @retval EFI_INVALID_PARAMETER Handle is not a valid EFI_HANDLE.
1414 @retval EFI_INVALID_PARAMETER ProtocolBuffer is NULL.
1415 @retval EFI_INVALID_PARAMETER ProtocolBufferCount is NULL.
1416 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the
1422 CoreProtocolsPerHandle (
1423 IN EFI_HANDLE UserHandle
,
1424 OUT EFI_GUID
***ProtocolBuffer
,
1425 OUT UINTN
*ProtocolBufferCount
1430 PROTOCOL_INTERFACE
*Prot
;
1432 UINTN ProtocolCount
;
1435 if (ProtocolBuffer
== NULL
) {
1436 return EFI_INVALID_PARAMETER
;
1439 if (ProtocolBufferCount
== NULL
) {
1440 return EFI_INVALID_PARAMETER
;
1443 *ProtocolBufferCount
= 0;
1447 CoreAcquireProtocolLock ();
1449 Status
= CoreValidateHandle (UserHandle
);
1450 if (EFI_ERROR (Status
)) {
1454 Handle
= (IHANDLE
*)UserHandle
;
1456 for (Link
= Handle
->Protocols
.ForwardLink
; Link
!= &Handle
->Protocols
; Link
= Link
->ForwardLink
) {
1461 // If there are no protocol interfaces installed on Handle, then Handle is not a valid EFI_HANDLE
1463 if (ProtocolCount
== 0) {
1464 Status
= EFI_INVALID_PARAMETER
;
1468 Buffer
= AllocatePool (sizeof (EFI_GUID
*) * ProtocolCount
);
1469 if (Buffer
== NULL
) {
1470 Status
= EFI_OUT_OF_RESOURCES
;
1474 *ProtocolBuffer
= Buffer
;
1475 *ProtocolBufferCount
= ProtocolCount
;
1477 for ( Link
= Handle
->Protocols
.ForwardLink
, ProtocolCount
= 0;
1478 Link
!= &Handle
->Protocols
;
1479 Link
= Link
->ForwardLink
, ProtocolCount
++)
1481 Prot
= CR (Link
, PROTOCOL_INTERFACE
, Link
, PROTOCOL_INTERFACE_SIGNATURE
);
1482 Buffer
[ProtocolCount
] = &(Prot
->Protocol
->ProtocolID
);
1485 Status
= EFI_SUCCESS
;
1488 CoreReleaseProtocolLock ();
1493 return handle database key.
1496 @return Handle database key.
1500 CoreGetHandleDatabaseKey (
1504 return gHandleDatabaseKey
;
1508 Go connect any handles that were created or modified while a image executed.
1510 @param Key The Key to show that the handle has been
1515 CoreConnectHandlesByKey (
1521 EFI_HANDLE
*HandleBuffer
;
1526 // Lock the protocol database
1528 CoreAcquireProtocolLock ();
1530 for (Link
= gHandleList
.ForwardLink
, Count
= 0; Link
!= &gHandleList
; Link
= Link
->ForwardLink
) {
1531 Handle
= CR (Link
, IHANDLE
, AllHandles
, EFI_HANDLE_SIGNATURE
);
1532 if (Handle
->Key
> Key
) {
1537 HandleBuffer
= AllocatePool (Count
* sizeof (EFI_HANDLE
));
1538 if (HandleBuffer
== NULL
) {
1539 CoreReleaseProtocolLock ();
1543 for (Link
= gHandleList
.ForwardLink
, Count
= 0; Link
!= &gHandleList
; Link
= Link
->ForwardLink
) {
1544 Handle
= CR (Link
, IHANDLE
, AllHandles
, EFI_HANDLE_SIGNATURE
);
1545 if (Handle
->Key
> Key
) {
1546 HandleBuffer
[Count
++] = Handle
;
1551 // Unlock the protocol database
1553 CoreReleaseProtocolLock ();
1556 // Connect all handles whose Key value is greater than Key
1558 for (Index
= 0; Index
< Count
; Index
++) {
1559 CoreConnectController (HandleBuffer
[Index
], NULL
, NULL
, TRUE
);
1562 CoreFreePool (HandleBuffer
);