2 UEFI handle & protocol handling.
4 Copyright (c) 2006 - 2008, Intel Corporation. <BR>
5 All rights reserved. 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.
19 // mProtocolDatabase - A list of all protocols in the system. (simple list for now)
20 // gHandleList - A list of all the handles in the system
21 // gProtocolDatabaseLock - Lock to protect the mProtocolDatabase
22 // gHandleDatabaseKey - The Key to show that the handle has been created/modified
24 STATIC LIST_ENTRY mProtocolDatabase
= INITIALIZE_LIST_HEAD_VARIABLE (mProtocolDatabase
);
25 LIST_ENTRY gHandleList
= INITIALIZE_LIST_HEAD_VARIABLE (gHandleList
);
26 EFI_LOCK gProtocolDatabaseLock
= EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY
);
27 UINT64 gHandleDatabaseKey
= 0;
32 Acquire lock on gProtocolDatabaseLock.
36 CoreAcquireProtocolLock (
40 CoreAcquireLock (&gProtocolDatabaseLock
);
46 Release lock on gProtocolDatabaseLock.
50 CoreReleaseProtocolLock (
54 CoreReleaseLock (&gProtocolDatabaseLock
);
60 Check whether a handle is a valid EFI_HANDLE
62 @param UserHandle The handle to check
64 @retval EFI_INVALID_PARAMETER The handle is NULL or not a valid EFI_HANDLE.
65 @retval EFI_SUCCESS The handle is valid EFI_HANDLE.
70 IN EFI_HANDLE UserHandle
75 Handle
= (IHANDLE
*)UserHandle
;
77 return EFI_INVALID_PARAMETER
;
79 if (Handle
->Signature
!= EFI_HANDLE_SIGNATURE
) {
80 return EFI_INVALID_PARAMETER
;
88 Finds the protocol entry for the requested protocol.
89 The gProtocolDatabaseLock must be owned
91 @param Protocol The ID of the protocol
92 @param Create Create a new entry if not found
94 @return Protocol entry
98 CoreFindProtocolEntry (
99 IN EFI_GUID
*Protocol
,
104 PROTOCOL_ENTRY
*Item
;
105 PROTOCOL_ENTRY
*ProtEntry
;
107 ASSERT_LOCKED(&gProtocolDatabaseLock
);
110 // Search the database for the matching GUID
114 for (Link
= mProtocolDatabase
.ForwardLink
;
115 Link
!= &mProtocolDatabase
;
116 Link
= Link
->ForwardLink
) {
118 Item
= CR(Link
, PROTOCOL_ENTRY
, AllEntries
, PROTOCOL_ENTRY_SIGNATURE
);
119 if (CompareGuid (&Item
->ProtocolID
, Protocol
)) {
122 // This is the protocol entry
131 // If the protocol entry was not found and Create is TRUE, then
132 // allocate a new entry
134 if ((ProtEntry
== NULL
) && Create
) {
135 ProtEntry
= CoreAllocateBootServicesPool (sizeof(PROTOCOL_ENTRY
));
137 if (ProtEntry
!= NULL
) {
139 // Initialize new protocol entry structure
141 ProtEntry
->Signature
= PROTOCOL_ENTRY_SIGNATURE
;
142 CopyMem ((VOID
*)&ProtEntry
->ProtocolID
, Protocol
, sizeof (EFI_GUID
));
143 InitializeListHead (&ProtEntry
->Protocols
);
144 InitializeListHead (&ProtEntry
->Notify
);
147 // Add it to protocol database
149 InsertTailList (&mProtocolDatabase
, &ProtEntry
->AllEntries
);
159 Finds the protocol instance for the requested handle and protocol.
160 Note: This function doesn't do parameters checking, it's caller's responsibility
161 to pass in valid parameters.
163 @param Handle The handle to search the protocol on
164 @param Protocol GUID of the protocol
165 @param Interface The interface for the protocol being searched
167 @return Protocol instance (NULL: Not found)
171 CoreFindProtocolInterface (
173 IN EFI_GUID
*Protocol
,
177 PROTOCOL_INTERFACE
*Prot
;
178 PROTOCOL_ENTRY
*ProtEntry
;
181 ASSERT_LOCKED(&gProtocolDatabaseLock
);
185 // Lookup the protocol entry for this protocol ID
188 ProtEntry
= CoreFindProtocolEntry (Protocol
, FALSE
);
189 if (ProtEntry
!= NULL
) {
192 // Look at each protocol interface for any matches
194 for (Link
= Handle
->Protocols
.ForwardLink
; Link
!= &Handle
->Protocols
; Link
=Link
->ForwardLink
) {
197 // If this protocol interface matches, remove it
199 Prot
= CR(Link
, PROTOCOL_INTERFACE
, Link
, PROTOCOL_INTERFACE_SIGNATURE
);
200 if (Prot
->Interface
== Interface
&& Prot
->Protocol
== ProtEntry
) {
213 Removes an event from a register protocol notify list on a protocol.
215 @param Event The event to search for in the protocol
218 @return EFI_SUCCESS if the event was found and removed.
219 @return EFI_NOT_FOUND if the event was not found in the protocl database.
223 CoreUnregisterProtocolNotifyEvent (
228 PROTOCOL_ENTRY
*ProtEntry
;
229 LIST_ENTRY
*NotifyLink
;
230 PROTOCOL_NOTIFY
*ProtNotify
;
232 CoreAcquireProtocolLock ();
234 for ( Link
= mProtocolDatabase
.ForwardLink
;
235 Link
!= &mProtocolDatabase
;
236 Link
= Link
->ForwardLink
) {
238 ProtEntry
= CR(Link
, PROTOCOL_ENTRY
, AllEntries
, PROTOCOL_ENTRY_SIGNATURE
);
240 for ( NotifyLink
= ProtEntry
->Notify
.ForwardLink
;
241 NotifyLink
!= &ProtEntry
->Notify
;
242 NotifyLink
= NotifyLink
->ForwardLink
) {
244 ProtNotify
= CR(NotifyLink
, PROTOCOL_NOTIFY
, Link
, PROTOCOL_NOTIFY_SIGNATURE
);
246 if (ProtNotify
->Event
== Event
) {
247 RemoveEntryList(&ProtNotify
->Link
);
248 CoreFreePool(ProtNotify
);
249 CoreReleaseProtocolLock ();
255 CoreReleaseProtocolLock ();
256 return EFI_NOT_FOUND
;
262 Removes all the events in the protocol database that match Event.
264 @param Event The event to search for in the protocol
267 @return EFI_SUCCESS when done searching the entire database.
271 CoreUnregisterProtocolNotify (
278 Status
= CoreUnregisterProtocolNotifyEvent (Event
);
279 } while (!EFI_ERROR (Status
));
288 Wrapper function to CoreInstallProtocolInterfaceNotify. This is the public API which
289 Calls the private one which contains a BOOLEAN parameter for notifications
291 @param UserHandle The handle to install the protocol handler on,
292 or NULL if a new handle is to be allocated
293 @param Protocol The protocol to add to the handle
294 @param InterfaceType Indicates whether Interface is supplied in
296 @param Interface The interface for the protocol being added
303 CoreInstallProtocolInterface (
304 IN OUT EFI_HANDLE
*UserHandle
,
305 IN EFI_GUID
*Protocol
,
306 IN EFI_INTERFACE_TYPE InterfaceType
,
310 return CoreInstallProtocolInterfaceNotify (
321 Installs a protocol interface into the boot services environment.
323 @param UserHandle The handle to install the protocol handler on,
324 or NULL if a new handle is to be allocated
325 @param Protocol The protocol to add to the handle
326 @param InterfaceType Indicates whether Interface is supplied in
328 @param Interface The interface for the protocol being added
329 @param Notify indicates whether notify the notification list
332 @retval EFI_INVALID_PARAMETER Invalid parameter
333 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
334 @retval EFI_SUCCESS Protocol interface successfully installed
338 CoreInstallProtocolInterfaceNotify (
339 IN OUT EFI_HANDLE
*UserHandle
,
340 IN EFI_GUID
*Protocol
,
341 IN EFI_INTERFACE_TYPE InterfaceType
,
346 PROTOCOL_INTERFACE
*Prot
;
347 PROTOCOL_ENTRY
*ProtEntry
;
350 VOID
*ExistingInterface
;
353 // returns EFI_INVALID_PARAMETER if InterfaceType is invalid.
354 // Also added check for invalid UserHandle and Protocol pointers.
356 if (UserHandle
== NULL
|| Protocol
== NULL
) {
357 return EFI_INVALID_PARAMETER
;
360 if (InterfaceType
!= EFI_NATIVE_INTERFACE
) {
361 return EFI_INVALID_PARAMETER
;
365 // Print debug message
367 DEBUG((DEBUG_ERROR
| DEBUG_INFO
, "InstallProtocolInterface: %g %p\n", Protocol
, Interface
));
369 Status
= EFI_OUT_OF_RESOURCES
;
373 ASSERT (NULL
!= gDxeCoreBS
);
375 if (*UserHandle
!= NULL_HANDLE
) {
376 Status
= CoreHandleProtocol (*UserHandle
, Protocol
, (VOID
**)&ExistingInterface
);
377 if (!EFI_ERROR (Status
)) {
378 return EFI_INVALID_PARAMETER
;
383 // Lock the protocol database
385 CoreAcquireProtocolLock ();
388 // Lookup the Protocol Entry for the requested protocol
390 ProtEntry
= CoreFindProtocolEntry (Protocol
, TRUE
);
391 if (ProtEntry
== NULL
) {
396 // Allocate a new protocol interface structure
398 Prot
= CoreAllocateZeroBootServicesPool (sizeof(PROTOCOL_INTERFACE
));
400 Status
= EFI_OUT_OF_RESOURCES
;
405 // If caller didn't supply a handle, allocate a new one
407 Handle
= (IHANDLE
*)*UserHandle
;
408 if (Handle
== NULL
) {
409 Handle
= CoreAllocateZeroBootServicesPool (sizeof(IHANDLE
));
410 if (Handle
== NULL
) {
411 Status
= EFI_OUT_OF_RESOURCES
;
416 // Initialize new handler structure
418 Handle
->Signature
= EFI_HANDLE_SIGNATURE
;
419 InitializeListHead (&Handle
->Protocols
);
422 // Initialize the Key to show that the handle has been created/modified
424 gHandleDatabaseKey
++;
425 Handle
->Key
= gHandleDatabaseKey
;
428 // Add this handle to the list global list of all handles
431 InsertTailList (&gHandleList
, &Handle
->AllHandles
);
434 Status
= CoreValidateHandle (Handle
);
435 if (EFI_ERROR (Status
)) {
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
504 Installs a list of protocol interface into the boot services environment.
505 This function calls InstallProtocolInterface() in a loop. If any error
506 occures all the protocols added by this function are removed. This is
507 basically a lib function to save space.
509 @param Handle The handle to install the protocol handlers on,
510 or NULL if a new handle is to be allocated
511 @param ... EFI_GUID followed by protocol instance. A NULL
512 terminates the list. The pairs are the
513 arguments to InstallProtocolInterface(). All the
514 protocols are added to Handle.
516 @retval EFI_INVALID_PARAMETER Handle is NULL.
517 @retval EFI_SUCCESS Protocol interfaces successfully installed.
522 CoreInstallMultipleProtocolInterfaces (
523 IN OUT EFI_HANDLE
*Handle
,
533 EFI_HANDLE OldHandle
;
534 EFI_HANDLE DeviceHandle
;
535 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
537 if (Handle
== NULL
) {
538 return EFI_INVALID_PARAMETER
;
542 // Syncronize with notifcations.
544 OldTpl
= CoreRaiseTpl (TPL_NOTIFY
);
548 // Check for duplicate device path and install the protocol interfaces
550 VA_START (Args
, Handle
);
551 for (Index
= 0, Status
= EFI_SUCCESS
; !EFI_ERROR (Status
); Index
++) {
553 // If protocol is NULL, then it's the end of the list
555 Protocol
= VA_ARG (Args
, EFI_GUID
*);
556 if (Protocol
== NULL
) {
560 Interface
= VA_ARG (Args
, VOID
*);
563 // Make sure you are installing on top a device path that has already been added.
565 if (CompareGuid (Protocol
, &gEfiDevicePathProtocolGuid
)) {
567 DevicePath
= Interface
;
568 Status
= CoreLocateDevicePath (&gEfiDevicePathProtocolGuid
, &DevicePath
, &DeviceHandle
);
569 if (!EFI_ERROR (Status
) && (DeviceHandle
!= NULL_HANDLE
) && IsDevicePathEnd(DevicePath
)) {
570 Status
= EFI_ALREADY_STARTED
;
578 Status
= CoreInstallProtocolInterface (Handle
, Protocol
, EFI_NATIVE_INTERFACE
, Interface
);
582 // If there was an error, remove all the interfaces that were installed without any errors
584 if (EFI_ERROR (Status
)) {
586 // Reset the va_arg back to the first argument.
588 VA_START (Args
, Handle
);
589 for (; Index
> 1; Index
--) {
590 Protocol
= VA_ARG (Args
, EFI_GUID
*);
591 Interface
= VA_ARG (Args
, VOID
*);
592 CoreUninstallProtocolInterface (*Handle
, Protocol
, Interface
);
600 CoreRestoreTpl (OldTpl
);
606 Attempts to disconnect all drivers that are using the protocol interface being queried.
607 If failed, reconnect all drivers disconnected.
608 Note: This function doesn't do parameters checking, it's caller's responsibility
609 to pass in valid parameters.
611 @param UserHandle The handle on which the protocol is installed
612 @param Prot The protocol to disconnect drivers from
614 @retval EFI_SUCCESS Drivers using the protocol interface are all
616 @retval EFI_ACCESS_DENIED Failed to disconnect one or all of the drivers
620 CoreDisconnectControllersUsingProtocolInterface (
621 IN EFI_HANDLE UserHandle
,
622 IN PROTOCOL_INTERFACE
*Prot
628 OPEN_PROTOCOL_DATA
*OpenData
;
630 Status
= EFI_SUCCESS
;
633 // Attempt to disconnect all drivers from this protocol interface
637 for ( Link
= Prot
->OpenList
.ForwardLink
;
638 (Link
!= &Prot
->OpenList
) && !ItemFound
;
639 Link
= Link
->ForwardLink
) {
640 OpenData
= CR (Link
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
641 if (OpenData
->Attributes
& EFI_OPEN_PROTOCOL_BY_DRIVER
) {
643 CoreReleaseProtocolLock ();
644 Status
= CoreDisconnectController (UserHandle
, OpenData
->AgentHandle
, NULL
);
645 CoreAcquireProtocolLock ();
646 if (EFI_ERROR (Status
)) {
654 if (!EFI_ERROR (Status
)) {
656 // Attempt to remove BY_HANDLE_PROTOOCL and GET_PROTOCOL and TEST_PROTOCOL Open List items
660 for ( Link
= Prot
->OpenList
.ForwardLink
;
661 (Link
!= &Prot
->OpenList
) && !ItemFound
;
662 Link
= Link
->ForwardLink
) {
663 OpenData
= CR (Link
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
664 if (OpenData
->Attributes
&
665 (EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
| EFI_OPEN_PROTOCOL_GET_PROTOCOL
| EFI_OPEN_PROTOCOL_TEST_PROTOCOL
)) {
667 RemoveEntryList (&OpenData
->Link
);
668 Prot
->OpenListCount
--;
669 CoreFreePool (OpenData
);
676 // If there are errors or still has open items in the list, then reconnect all the drivers and return an error
678 if (EFI_ERROR (Status
) || (Prot
->OpenListCount
> 0)) {
679 CoreReleaseProtocolLock ();
680 CoreConnectController (UserHandle
, NULL
, NULL
, TRUE
);
681 CoreAcquireProtocolLock ();
682 Status
= EFI_ACCESS_DENIED
;
691 Uninstalls all instances of a protocol:interfacer from a handle.
692 If the last protocol interface is remove from the handle, the
695 @param UserHandle The handle to remove the protocol handler from
696 @param Protocol The protocol, of protocol:interface, to remove
697 @param Interface The interface, of protocol:interface, to remove
699 @retval EFI_INVALID_PARAMETER Protocol is NULL.
700 @retval EFI_SUCCESS Protocol interface successfully uninstalled.
705 CoreUninstallProtocolInterface (
706 IN EFI_HANDLE UserHandle
,
707 IN EFI_GUID
*Protocol
,
713 PROTOCOL_INTERFACE
*Prot
;
716 // Check that Protocol is valid
718 if (Protocol
== NULL
) {
719 return EFI_INVALID_PARAMETER
;
723 // Check that UserHandle is a valid handle
725 Status
= CoreValidateHandle (UserHandle
);
726 if (EFI_ERROR (Status
)) {
731 // Lock the protocol database
733 CoreAcquireProtocolLock ();
736 // Check that Protocol exists on UserHandle, and Interface matches the interface in the database
738 Prot
= CoreFindProtocolInterface (UserHandle
, Protocol
, Interface
);
740 Status
= EFI_NOT_FOUND
;
745 // Attempt to disconnect all drivers that are using the protocol interface that is about to be removed
747 Status
= CoreDisconnectControllersUsingProtocolInterface (
751 if (EFI_ERROR (Status
)) {
753 // One or more drivers refused to release, so return the error
759 // Remove the protocol interface from the protocol
761 Status
= EFI_NOT_FOUND
;
762 Handle
= (IHANDLE
*)UserHandle
;
763 Prot
= CoreRemoveInterfaceFromProtocol (Handle
, Protocol
, Interface
);
767 // Update the Key to show that the handle has been created/modified
769 gHandleDatabaseKey
++;
770 Handle
->Key
= gHandleDatabaseKey
;
773 // Remove the protocol interface from the handle
775 RemoveEntryList (&Prot
->Link
);
782 Status
= EFI_SUCCESS
;
786 // If there are no more handlers for the handle, free the handle
788 if (IsListEmpty (&Handle
->Protocols
)) {
789 Handle
->Signature
= 0;
790 RemoveEntryList (&Handle
->AllHandles
);
791 CoreFreePool (Handle
);
796 // Done, unlock the database and return
798 CoreReleaseProtocolLock ();
806 Uninstalls a list of protocol interface in the boot services environment.
807 This function calls UnisatllProtocolInterface() in a loop. This is
808 basically a lib function to save space.
810 @param Handle The handle to uninstall the protocol
811 @param ... EFI_GUID followed by protocol instance. A NULL
812 terminates the list. The pairs are the
813 arguments to UninstallProtocolInterface(). All
814 the protocols are added to Handle.
821 CoreUninstallMultipleProtocolInterfaces (
822 IN EFI_HANDLE Handle
,
832 VA_START (Args
, Handle
);
833 for (Index
= 0, Status
= EFI_SUCCESS
; !EFI_ERROR (Status
); Index
++) {
835 // If protocol is NULL, then it's the end of the list
837 Protocol
= VA_ARG (Args
, EFI_GUID
*);
838 if (Protocol
== NULL
) {
842 Interface
= VA_ARG (Args
, VOID
*);
847 Status
= CoreUninstallProtocolInterface (Handle
, Protocol
, Interface
);
851 // If there was an error, add all the interfaces that were
852 // uninstalled without any errors
854 if (EFI_ERROR (Status
)) {
856 // Reset the va_arg back to the first argument.
858 VA_START (Args
, Handle
);
859 for (; Index
> 1; Index
--) {
860 Protocol
= VA_ARG(Args
, EFI_GUID
*);
861 Interface
= VA_ARG(Args
, VOID
*);
862 CoreInstallProtocolInterface (&Handle
, Protocol
, EFI_NATIVE_INTERFACE
, Interface
);
871 Locate a certain GUID protocol interface in a Handle's protocols.
873 @param UserHandle The handle to obtain the protocol interface on
874 @param Protocol The GUID of the protocol
876 @return The requested protocol interface for the handle
880 CoreGetProtocolInterface (
881 IN EFI_HANDLE UserHandle
,
882 IN EFI_GUID
*Protocol
886 PROTOCOL_ENTRY
*ProtEntry
;
887 PROTOCOL_INTERFACE
*Prot
;
891 Status
= CoreValidateHandle (UserHandle
);
892 if (EFI_ERROR (Status
)) {
896 Handle
= (IHANDLE
*)UserHandle
;
899 // Look at each protocol interface for a match
901 for (Link
= Handle
->Protocols
.ForwardLink
; Link
!= &Handle
->Protocols
; Link
= Link
->ForwardLink
) {
902 Prot
= CR(Link
, PROTOCOL_INTERFACE
, Link
, PROTOCOL_INTERFACE_SIGNATURE
);
903 ProtEntry
= Prot
->Protocol
;
904 if (CompareGuid (&ProtEntry
->ProtocolID
, Protocol
)) {
914 Queries a handle to determine if it supports a specified protocol.
916 @param UserHandle The handle being queried.
917 @param Protocol The published unique identifier of the protocol.
918 @param Interface Supplies the address where a pointer to the
919 corresponding Protocol Interface is returned.
921 @return The requested protocol interface for the handle
927 IN EFI_HANDLE UserHandle
,
928 IN EFI_GUID
*Protocol
,
932 return CoreOpenProtocol (
938 EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
945 Locates the installed protocol handler for the handle, and
946 invokes it to obtain the protocol interface. Usage information
947 is registered in the protocol data base.
949 @param UserHandle The handle to obtain the protocol interface on
950 @param Protocol The ID of the protocol
951 @param Interface The location to return the protocol interface
952 @param ImageHandle The handle of the Image that is opening the
953 protocol interface specified by Protocol and
955 @param ControllerHandle The controller handle that is requiring this
957 @param Attributes The open mode of the protocol interface
958 specified by Handle and Protocol.
960 @retval EFI_INVALID_PARAMETER Protocol is NULL.
961 @retval EFI_SUCCESS Get the protocol interface.
967 IN EFI_HANDLE UserHandle
,
968 IN EFI_GUID
*Protocol
,
969 OUT VOID
**Interface OPTIONAL
,
970 IN EFI_HANDLE ImageHandle
,
971 IN EFI_HANDLE ControllerHandle
,
976 PROTOCOL_INTERFACE
*Prot
;
978 OPEN_PROTOCOL_DATA
*OpenData
;
985 // Check for invalid Protocol
987 if (Protocol
== NULL
) {
988 return EFI_INVALID_PARAMETER
;
992 // Check for invalid Interface
994 if (Attributes
!= EFI_OPEN_PROTOCOL_TEST_PROTOCOL
) {
995 if (Interface
== NULL
) {
996 return EFI_INVALID_PARAMETER
;
1003 // Check for invalid UserHandle
1005 Status
= CoreValidateHandle (UserHandle
);
1006 if (EFI_ERROR (Status
)) {
1011 // Check for invalid Attributes
1013 switch (Attributes
) {
1014 case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
:
1015 Status
= CoreValidateHandle (ImageHandle
);
1016 if (EFI_ERROR (Status
)) {
1019 Status
= CoreValidateHandle (ControllerHandle
);
1020 if (EFI_ERROR (Status
)) {
1023 if (UserHandle
== ControllerHandle
) {
1024 return EFI_INVALID_PARAMETER
;
1027 case EFI_OPEN_PROTOCOL_BY_DRIVER
:
1028 case EFI_OPEN_PROTOCOL_BY_DRIVER
| EFI_OPEN_PROTOCOL_EXCLUSIVE
:
1029 Status
= CoreValidateHandle (ImageHandle
);
1030 if (EFI_ERROR (Status
)) {
1033 Status
= CoreValidateHandle (ControllerHandle
);
1034 if (EFI_ERROR (Status
)) {
1038 case EFI_OPEN_PROTOCOL_EXCLUSIVE
:
1039 Status
= CoreValidateHandle (ImageHandle
);
1040 if (EFI_ERROR (Status
)) {
1044 case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
:
1045 case EFI_OPEN_PROTOCOL_GET_PROTOCOL
:
1046 case EFI_OPEN_PROTOCOL_TEST_PROTOCOL
:
1049 return EFI_INVALID_PARAMETER
;
1053 // Lock the protocol database
1055 CoreAcquireProtocolLock ();
1058 // Look at each protocol interface for a match
1060 Prot
= CoreGetProtocolInterface (UserHandle
, Protocol
);
1062 Status
= EFI_UNSUPPORTED
;
1067 // This is the protocol interface entry for this protocol
1069 if (Attributes
!= EFI_OPEN_PROTOCOL_TEST_PROTOCOL
) {
1070 *Interface
= Prot
->Interface
;
1072 Status
= EFI_SUCCESS
;
1076 for ( Link
= Prot
->OpenList
.ForwardLink
; Link
!= &Prot
->OpenList
; Link
= Link
->ForwardLink
) {
1077 OpenData
= CR (Link
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
1078 ExactMatch
= (BOOLEAN
)((OpenData
->AgentHandle
== ImageHandle
) &&
1079 (OpenData
->Attributes
== Attributes
) &&
1080 (OpenData
->ControllerHandle
== ControllerHandle
));
1081 if (OpenData
->Attributes
& EFI_OPEN_PROTOCOL_BY_DRIVER
) {
1084 Status
= EFI_ALREADY_STARTED
;
1088 if (OpenData
->Attributes
& EFI_OPEN_PROTOCOL_EXCLUSIVE
) {
1090 } else if (ExactMatch
) {
1091 OpenData
->OpenCount
++;
1092 Status
= EFI_SUCCESS
;
1098 // ByDriver TRUE -> A driver is managing (UserHandle, Protocol)
1099 // ByDriver FALSE -> There are no drivers managing (UserHandle, Protocol)
1100 // Exclusive TRUE -> Something has exclusive access to (UserHandle, Protocol)
1101 // Exclusive FALSE -> Nothing has exclusive access to (UserHandle, Protocol)
1104 switch (Attributes
) {
1105 case EFI_OPEN_PROTOCOL_BY_DRIVER
:
1106 if (Exclusive
|| ByDriver
) {
1107 Status
= EFI_ACCESS_DENIED
;
1111 case EFI_OPEN_PROTOCOL_BY_DRIVER
| EFI_OPEN_PROTOCOL_EXCLUSIVE
:
1112 case EFI_OPEN_PROTOCOL_EXCLUSIVE
:
1114 Status
= EFI_ACCESS_DENIED
;
1120 for ( Link
= Prot
->OpenList
.ForwardLink
; (Link
!= &Prot
->OpenList
) && (!Disconnect
); Link
= Link
->ForwardLink
) {
1121 OpenData
= CR (Link
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
1122 if (OpenData
->Attributes
& EFI_OPEN_PROTOCOL_BY_DRIVER
) {
1124 CoreReleaseProtocolLock ();
1125 Status
= CoreDisconnectController (UserHandle
, OpenData
->AgentHandle
, NULL
);
1126 CoreAcquireProtocolLock ();
1127 if (EFI_ERROR (Status
)) {
1128 Status
= EFI_ACCESS_DENIED
;
1133 } while (Disconnect
);
1136 case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
:
1137 case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
:
1138 case EFI_OPEN_PROTOCOL_GET_PROTOCOL
:
1139 case EFI_OPEN_PROTOCOL_TEST_PROTOCOL
:
1143 if (ImageHandle
== NULL
) {
1144 Status
= EFI_SUCCESS
;
1150 OpenData
= CoreAllocateBootServicesPool (sizeof(OPEN_PROTOCOL_DATA
));
1151 if (OpenData
== NULL
) {
1152 Status
= EFI_OUT_OF_RESOURCES
;
1154 OpenData
->Signature
= OPEN_PROTOCOL_DATA_SIGNATURE
;
1155 OpenData
->AgentHandle
= ImageHandle
;
1156 OpenData
->ControllerHandle
= ControllerHandle
;
1157 OpenData
->Attributes
= Attributes
;
1158 OpenData
->OpenCount
= 1;
1159 InsertTailList (&Prot
->OpenList
, &OpenData
->Link
);
1160 Prot
->OpenListCount
++;
1161 Status
= EFI_SUCCESS
;
1166 // Done. Release the database lock are return
1168 CoreReleaseProtocolLock ();
1175 Closes a protocol on a handle that was opened using OpenProtocol().
1177 @param UserHandle The handle for the protocol interface that was
1178 previously opened with OpenProtocol(), and is
1180 @param Protocol The published unique identifier of the protocol.
1181 It is the caller's responsibility to pass in a
1183 @param AgentHandle The handle of the agent that is closing the
1185 @param ControllerHandle If the agent that opened a protocol is a driver
1186 that follows the EFI Driver Model, then this
1187 parameter is the controller handle that required
1188 the protocol interface. If the agent does not
1189 follow the EFI Driver Model, then this parameter
1190 is optional and may be NULL.
1192 @retval EFI_SUCCESS The protocol instance was closed.
1193 @retval EFI_INVALID_PARAMETER Handle, AgentHandle or ControllerHandle is not a
1195 @retval EFI_NOT_FOUND Can not find the specified protocol or
1202 IN EFI_HANDLE UserHandle
,
1203 IN EFI_GUID
*Protocol
,
1204 IN EFI_HANDLE AgentHandle
,
1205 IN EFI_HANDLE ControllerHandle
1209 PROTOCOL_INTERFACE
*ProtocolInterface
;
1211 OPEN_PROTOCOL_DATA
*OpenData
;
1214 // Check for invalid parameters
1216 Status
= CoreValidateHandle (UserHandle
);
1217 if (EFI_ERROR (Status
)) {
1220 Status
= CoreValidateHandle (AgentHandle
);
1221 if (EFI_ERROR (Status
)) {
1224 if (ControllerHandle
!= NULL_HANDLE
) {
1225 Status
= CoreValidateHandle (ControllerHandle
);
1226 if (EFI_ERROR (Status
)) {
1230 if (Protocol
== NULL
) {
1231 return EFI_INVALID_PARAMETER
;
1235 // Lock the protocol database
1237 CoreAcquireProtocolLock ();
1240 // Look at each protocol interface for a match
1242 Status
= EFI_NOT_FOUND
;
1243 ProtocolInterface
= CoreGetProtocolInterface (UserHandle
, Protocol
);
1244 if (ProtocolInterface
== NULL
) {
1249 // Walk the Open data base looking for AgentHandle
1251 Link
= ProtocolInterface
->OpenList
.ForwardLink
;
1252 while (Link
!= &ProtocolInterface
->OpenList
) {
1253 OpenData
= CR (Link
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
1254 Link
= Link
->ForwardLink
;
1255 if ((OpenData
->AgentHandle
== AgentHandle
) && (OpenData
->ControllerHandle
== ControllerHandle
)) {
1256 RemoveEntryList (&OpenData
->Link
);
1257 ProtocolInterface
->OpenListCount
--;
1258 CoreFreePool (OpenData
);
1259 Status
= EFI_SUCCESS
;
1265 // Done. Release the database lock and return.
1267 CoreReleaseProtocolLock ();
1275 Return information about Opened protocols in the system
1277 @param UserHandle The handle to close the protocol interface on
1278 @param Protocol The ID of the protocol
1279 @param EntryBuffer A pointer to a buffer of open protocol
1280 information in the form of
1281 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY structures.
1282 @param EntryCount Number of EntryBuffer entries
1287 CoreOpenProtocolInformation (
1288 IN EFI_HANDLE UserHandle
,
1289 IN EFI_GUID
*Protocol
,
1290 OUT EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
**EntryBuffer
,
1291 OUT UINTN
*EntryCount
1295 PROTOCOL_INTERFACE
*ProtocolInterface
;
1297 OPEN_PROTOCOL_DATA
*OpenData
;
1298 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*Buffer
;
1302 *EntryBuffer
= NULL
;
1306 // Lock the protocol database
1308 CoreAcquireProtocolLock ();
1311 // Look at each protocol interface for a match
1313 Status
= EFI_NOT_FOUND
;
1314 ProtocolInterface
= CoreGetProtocolInterface (UserHandle
, Protocol
);
1315 if (ProtocolInterface
== NULL
) {
1320 // Count the number of Open Entries
1322 for ( Link
= ProtocolInterface
->OpenList
.ForwardLink
, Count
= 0;
1323 (Link
!= &ProtocolInterface
->OpenList
) ;
1324 Link
= Link
->ForwardLink
) {
1328 ASSERT (Count
== ProtocolInterface
->OpenListCount
);
1331 Size
= sizeof(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
);
1333 Size
= Count
* sizeof(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
);
1336 Buffer
= CoreAllocateBootServicesPool (Size
);
1337 if (Buffer
== NULL
) {
1338 Status
= EFI_OUT_OF_RESOURCES
;
1342 Status
= EFI_SUCCESS
;
1343 for ( Link
= ProtocolInterface
->OpenList
.ForwardLink
, Count
= 0;
1344 (Link
!= &ProtocolInterface
->OpenList
);
1345 Link
= Link
->ForwardLink
, Count
++ ) {
1346 OpenData
= CR (Link
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
1348 Buffer
[Count
].AgentHandle
= OpenData
->AgentHandle
;
1349 Buffer
[Count
].ControllerHandle
= OpenData
->ControllerHandle
;
1350 Buffer
[Count
].Attributes
= OpenData
->Attributes
;
1351 Buffer
[Count
].OpenCount
= OpenData
->OpenCount
;
1354 *EntryBuffer
= Buffer
;
1355 *EntryCount
= Count
;
1359 // Done. Release the database lock are return
1361 CoreReleaseProtocolLock ();
1369 Retrieves the list of protocol interface GUIDs that are installed on a handle in a buffer allocated
1372 @param UserHandle The handle from which to retrieve the list of
1373 protocol interface GUIDs.
1374 @param ProtocolBuffer A pointer to the list of protocol interface GUID
1375 pointers that are installed on Handle.
1376 @param ProtocolBufferCount A pointer to the number of GUID pointers present
1379 @retval EFI_SUCCESS The list of protocol interface GUIDs installed
1380 on Handle was returned in ProtocolBuffer. The
1381 number of protocol interface GUIDs was returned
1382 in ProtocolBufferCount.
1383 @retval EFI_INVALID_PARAMETER Handle is NULL.
1384 @retval EFI_INVALID_PARAMETER Handle is not a valid EFI_HANDLE.
1385 @retval EFI_INVALID_PARAMETER ProtocolBuffer is NULL.
1386 @retval EFI_INVALID_PARAMETER ProtocolBufferCount is NULL.
1387 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the
1393 CoreProtocolsPerHandle (
1394 IN EFI_HANDLE UserHandle
,
1395 OUT EFI_GUID
***ProtocolBuffer
,
1396 OUT UINTN
*ProtocolBufferCount
1401 PROTOCOL_INTERFACE
*Prot
;
1403 UINTN ProtocolCount
;
1406 Status
= CoreValidateHandle (UserHandle
);
1407 if (EFI_ERROR (Status
)) {
1411 Handle
= (IHANDLE
*)UserHandle
;
1413 if (ProtocolBuffer
== NULL
) {
1414 return EFI_INVALID_PARAMETER
;
1417 if (ProtocolBufferCount
== NULL
) {
1418 return EFI_INVALID_PARAMETER
;
1421 *ProtocolBufferCount
= 0;
1425 CoreAcquireProtocolLock ();
1427 for (Link
= Handle
->Protocols
.ForwardLink
; Link
!= &Handle
->Protocols
; Link
= Link
->ForwardLink
) {
1432 // If there are no protocol interfaces installed on Handle, then Handle is not a valid EFI_HANDLE
1434 if (ProtocolCount
== 0) {
1435 Status
= EFI_INVALID_PARAMETER
;
1439 Buffer
= CoreAllocateBootServicesPool (sizeof (EFI_GUID
*) * ProtocolCount
);
1440 if (Buffer
== NULL
) {
1441 Status
= EFI_OUT_OF_RESOURCES
;
1445 *ProtocolBuffer
= Buffer
;
1446 *ProtocolBufferCount
= ProtocolCount
;
1448 for ( Link
= Handle
->Protocols
.ForwardLink
, ProtocolCount
= 0;
1449 Link
!= &Handle
->Protocols
;
1450 Link
= Link
->ForwardLink
, ProtocolCount
++) {
1451 Prot
= CR(Link
, PROTOCOL_INTERFACE
, Link
, PROTOCOL_INTERFACE_SIGNATURE
);
1452 Buffer
[ProtocolCount
] = &(Prot
->Protocol
->ProtocolID
);
1454 Status
= EFI_SUCCESS
;
1457 CoreReleaseProtocolLock ();
1464 return handle database key.
1467 @return Handle database key.
1471 CoreGetHandleDatabaseKey (
1475 return gHandleDatabaseKey
;
1481 Go connect any handles that were created or modified while a image executed.
1483 @param Key The Key to show that the handle has been
1488 CoreConnectHandlesByKey (
1494 EFI_HANDLE
*HandleBuffer
;
1499 // Lock the protocol database
1501 CoreAcquireProtocolLock ();
1503 for (Link
= gHandleList
.ForwardLink
, Count
= 0; Link
!= &gHandleList
; Link
= Link
->ForwardLink
) {
1504 Handle
= CR (Link
, IHANDLE
, AllHandles
, EFI_HANDLE_SIGNATURE
);
1505 if (Handle
->Key
> Key
) {
1510 HandleBuffer
= CoreAllocateBootServicesPool (Count
* sizeof (EFI_HANDLE
));
1511 if (HandleBuffer
== NULL
) {
1512 CoreReleaseProtocolLock ();
1516 for (Link
= gHandleList
.ForwardLink
, Count
= 0; Link
!= &gHandleList
; Link
= Link
->ForwardLink
) {
1517 Handle
= CR (Link
, IHANDLE
, AllHandles
, EFI_HANDLE_SIGNATURE
);
1518 if (Handle
->Key
> Key
) {
1519 HandleBuffer
[Count
++] = Handle
;
1524 // Unlock the protocol database
1526 CoreReleaseProtocolLock ();
1529 // Connect all handles whose Key value is greater than Key
1531 for (Index
= 0; Index
< Count
; Index
++) {
1532 CoreConnectController (HandleBuffer
[Index
], NULL
, NULL
, TRUE
);
1535 CoreFreePool(HandleBuffer
);