3 UEFI handle & protocol handling
5 Copyright (c) 2006 - 2008, Intel Corporation
6 All rights reserved. This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 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 static 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;
32 CoreAcquireProtocolLock (
39 Acquire lock on gProtocolDatabaseLock.
51 CoreAcquireLock (&gProtocolDatabaseLock
);
56 CoreReleaseProtocolLock (
63 Release lock on gProtocolDatabaseLock.
75 CoreReleaseLock (&gProtocolDatabaseLock
);
81 IN EFI_HANDLE UserHandle
87 Check whether a handle is a valid EFI_HANDLE
91 UserHandle - The handle to check
95 EFI_INVALID_PARAMETER - The handle is NULL or not a valid EFI_HANDLE.
97 EFI_SUCCESS - The handle is valid EFI_HANDLE.
103 Handle
= (IHANDLE
*)UserHandle
;
104 if (Handle
== NULL
) {
105 return EFI_INVALID_PARAMETER
;
107 if (Handle
->Signature
!= EFI_HANDLE_SIGNATURE
) {
108 return EFI_INVALID_PARAMETER
;
115 CoreFindProtocolEntry (
116 IN EFI_GUID
*Protocol
,
123 Finds the protocol entry for the requested protocol.
125 The gProtocolDatabaseLock must be owned
129 Protocol - The ID of the protocol
131 Create - Create a new entry if not found
140 PROTOCOL_ENTRY
*Item
;
141 PROTOCOL_ENTRY
*ProtEntry
;
143 ASSERT_LOCKED(&gProtocolDatabaseLock
);
146 // Search the database for the matching GUID
150 for (Link
= mProtocolDatabase
.ForwardLink
;
151 Link
!= &mProtocolDatabase
;
152 Link
= Link
->ForwardLink
) {
154 Item
= CR(Link
, PROTOCOL_ENTRY
, AllEntries
, PROTOCOL_ENTRY_SIGNATURE
);
155 if (CompareGuid (&Item
->ProtocolID
, Protocol
)) {
158 // This is the protocol entry
167 // If the protocol entry was not found and Create is TRUE, then
168 // allocate a new entry
170 if ((ProtEntry
== NULL
) && Create
) {
171 ProtEntry
= CoreAllocateBootServicesPool (sizeof(PROTOCOL_ENTRY
));
173 if (ProtEntry
!= NULL
) {
175 // Initialize new protocol entry structure
177 ProtEntry
->Signature
= PROTOCOL_ENTRY_SIGNATURE
;
178 CopyMem ((VOID
*)&ProtEntry
->ProtocolID
, Protocol
, sizeof (EFI_GUID
));
179 InitializeListHead (&ProtEntry
->Protocols
);
180 InitializeListHead (&ProtEntry
->Notify
);
183 // Add it to protocol database
185 InsertTailList (&mProtocolDatabase
, &ProtEntry
->AllEntries
);
194 CoreFindProtocolInterface (
196 IN EFI_GUID
*Protocol
,
203 Finds the protocol instance for the requested handle and protocol.
205 Note: This function doesn't do parameters checking, it's caller's responsibility
206 to pass in valid parameters.
210 Handle - The handle to search the protocol on
212 Protocol - GUID of the protocol
214 Interface - The interface for the protocol being searched
218 Protocol instance (NULL: Not found)
222 PROTOCOL_INTERFACE
*Prot
;
223 PROTOCOL_ENTRY
*ProtEntry
;
226 ASSERT_LOCKED(&gProtocolDatabaseLock
);
230 // Lookup the protocol entry for this protocol ID
233 ProtEntry
= CoreFindProtocolEntry (Protocol
, FALSE
);
234 if (ProtEntry
!= NULL
) {
237 // Look at each protocol interface for any matches
239 for (Link
= Handle
->Protocols
.ForwardLink
; Link
!= &Handle
->Protocols
; Link
=Link
->ForwardLink
) {
242 // If this protocol interface matches, remove it
244 Prot
= CR(Link
, PROTOCOL_INTERFACE
, Link
, PROTOCOL_INTERFACE_SIGNATURE
);
245 if (Prot
->Interface
== Interface
&& Prot
->Protocol
== ProtEntry
) {
258 CoreUnregisterProtocolNotifyEvent (
265 Removes an event from a register protocol notify list on a protocol.
269 Event - The event to search for in the protocol database.
273 EFI_SUCCESS if the event was found and removed.
274 EFI_NOT_FOUND if the event was not found in the protocl database.
279 PROTOCOL_ENTRY
*ProtEntry
;
280 LIST_ENTRY
*NotifyLink
;
281 PROTOCOL_NOTIFY
*ProtNotify
;
283 CoreAcquireProtocolLock ();
285 for ( Link
= mProtocolDatabase
.ForwardLink
;
286 Link
!= &mProtocolDatabase
;
287 Link
= Link
->ForwardLink
) {
289 ProtEntry
= CR(Link
, PROTOCOL_ENTRY
, AllEntries
, PROTOCOL_ENTRY_SIGNATURE
);
291 for ( NotifyLink
= ProtEntry
->Notify
.ForwardLink
;
292 NotifyLink
!= &ProtEntry
->Notify
;
293 NotifyLink
= NotifyLink
->ForwardLink
) {
295 ProtNotify
= CR(NotifyLink
, PROTOCOL_NOTIFY
, Link
, PROTOCOL_NOTIFY_SIGNATURE
);
297 if (ProtNotify
->Event
== Event
) {
298 RemoveEntryList(&ProtNotify
->Link
);
299 CoreFreePool(ProtNotify
);
300 CoreReleaseProtocolLock ();
306 CoreReleaseProtocolLock ();
307 return EFI_NOT_FOUND
;
312 CoreUnregisterProtocolNotify (
319 Removes all the events in the protocol database that match Event.
323 Event - The event to search for in the protocol database.
327 EFI_SUCCESS when done searching the entire database.
334 Status
= CoreUnregisterProtocolNotifyEvent (Event
);
335 } while (!EFI_ERROR (Status
));
344 CoreInstallProtocolInterface (
345 IN OUT EFI_HANDLE
*UserHandle
,
346 IN EFI_GUID
*Protocol
,
347 IN EFI_INTERFACE_TYPE InterfaceType
,
354 Wrapper function to CoreInstallProtocolInterfaceNotify. This is the public API which
355 Calls the private one which contains a BOOLEAN parameter for notifications
359 UserHandle - The handle to install the protocol handler on,
360 or NULL if a new handle is to be allocated
362 Protocol - The protocol to add to the handle
364 InterfaceType - Indicates whether Interface is supplied in native form.
366 Interface - The interface for the protocol being added
374 return CoreInstallProtocolInterfaceNotify (
384 CoreInstallProtocolInterfaceNotify (
385 IN OUT EFI_HANDLE
*UserHandle
,
386 IN EFI_GUID
*Protocol
,
387 IN EFI_INTERFACE_TYPE InterfaceType
,
395 Installs a protocol interface into the boot services environment.
399 UserHandle - The handle to install the protocol handler on,
400 or NULL if a new handle is to be allocated
402 Protocol - The protocol to add to the handle
404 InterfaceType - Indicates whether Interface is supplied in native form.
406 Interface - The interface for the protocol being added
408 Notify - indicates whether notify the notification list
413 EFI_INVALID_PARAMETER - Invalid parameter
415 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
417 EFI_SUCCESS - Protocol interface successfully installed
421 PROTOCOL_INTERFACE
*Prot
;
422 PROTOCOL_ENTRY
*ProtEntry
;
425 VOID
*ExistingInterface
;
428 // returns EFI_INVALID_PARAMETER if InterfaceType is invalid.
429 // Also added check for invalid UserHandle and Protocol pointers.
431 if (UserHandle
== NULL
|| Protocol
== NULL
) {
432 return EFI_INVALID_PARAMETER
;
435 if (InterfaceType
!= EFI_NATIVE_INTERFACE
) {
436 return EFI_INVALID_PARAMETER
;
440 // Print debug message
442 DEBUG((EFI_D_ERROR
| EFI_D_INFO
, "InstallProtocolInterface: %g %p\n", Protocol
, Interface
));
444 Status
= EFI_OUT_OF_RESOURCES
;
448 ASSERT (NULL
!= gDxeCoreBS
);
450 if (*UserHandle
!= NULL_HANDLE
) {
451 Status
= CoreHandleProtocol (*UserHandle
, Protocol
, (VOID
**)&ExistingInterface
);
452 if (!EFI_ERROR (Status
)) {
453 return EFI_INVALID_PARAMETER
;
458 // Lock the protocol database
460 CoreAcquireProtocolLock ();
463 // Lookup the Protocol Entry for the requested protocol
465 ProtEntry
= CoreFindProtocolEntry (Protocol
, TRUE
);
466 if (ProtEntry
== NULL
) {
471 // Allocate a new protocol interface structure
473 Prot
= CoreAllocateZeroBootServicesPool (sizeof(PROTOCOL_INTERFACE
));
475 Status
= EFI_OUT_OF_RESOURCES
;
480 // If caller didn't supply a handle, allocate a new one
482 Handle
= (IHANDLE
*)*UserHandle
;
483 if (Handle
== NULL
) {
484 Handle
= CoreAllocateZeroBootServicesPool (sizeof(IHANDLE
));
485 if (Handle
== NULL
) {
486 Status
= EFI_OUT_OF_RESOURCES
;
491 // Initialize new handler structure
493 Handle
->Signature
= EFI_HANDLE_SIGNATURE
;
494 InitializeListHead (&Handle
->Protocols
);
497 // Initialize the Key to show that the handle has been created/modified
499 gHandleDatabaseKey
++;
500 Handle
->Key
= gHandleDatabaseKey
;
503 // Add this handle to the list global list of all handles
506 InsertTailList (&gHandleList
, &Handle
->AllHandles
);
509 Status
= CoreValidateHandle (Handle
);
510 if (EFI_ERROR (Status
)) {
515 // Each interface that is added must be unique
517 ASSERT (CoreFindProtocolInterface (Handle
, Protocol
, Interface
) == NULL
);
520 // Initialize the protocol interface structure
522 Prot
->Signature
= PROTOCOL_INTERFACE_SIGNATURE
;
523 Prot
->Handle
= Handle
;
524 Prot
->Protocol
= ProtEntry
;
525 Prot
->Interface
= Interface
;
528 // Initalize OpenProtocol Data base
530 InitializeListHead (&Prot
->OpenList
);
531 Prot
->OpenListCount
= 0;
534 // Add this protocol interface to the head of the supported
535 // protocol list for this handle
537 InsertHeadList (&Handle
->Protocols
, &Prot
->Link
);
540 // Add this protocol interface to the tail of the
543 InsertTailList (&ProtEntry
->Protocols
, &Prot
->ByProtocol
);
546 // Notify the notification list for this protocol
549 CoreNotifyProtocolEntry (ProtEntry
);
551 Status
= EFI_SUCCESS
;
555 // Done, unlock the database and return
557 CoreReleaseProtocolLock ();
558 if (!EFI_ERROR (Status
)) {
560 // Return the new handle back to the caller
562 *UserHandle
= Handle
;
565 // There was an error, clean up
579 CoreInstallMultipleProtocolInterfaces (
580 IN OUT EFI_HANDLE
*Handle
,
587 Installs a list of protocol interface into the boot services environment.
588 This function calls InstallProtocolInterface() in a loop. If any error
589 occures all the protocols added by this function are removed. This is
590 basically a lib function to save space.
594 Handle - The handle to install the protocol handlers on,
595 or NULL if a new handle is to be allocated
596 ... - EFI_GUID followed by protocol instance. A NULL terminates the
597 list. The pairs are the arguments to InstallProtocolInterface().
598 All the protocols are added to Handle.
602 EFI_INVALID_PARAMETER - Handle is NULL.
604 EFI_SUCCESS - Protocol interfaces successfully installed.
614 EFI_HANDLE OldHandle
;
615 EFI_HANDLE DeviceHandle
;
616 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
618 if (Handle
== NULL
) {
619 return EFI_INVALID_PARAMETER
;
623 // Syncronize with notifcations.
625 OldTpl
= CoreRaiseTpl (TPL_NOTIFY
);
629 // Check for duplicate device path and install the protocol interfaces
631 VA_START (args
, Handle
);
632 for (Index
= 0, Status
= EFI_SUCCESS
; !EFI_ERROR (Status
); Index
++) {
634 // If protocol is NULL, then it's the end of the list
636 Protocol
= VA_ARG (args
, EFI_GUID
*);
637 if (Protocol
== NULL
) {
641 Interface
= VA_ARG (args
, VOID
*);
644 // Make sure you are installing on top a device path that has already been added.
646 if (CompareGuid (Protocol
, &gEfiDevicePathProtocolGuid
)) {
648 DevicePath
= Interface
;
649 Status
= CoreLocateDevicePath (&gEfiDevicePathProtocolGuid
, &DevicePath
, &DeviceHandle
);
650 if (!EFI_ERROR (Status
) && (DeviceHandle
!= NULL_HANDLE
) && IsDevicePathEnd(DevicePath
)) {
651 Status
= EFI_ALREADY_STARTED
;
659 Status
= CoreInstallProtocolInterface (Handle
, Protocol
, EFI_NATIVE_INTERFACE
, Interface
);
663 // If there was an error, remove all the interfaces that were installed without any errors
665 if (EFI_ERROR (Status
)) {
667 // Reset the va_arg back to the first argument.
669 VA_START (args
, Handle
);
670 for (; Index
> 1; Index
--) {
671 Protocol
= VA_ARG (args
, EFI_GUID
*);
672 Interface
= VA_ARG (args
, VOID
*);
673 CoreUninstallProtocolInterface (*Handle
, Protocol
, Interface
);
681 CoreRestoreTpl (OldTpl
);
686 CoreDisconnectControllersUsingProtocolInterface (
687 IN EFI_HANDLE UserHandle
,
688 IN PROTOCOL_INTERFACE
*Prot
694 Attempts to disconnect all drivers that are using the protocol interface being queried.
695 If failed, reconnect all drivers disconnected.
697 Note: This function doesn't do parameters checking, it's caller's responsibility
698 to pass in valid parameters.
702 UserHandle - The handle on which the protocol is installed
703 Prot - The protocol to disconnect drivers from
707 EFI_SUCCESS - Drivers using the protocol interface are all disconnected
708 EFI_ACCESS_DENIED - Failed to disconnect one or all of the drivers
715 OPEN_PROTOCOL_DATA
*OpenData
;
717 Status
= EFI_SUCCESS
;
720 // Attempt to disconnect all drivers from this protocol interface
724 for ( Link
= Prot
->OpenList
.ForwardLink
;
725 (Link
!= &Prot
->OpenList
) && !ItemFound
;
726 Link
= Link
->ForwardLink
) {
727 OpenData
= CR (Link
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
728 if (OpenData
->Attributes
& EFI_OPEN_PROTOCOL_BY_DRIVER
) {
730 CoreReleaseProtocolLock ();
731 Status
= CoreDisconnectController (UserHandle
, OpenData
->AgentHandle
, NULL
);
732 CoreAcquireProtocolLock ();
733 if (EFI_ERROR (Status
)) {
741 if (!EFI_ERROR (Status
)) {
743 // Attempt to remove BY_HANDLE_PROTOOCL and GET_PROTOCOL and TEST_PROTOCOL Open List items
747 for ( Link
= Prot
->OpenList
.ForwardLink
;
748 (Link
!= &Prot
->OpenList
) && !ItemFound
;
749 Link
= Link
->ForwardLink
) {
750 OpenData
= CR (Link
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
751 if (OpenData
->Attributes
&
752 (EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
| EFI_OPEN_PROTOCOL_GET_PROTOCOL
| EFI_OPEN_PROTOCOL_TEST_PROTOCOL
)) {
754 RemoveEntryList (&OpenData
->Link
);
755 Prot
->OpenListCount
--;
756 CoreFreePool (OpenData
);
763 // If there are errors or still has open items in the list, then reconnect all the drivers and return an error
765 if (EFI_ERROR (Status
) || (Prot
->OpenListCount
> 0)) {
766 CoreReleaseProtocolLock ();
767 CoreConnectController (UserHandle
, NULL
, NULL
, TRUE
);
768 CoreAcquireProtocolLock ();
769 Status
= EFI_ACCESS_DENIED
;
778 CoreUninstallProtocolInterface (
779 IN EFI_HANDLE UserHandle
,
780 IN EFI_GUID
*Protocol
,
787 Uninstalls all instances of a protocol:interfacer from a handle.
788 If the last protocol interface is remove from the handle, the
793 UserHandle - The handle to remove the protocol handler from
795 Protocol - The protocol, of protocol:interface, to remove
797 Interface - The interface, of protocol:interface, to remove
801 EFI_INVALID_PARAMETER - Protocol is NULL.
803 EFI_SUCCESS - Protocol interface successfully uninstalled.
809 PROTOCOL_INTERFACE
*Prot
;
812 // Check that Protocol is valid
814 if (Protocol
== NULL
) {
815 return EFI_INVALID_PARAMETER
;
819 // Check that UserHandle is a valid handle
821 Status
= CoreValidateHandle (UserHandle
);
822 if (EFI_ERROR (Status
)) {
827 // Lock the protocol database
829 CoreAcquireProtocolLock ();
832 // Check that Protocol exists on UserHandle, and Interface matches the interface in the database
834 Prot
= CoreFindProtocolInterface (UserHandle
, Protocol
, Interface
);
836 Status
= EFI_NOT_FOUND
;
841 // Attempt to disconnect all drivers that are using the protocol interface that is about to be removed
843 Status
= CoreDisconnectControllersUsingProtocolInterface (
847 if (EFI_ERROR (Status
)) {
849 // One or more drivers refused to release, so return the error
855 // Remove the protocol interface from the protocol
857 Status
= EFI_NOT_FOUND
;
858 Handle
= (IHANDLE
*)UserHandle
;
859 Prot
= CoreRemoveInterfaceFromProtocol (Handle
, Protocol
, Interface
);
863 // Update the Key to show that the handle has been created/modified
865 gHandleDatabaseKey
++;
866 Handle
->Key
= gHandleDatabaseKey
;
869 // Remove the protocol interface from the handle
871 RemoveEntryList (&Prot
->Link
);
878 Status
= EFI_SUCCESS
;
882 // If there are no more handlers for the handle, free the handle
884 if (IsListEmpty (&Handle
->Protocols
)) {
885 Handle
->Signature
= 0;
886 RemoveEntryList (&Handle
->AllHandles
);
887 CoreFreePool (Handle
);
892 // Done, unlock the database and return
894 CoreReleaseProtocolLock ();
902 CoreUninstallMultipleProtocolInterfaces (
903 IN EFI_HANDLE Handle
,
910 Uninstalls a list of protocol interface in the boot services environment.
911 This function calls UnisatllProtocolInterface() in a loop. This is
912 basically a lib function to save space.
916 Handle - The handle to uninstall the protocol
918 ... - EFI_GUID followed by protocol instance. A NULL terminates the
919 list. The pairs are the arguments to UninstallProtocolInterface().
920 All the protocols are added to Handle.
934 VA_START (args
, Handle
);
935 for (Index
= 0, Status
= EFI_SUCCESS
; !EFI_ERROR (Status
); Index
++) {
937 // If protocol is NULL, then it's the end of the list
939 Protocol
= VA_ARG (args
, EFI_GUID
*);
940 if (Protocol
== NULL
) {
944 Interface
= VA_ARG (args
, VOID
*);
949 Status
= CoreUninstallProtocolInterface (Handle
, Protocol
, Interface
);
953 // If there was an error, add all the interfaces that were
954 // uninstalled without any errors
956 if (EFI_ERROR (Status
)) {
958 // Reset the va_arg back to the first argument.
960 VA_START (args
, Handle
);
961 for (; Index
> 1; Index
--) {
962 Protocol
= VA_ARG(args
, EFI_GUID
*);
963 Interface
= VA_ARG(args
, VOID
*);
964 CoreInstallProtocolInterface (&Handle
, Protocol
, EFI_NATIVE_INTERFACE
, Interface
);
973 CoreGetProtocolInterface (
974 IN EFI_HANDLE UserHandle
,
975 IN EFI_GUID
*Protocol
981 Locate a certain GUID protocol interface in a Handle's protocols.
985 UserHandle - The handle to obtain the protocol interface on
987 Protocol - The GUID of the protocol
991 The requested protocol interface for the handle
996 PROTOCOL_ENTRY
*ProtEntry
;
997 PROTOCOL_INTERFACE
*Prot
;
1001 Status
= CoreValidateHandle (UserHandle
);
1002 if (EFI_ERROR (Status
)) {
1006 Handle
= (IHANDLE
*)UserHandle
;
1009 // Look at each protocol interface for a match
1011 for (Link
= Handle
->Protocols
.ForwardLink
; Link
!= &Handle
->Protocols
; Link
= Link
->ForwardLink
) {
1012 Prot
= CR(Link
, PROTOCOL_INTERFACE
, Link
, PROTOCOL_INTERFACE_SIGNATURE
);
1013 ProtEntry
= Prot
->Protocol
;
1014 if (CompareGuid (&ProtEntry
->ProtocolID
, Protocol
)) {
1024 CoreHandleProtocol (
1025 IN EFI_HANDLE UserHandle
,
1026 IN EFI_GUID
*Protocol
,
1027 OUT VOID
**Interface
1031 Routine Description:
1033 Queries a handle to determine if it supports a specified protocol.
1037 UserHandle - The handle being queried.
1039 Protocol - The published unique identifier of the protocol.
1041 Interface - Supplies the address where a pointer to the corresponding Protocol
1042 Interface is returned.
1046 The requested protocol interface for the handle
1050 return CoreOpenProtocol (
1054 gDxeCoreImageHandle
,
1056 EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
1064 IN EFI_HANDLE UserHandle
,
1065 IN EFI_GUID
*Protocol
,
1066 OUT VOID
**Interface OPTIONAL
,
1067 IN EFI_HANDLE ImageHandle
,
1068 IN EFI_HANDLE ControllerHandle
,
1069 IN UINT32 Attributes
1073 Routine Description:
1075 Locates the installed protocol handler for the handle, and
1076 invokes it to obtain the protocol interface. Usage information
1077 is registered in the protocol data base.
1081 UserHandle - The handle to obtain the protocol interface on
1083 Protocol - The ID of the protocol
1085 Interface - The location to return the protocol interface
1087 ImageHandle - The handle of the Image that is opening the protocol interface
1088 specified by Protocol and Interface.
1090 ControllerHandle - The controller handle that is requiring this interface.
1092 Attributes - The open mode of the protocol interface specified by Handle
1097 EFI_INVALID_PARAMETER - Protocol is NULL.
1099 EFI_SUCCESS - Get the protocol interface.
1104 PROTOCOL_INTERFACE
*Prot
;
1106 OPEN_PROTOCOL_DATA
*OpenData
;
1113 // Check for invalid Protocol
1115 if (Protocol
== NULL
) {
1116 return EFI_INVALID_PARAMETER
;
1120 // Check for invalid Interface
1122 if (Attributes
!= EFI_OPEN_PROTOCOL_TEST_PROTOCOL
) {
1123 if (Interface
== NULL
) {
1124 return EFI_INVALID_PARAMETER
;
1131 // Check for invalid UserHandle
1133 Status
= CoreValidateHandle (UserHandle
);
1134 if (EFI_ERROR (Status
)) {
1139 // Check for invalid Attributes
1141 switch (Attributes
) {
1142 case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
:
1143 Status
= CoreValidateHandle (ImageHandle
);
1144 if (EFI_ERROR (Status
)) {
1147 Status
= CoreValidateHandle (ControllerHandle
);
1148 if (EFI_ERROR (Status
)) {
1151 if (UserHandle
== ControllerHandle
) {
1152 return EFI_INVALID_PARAMETER
;
1155 case EFI_OPEN_PROTOCOL_BY_DRIVER
:
1156 case EFI_OPEN_PROTOCOL_BY_DRIVER
| EFI_OPEN_PROTOCOL_EXCLUSIVE
:
1157 Status
= CoreValidateHandle (ImageHandle
);
1158 if (EFI_ERROR (Status
)) {
1161 Status
= CoreValidateHandle (ControllerHandle
);
1162 if (EFI_ERROR (Status
)) {
1166 case EFI_OPEN_PROTOCOL_EXCLUSIVE
:
1167 Status
= CoreValidateHandle (ImageHandle
);
1168 if (EFI_ERROR (Status
)) {
1172 case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
:
1173 case EFI_OPEN_PROTOCOL_GET_PROTOCOL
:
1174 case EFI_OPEN_PROTOCOL_TEST_PROTOCOL
:
1177 return EFI_INVALID_PARAMETER
;
1181 // Lock the protocol database
1183 CoreAcquireProtocolLock ();
1186 // Look at each protocol interface for a match
1188 Prot
= CoreGetProtocolInterface (UserHandle
, Protocol
);
1190 Status
= EFI_UNSUPPORTED
;
1195 // This is the protocol interface entry for this protocol
1197 if (Attributes
!= EFI_OPEN_PROTOCOL_TEST_PROTOCOL
) {
1198 *Interface
= Prot
->Interface
;
1200 Status
= EFI_SUCCESS
;
1204 for ( Link
= Prot
->OpenList
.ForwardLink
; Link
!= &Prot
->OpenList
; Link
= Link
->ForwardLink
) {
1205 OpenData
= CR (Link
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
1206 ExactMatch
= (BOOLEAN
)((OpenData
->AgentHandle
== ImageHandle
) &&
1207 (OpenData
->Attributes
== Attributes
) &&
1208 (OpenData
->ControllerHandle
== ControllerHandle
));
1209 if (OpenData
->Attributes
& EFI_OPEN_PROTOCOL_BY_DRIVER
) {
1212 Status
= EFI_ALREADY_STARTED
;
1216 if (OpenData
->Attributes
& EFI_OPEN_PROTOCOL_EXCLUSIVE
) {
1218 } else if (ExactMatch
) {
1219 OpenData
->OpenCount
++;
1220 Status
= EFI_SUCCESS
;
1226 // ByDriver TRUE -> A driver is managing (UserHandle, Protocol)
1227 // ByDriver FALSE -> There are no drivers managing (UserHandle, Protocol)
1228 // Exclusive TRUE -> Something has exclusive access to (UserHandle, Protocol)
1229 // Exclusive FALSE -> Nothing has exclusive access to (UserHandle, Protocol)
1232 switch (Attributes
) {
1233 case EFI_OPEN_PROTOCOL_BY_DRIVER
:
1234 if (Exclusive
|| ByDriver
) {
1235 Status
= EFI_ACCESS_DENIED
;
1239 case EFI_OPEN_PROTOCOL_BY_DRIVER
| EFI_OPEN_PROTOCOL_EXCLUSIVE
:
1240 case EFI_OPEN_PROTOCOL_EXCLUSIVE
:
1242 Status
= EFI_ACCESS_DENIED
;
1248 for ( Link
= Prot
->OpenList
.ForwardLink
; (Link
!= &Prot
->OpenList
) && (!Disconnect
); Link
= Link
->ForwardLink
) {
1249 OpenData
= CR (Link
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
1250 if (OpenData
->Attributes
& EFI_OPEN_PROTOCOL_BY_DRIVER
) {
1252 CoreReleaseProtocolLock ();
1253 Status
= CoreDisconnectController (UserHandle
, OpenData
->AgentHandle
, NULL
);
1254 CoreAcquireProtocolLock ();
1255 if (EFI_ERROR (Status
)) {
1256 Status
= EFI_ACCESS_DENIED
;
1261 } while (Disconnect
);
1264 case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
:
1265 case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
:
1266 case EFI_OPEN_PROTOCOL_GET_PROTOCOL
:
1267 case EFI_OPEN_PROTOCOL_TEST_PROTOCOL
:
1271 if (ImageHandle
== NULL
) {
1272 Status
= EFI_SUCCESS
;
1278 OpenData
= CoreAllocateBootServicesPool (sizeof(OPEN_PROTOCOL_DATA
));
1279 if (OpenData
== NULL
) {
1280 Status
= EFI_OUT_OF_RESOURCES
;
1282 OpenData
->Signature
= OPEN_PROTOCOL_DATA_SIGNATURE
;
1283 OpenData
->AgentHandle
= ImageHandle
;
1284 OpenData
->ControllerHandle
= ControllerHandle
;
1285 OpenData
->Attributes
= Attributes
;
1286 OpenData
->OpenCount
= 1;
1287 InsertTailList (&Prot
->OpenList
, &OpenData
->Link
);
1288 Prot
->OpenListCount
++;
1289 Status
= EFI_SUCCESS
;
1294 // Done. Release the database lock are return
1296 CoreReleaseProtocolLock ();
1304 IN EFI_HANDLE UserHandle
,
1305 IN EFI_GUID
*Protocol
,
1306 IN EFI_HANDLE AgentHandle
,
1307 IN EFI_HANDLE ControllerHandle
1311 Routine Description:
1313 Closes a protocol on a handle that was opened using OpenProtocol().
1317 UserHandle - The handle for the protocol interface that was previously opened
1318 with OpenProtocol(), and is now being closed.
1319 Protocol - The published unique identifier of the protocol. It is the caller's
1320 responsibility to pass in a valid GUID.
1321 AgentHandle - The handle of the agent that is closing the protocol interface.
1322 ControllerHandle - If the agent that opened a protocol is a driver that follows the
1323 EFI Driver Model, then this parameter is the controller handle
1324 that required the protocol interface. If the agent does not follow
1325 the EFI Driver Model, then this parameter is optional and may be NULL.
1329 EFI_SUCCESS - The protocol instance was closed.
1330 EFI_INVALID_PARAMETER - Handle, AgentHandle or ControllerHandle is not a valid EFI_HANDLE.
1331 EFI_NOT_FOUND - Can not find the specified protocol or AgentHandle.
1336 PROTOCOL_INTERFACE
*ProtocolInterface
;
1338 OPEN_PROTOCOL_DATA
*OpenData
;
1341 // Check for invalid parameters
1343 Status
= CoreValidateHandle (UserHandle
);
1344 if (EFI_ERROR (Status
)) {
1347 Status
= CoreValidateHandle (AgentHandle
);
1348 if (EFI_ERROR (Status
)) {
1351 if (ControllerHandle
!= NULL_HANDLE
) {
1352 Status
= CoreValidateHandle (ControllerHandle
);
1353 if (EFI_ERROR (Status
)) {
1357 if (Protocol
== NULL
) {
1358 return EFI_INVALID_PARAMETER
;
1362 // Lock the protocol database
1364 CoreAcquireProtocolLock ();
1367 // Look at each protocol interface for a match
1369 Status
= EFI_NOT_FOUND
;
1370 ProtocolInterface
= CoreGetProtocolInterface (UserHandle
, Protocol
);
1371 if (ProtocolInterface
== NULL
) {
1376 // Walk the Open data base looking for AgentHandle
1378 Link
= ProtocolInterface
->OpenList
.ForwardLink
;
1379 while (Link
!= &ProtocolInterface
->OpenList
) {
1380 OpenData
= CR (Link
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
1381 Link
= Link
->ForwardLink
;
1382 if ((OpenData
->AgentHandle
== AgentHandle
) && (OpenData
->ControllerHandle
== ControllerHandle
)) {
1383 RemoveEntryList (&OpenData
->Link
);
1384 ProtocolInterface
->OpenListCount
--;
1385 CoreFreePool (OpenData
);
1386 Status
= EFI_SUCCESS
;
1392 // Done. Release the database lock and return.
1394 CoreReleaseProtocolLock ();
1402 CoreOpenProtocolInformation (
1403 IN EFI_HANDLE UserHandle
,
1404 IN EFI_GUID
*Protocol
,
1405 OUT EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
**EntryBuffer
,
1406 OUT UINTN
*EntryCount
1410 Routine Description:
1412 Return information about Opened protocols in the system
1416 UserHandle - The handle to close the protocol interface on
1418 Protocol - The ID of the protocol
1420 EntryBuffer - A pointer to a buffer of open protocol information in the form of
1421 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY structures.
1423 EntryCount - Number of EntryBuffer entries
1431 PROTOCOL_INTERFACE
*ProtocolInterface
;
1433 OPEN_PROTOCOL_DATA
*OpenData
;
1434 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*Buffer
;
1438 *EntryBuffer
= NULL
;
1442 // Lock the protocol database
1444 CoreAcquireProtocolLock ();
1447 // Look at each protocol interface for a match
1449 Status
= EFI_NOT_FOUND
;
1450 ProtocolInterface
= CoreGetProtocolInterface (UserHandle
, Protocol
);
1451 if (ProtocolInterface
== NULL
) {
1456 // Count the number of Open Entries
1458 for ( Link
= ProtocolInterface
->OpenList
.ForwardLink
, Count
= 0;
1459 (Link
!= &ProtocolInterface
->OpenList
) ;
1460 Link
= Link
->ForwardLink
) {
1464 ASSERT (Count
== ProtocolInterface
->OpenListCount
);
1467 Size
= sizeof(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
);
1469 Size
= Count
* sizeof(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
);
1472 Buffer
= CoreAllocateBootServicesPool (Size
);
1473 if (Buffer
== NULL
) {
1474 Status
= EFI_OUT_OF_RESOURCES
;
1478 Status
= EFI_SUCCESS
;
1479 for ( Link
= ProtocolInterface
->OpenList
.ForwardLink
, Count
= 0;
1480 (Link
!= &ProtocolInterface
->OpenList
);
1481 Link
= Link
->ForwardLink
, Count
++ ) {
1482 OpenData
= CR (Link
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
1484 Buffer
[Count
].AgentHandle
= OpenData
->AgentHandle
;
1485 Buffer
[Count
].ControllerHandle
= OpenData
->ControllerHandle
;
1486 Buffer
[Count
].Attributes
= OpenData
->Attributes
;
1487 Buffer
[Count
].OpenCount
= OpenData
->OpenCount
;
1490 *EntryBuffer
= Buffer
;
1491 *EntryCount
= Count
;
1495 // Done. Release the database lock are return
1497 CoreReleaseProtocolLock ();
1505 CoreProtocolsPerHandle (
1506 IN EFI_HANDLE UserHandle
,
1507 OUT EFI_GUID
***ProtocolBuffer
,
1508 OUT UINTN
*ProtocolBufferCount
1512 Routine Description:
1514 Retrieves the list of protocol interface GUIDs that are installed on a handle in a buffer allocated
1519 UserHandle - The handle from which to retrieve the list of protocol interface
1522 ProtocolBuffer - A pointer to the list of protocol interface GUID pointers that are
1523 installed on Handle.
1525 ProtocolBufferCount - A pointer to the number of GUID pointers present in
1529 EFI_SUCCESS - The list of protocol interface GUIDs installed on Handle was returned in
1530 ProtocolBuffer. The number of protocol interface GUIDs was
1531 returned in ProtocolBufferCount.
1532 EFI_INVALID_PARAMETER - Handle is NULL.
1533 EFI_INVALID_PARAMETER - Handle is not a valid EFI_HANDLE.
1534 EFI_INVALID_PARAMETER - ProtocolBuffer is NULL.
1535 EFI_INVALID_PARAMETER - ProtocolBufferCount is NULL.
1536 EFI_OUT_OF_RESOURCES - There is not enough pool memory to store the results.
1542 PROTOCOL_INTERFACE
*Prot
;
1544 UINTN ProtocolCount
;
1547 Status
= CoreValidateHandle (UserHandle
);
1548 if (EFI_ERROR (Status
)) {
1552 Handle
= (IHANDLE
*)UserHandle
;
1554 if (ProtocolBuffer
== NULL
) {
1555 return EFI_INVALID_PARAMETER
;
1558 if (ProtocolBufferCount
== NULL
) {
1559 return EFI_INVALID_PARAMETER
;
1562 *ProtocolBufferCount
= 0;
1566 CoreAcquireProtocolLock ();
1568 for (Link
= Handle
->Protocols
.ForwardLink
; Link
!= &Handle
->Protocols
; Link
= Link
->ForwardLink
) {
1573 // If there are no protocol interfaces installed on Handle, then Handle is not a valid EFI_HANDLE
1575 if (ProtocolCount
== 0) {
1576 Status
= EFI_INVALID_PARAMETER
;
1580 Buffer
= CoreAllocateBootServicesPool (sizeof (EFI_GUID
*) * ProtocolCount
);
1581 if (Buffer
== NULL
) {
1582 Status
= EFI_OUT_OF_RESOURCES
;
1586 *ProtocolBuffer
= Buffer
;
1587 *ProtocolBufferCount
= ProtocolCount
;
1589 for ( Link
= Handle
->Protocols
.ForwardLink
, ProtocolCount
= 0;
1590 Link
!= &Handle
->Protocols
;
1591 Link
= Link
->ForwardLink
, ProtocolCount
++) {
1592 Prot
= CR(Link
, PROTOCOL_INTERFACE
, Link
, PROTOCOL_INTERFACE_SIGNATURE
);
1593 Buffer
[ProtocolCount
] = &(Prot
->Protocol
->ProtocolID
);
1595 Status
= EFI_SUCCESS
;
1598 CoreReleaseProtocolLock ();
1604 CoreGetHandleDatabaseKey (
1609 Routine Description:
1611 return handle database key.
1619 Handle database key.
1623 return gHandleDatabaseKey
;
1628 CoreConnectHandlesByKey (
1633 Routine Description:
1635 Go connect any handles that were created or modified while a image executed.
1639 Key - The Key to show that the handle has been created/modified
1648 EFI_HANDLE
*HandleBuffer
;
1653 // Lock the protocol database
1655 CoreAcquireProtocolLock ();
1657 for (Link
= gHandleList
.ForwardLink
, Count
= 0; Link
!= &gHandleList
; Link
= Link
->ForwardLink
) {
1658 Handle
= CR (Link
, IHANDLE
, AllHandles
, EFI_HANDLE_SIGNATURE
);
1659 if (Handle
->Key
> Key
) {
1664 HandleBuffer
= CoreAllocateBootServicesPool (Count
* sizeof (EFI_HANDLE
));
1665 if (HandleBuffer
== NULL
) {
1666 CoreReleaseProtocolLock ();
1670 for (Link
= gHandleList
.ForwardLink
, Count
= 0; Link
!= &gHandleList
; Link
= Link
->ForwardLink
) {
1671 Handle
= CR (Link
, IHANDLE
, AllHandles
, EFI_HANDLE_SIGNATURE
);
1672 if (Handle
->Key
> Key
) {
1673 HandleBuffer
[Count
++] = Handle
;
1678 // Unlock the protocol database
1680 CoreReleaseProtocolLock ();
1683 // Connect all handles whose Key value is greater than Key
1685 for (Index
= 0; Index
< Count
; Index
++) {
1686 CoreConnectController (HandleBuffer
[Index
], NULL
, NULL
, TRUE
);
1689 CoreFreePool(HandleBuffer
);