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;
33 Acquire lock on gProtocolDatabaseLock.
37 CoreAcquireProtocolLock (
41 CoreAcquireLock (&gProtocolDatabaseLock
);
47 Release lock on gProtocolDatabaseLock.
51 CoreReleaseProtocolLock (
55 CoreReleaseLock (&gProtocolDatabaseLock
);
61 Check whether a handle is a valid EFI_HANDLE
63 @param UserHandle The handle to check
65 @retval EFI_INVALID_PARAMETER The handle is NULL or not a valid EFI_HANDLE.
66 @retval EFI_SUCCESS The handle is valid EFI_HANDLE.
71 IN EFI_HANDLE UserHandle
76 Handle
= (IHANDLE
*)UserHandle
;
78 return EFI_INVALID_PARAMETER
;
80 if (Handle
->Signature
!= EFI_HANDLE_SIGNATURE
) {
81 return EFI_INVALID_PARAMETER
;
89 Finds the protocol entry for the requested protocol.
90 The gProtocolDatabaseLock must be owned
92 @param Protocol The ID of the protocol
93 @param Create Create a new entry if not found
95 @return Protocol entry
99 CoreFindProtocolEntry (
100 IN EFI_GUID
*Protocol
,
105 PROTOCOL_ENTRY
*Item
;
106 PROTOCOL_ENTRY
*ProtEntry
;
108 ASSERT_LOCKED(&gProtocolDatabaseLock
);
111 // Search the database for the matching GUID
115 for (Link
= mProtocolDatabase
.ForwardLink
;
116 Link
!= &mProtocolDatabase
;
117 Link
= Link
->ForwardLink
) {
119 Item
= CR(Link
, PROTOCOL_ENTRY
, AllEntries
, PROTOCOL_ENTRY_SIGNATURE
);
120 if (CompareGuid (&Item
->ProtocolID
, Protocol
)) {
123 // This is the protocol entry
132 // If the protocol entry was not found and Create is TRUE, then
133 // allocate a new entry
135 if ((ProtEntry
== NULL
) && Create
) {
136 ProtEntry
= CoreAllocateBootServicesPool (sizeof(PROTOCOL_ENTRY
));
138 if (ProtEntry
!= NULL
) {
140 // Initialize new protocol entry structure
142 ProtEntry
->Signature
= PROTOCOL_ENTRY_SIGNATURE
;
143 CopyMem ((VOID
*)&ProtEntry
->ProtocolID
, Protocol
, sizeof (EFI_GUID
));
144 InitializeListHead (&ProtEntry
->Protocols
);
145 InitializeListHead (&ProtEntry
->Notify
);
148 // Add it to protocol database
150 InsertTailList (&mProtocolDatabase
, &ProtEntry
->AllEntries
);
160 Finds the protocol instance for the requested handle and protocol.
161 Note: This function doesn't do parameters checking, it's caller's responsibility
162 to pass in valid parameters.
164 @param Handle The handle to search the protocol on
165 @param Protocol GUID of the protocol
166 @param Interface The interface for the protocol being searched
168 @return Protocol instance (NULL: Not found)
172 CoreFindProtocolInterface (
174 IN EFI_GUID
*Protocol
,
178 PROTOCOL_INTERFACE
*Prot
;
179 PROTOCOL_ENTRY
*ProtEntry
;
182 ASSERT_LOCKED(&gProtocolDatabaseLock
);
186 // Lookup the protocol entry for this protocol ID
189 ProtEntry
= CoreFindProtocolEntry (Protocol
, FALSE
);
190 if (ProtEntry
!= NULL
) {
193 // Look at each protocol interface for any matches
195 for (Link
= Handle
->Protocols
.ForwardLink
; Link
!= &Handle
->Protocols
; Link
=Link
->ForwardLink
) {
198 // If this protocol interface matches, remove it
200 Prot
= CR(Link
, PROTOCOL_INTERFACE
, Link
, PROTOCOL_INTERFACE_SIGNATURE
);
201 if (Prot
->Interface
== Interface
&& Prot
->Protocol
== ProtEntry
) {
214 Removes an event from a register protocol notify list on a protocol.
216 @param Event The event to search for in the protocol
219 @return EFI_SUCCESS if the event was found and removed.
220 @return EFI_NOT_FOUND if the event was not found in the protocl database.
225 CoreUnregisterProtocolNotifyEvent (
230 PROTOCOL_ENTRY
*ProtEntry
;
231 LIST_ENTRY
*NotifyLink
;
232 PROTOCOL_NOTIFY
*ProtNotify
;
234 CoreAcquireProtocolLock ();
236 for ( Link
= mProtocolDatabase
.ForwardLink
;
237 Link
!= &mProtocolDatabase
;
238 Link
= Link
->ForwardLink
) {
240 ProtEntry
= CR(Link
, PROTOCOL_ENTRY
, AllEntries
, PROTOCOL_ENTRY_SIGNATURE
);
242 for ( NotifyLink
= ProtEntry
->Notify
.ForwardLink
;
243 NotifyLink
!= &ProtEntry
->Notify
;
244 NotifyLink
= NotifyLink
->ForwardLink
) {
246 ProtNotify
= CR(NotifyLink
, PROTOCOL_NOTIFY
, Link
, PROTOCOL_NOTIFY_SIGNATURE
);
248 if (ProtNotify
->Event
== Event
) {
249 RemoveEntryList(&ProtNotify
->Link
);
250 CoreFreePool(ProtNotify
);
251 CoreReleaseProtocolLock ();
257 CoreReleaseProtocolLock ();
258 return EFI_NOT_FOUND
;
264 Removes all the events in the protocol database that match Event.
266 @param Event The event to search for in the protocol
269 @return EFI_SUCCESS when done searching the entire database.
273 CoreUnregisterProtocolNotify (
280 Status
= CoreUnregisterProtocolNotifyEvent (Event
);
281 } while (!EFI_ERROR (Status
));
290 Wrapper function to CoreInstallProtocolInterfaceNotify. This is the public API which
291 Calls the private one which contains a BOOLEAN parameter for notifications
293 @param UserHandle The handle to install the protocol handler on,
294 or NULL if a new handle is to be allocated
295 @param Protocol The protocol to add to the handle
296 @param InterfaceType Indicates whether Interface is supplied in
298 @param Interface The interface for the protocol being added
305 CoreInstallProtocolInterface (
306 IN OUT EFI_HANDLE
*UserHandle
,
307 IN EFI_GUID
*Protocol
,
308 IN EFI_INTERFACE_TYPE InterfaceType
,
312 return CoreInstallProtocolInterfaceNotify (
323 Installs a protocol interface into the boot services environment.
325 @param UserHandle The handle to install the protocol handler on,
326 or NULL if a new handle is to be allocated
327 @param Protocol The protocol to add to the handle
328 @param InterfaceType Indicates whether Interface is supplied in
330 @param Interface The interface for the protocol being added
331 @param Notify indicates whether notify the notification list
334 @retval EFI_INVALID_PARAMETER Invalid parameter
335 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
336 @retval EFI_SUCCESS Protocol interface successfully installed
340 CoreInstallProtocolInterfaceNotify (
341 IN OUT EFI_HANDLE
*UserHandle
,
342 IN EFI_GUID
*Protocol
,
343 IN EFI_INTERFACE_TYPE InterfaceType
,
348 PROTOCOL_INTERFACE
*Prot
;
349 PROTOCOL_ENTRY
*ProtEntry
;
352 VOID
*ExistingInterface
;
355 // returns EFI_INVALID_PARAMETER if InterfaceType is invalid.
356 // Also added check for invalid UserHandle and Protocol pointers.
358 if (UserHandle
== NULL
|| Protocol
== NULL
) {
359 return EFI_INVALID_PARAMETER
;
362 if (InterfaceType
!= EFI_NATIVE_INTERFACE
) {
363 return EFI_INVALID_PARAMETER
;
367 // Print debug message
369 DEBUG((DEBUG_ERROR
| DEBUG_INFO
, "InstallProtocolInterface: %g %p\n", Protocol
, Interface
));
371 Status
= EFI_OUT_OF_RESOURCES
;
375 ASSERT (NULL
!= gDxeCoreBS
);
377 if (*UserHandle
!= NULL_HANDLE
) {
378 Status
= CoreHandleProtocol (*UserHandle
, Protocol
, (VOID
**)&ExistingInterface
);
379 if (!EFI_ERROR (Status
)) {
380 return EFI_INVALID_PARAMETER
;
385 // Lock the protocol database
387 CoreAcquireProtocolLock ();
390 // Lookup the Protocol Entry for the requested protocol
392 ProtEntry
= CoreFindProtocolEntry (Protocol
, TRUE
);
393 if (ProtEntry
== NULL
) {
398 // Allocate a new protocol interface structure
400 Prot
= CoreAllocateZeroBootServicesPool (sizeof(PROTOCOL_INTERFACE
));
402 Status
= EFI_OUT_OF_RESOURCES
;
407 // If caller didn't supply a handle, allocate a new one
409 Handle
= (IHANDLE
*)*UserHandle
;
410 if (Handle
== NULL
) {
411 Handle
= CoreAllocateZeroBootServicesPool (sizeof(IHANDLE
));
412 if (Handle
== NULL
) {
413 Status
= EFI_OUT_OF_RESOURCES
;
418 // Initialize new handler structure
420 Handle
->Signature
= EFI_HANDLE_SIGNATURE
;
421 InitializeListHead (&Handle
->Protocols
);
424 // Initialize the Key to show that the handle has been created/modified
426 gHandleDatabaseKey
++;
427 Handle
->Key
= gHandleDatabaseKey
;
430 // Add this handle to the list global list of all handles
433 InsertTailList (&gHandleList
, &Handle
->AllHandles
);
436 Status
= CoreValidateHandle (Handle
);
437 if (EFI_ERROR (Status
)) {
442 // Each interface that is added must be unique
444 ASSERT (CoreFindProtocolInterface (Handle
, Protocol
, Interface
) == NULL
);
447 // Initialize the protocol interface structure
449 Prot
->Signature
= PROTOCOL_INTERFACE_SIGNATURE
;
450 Prot
->Handle
= Handle
;
451 Prot
->Protocol
= ProtEntry
;
452 Prot
->Interface
= Interface
;
455 // Initalize OpenProtocol Data base
457 InitializeListHead (&Prot
->OpenList
);
458 Prot
->OpenListCount
= 0;
461 // Add this protocol interface to the head of the supported
462 // protocol list for this handle
464 InsertHeadList (&Handle
->Protocols
, &Prot
->Link
);
467 // Add this protocol interface to the tail of the
470 InsertTailList (&ProtEntry
->Protocols
, &Prot
->ByProtocol
);
473 // Notify the notification list for this protocol
476 CoreNotifyProtocolEntry (ProtEntry
);
478 Status
= EFI_SUCCESS
;
482 // Done, unlock the database and return
484 CoreReleaseProtocolLock ();
485 if (!EFI_ERROR (Status
)) {
487 // Return the new handle back to the caller
489 *UserHandle
= Handle
;
492 // There was an error, clean up
506 Installs a list of protocol interface into the boot services environment.
507 This function calls InstallProtocolInterface() in a loop. If any error
508 occures all the protocols added by this function are removed. This is
509 basically a lib function to save space.
511 @param Handle The handle to install the protocol handlers on,
512 or NULL if a new handle is to be allocated
513 @param ... EFI_GUID followed by protocol instance. A NULL
514 terminates the list. The pairs are the
515 arguments to InstallProtocolInterface(). All the
516 protocols are added to Handle.
518 @retval EFI_INVALID_PARAMETER Handle is NULL.
519 @retval EFI_SUCCESS Protocol interfaces successfully installed.
524 CoreInstallMultipleProtocolInterfaces (
525 IN OUT EFI_HANDLE
*Handle
,
535 EFI_HANDLE OldHandle
;
536 EFI_HANDLE DeviceHandle
;
537 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
539 if (Handle
== NULL
) {
540 return EFI_INVALID_PARAMETER
;
544 // Syncronize with notifcations.
546 OldTpl
= CoreRaiseTpl (TPL_NOTIFY
);
550 // Check for duplicate device path and install the protocol interfaces
552 VA_START (Args
, Handle
);
553 for (Index
= 0, Status
= EFI_SUCCESS
; !EFI_ERROR (Status
); Index
++) {
555 // If protocol is NULL, then it's the end of the list
557 Protocol
= VA_ARG (Args
, EFI_GUID
*);
558 if (Protocol
== NULL
) {
562 Interface
= VA_ARG (Args
, VOID
*);
565 // Make sure you are installing on top a device path that has already been added.
567 if (CompareGuid (Protocol
, &gEfiDevicePathProtocolGuid
)) {
569 DevicePath
= Interface
;
570 Status
= CoreLocateDevicePath (&gEfiDevicePathProtocolGuid
, &DevicePath
, &DeviceHandle
);
571 if (!EFI_ERROR (Status
) && (DeviceHandle
!= NULL_HANDLE
) && IsDevicePathEnd(DevicePath
)) {
572 Status
= EFI_ALREADY_STARTED
;
580 Status
= CoreInstallProtocolInterface (Handle
, Protocol
, EFI_NATIVE_INTERFACE
, Interface
);
584 // If there was an error, remove all the interfaces that were installed without any errors
586 if (EFI_ERROR (Status
)) {
588 // Reset the va_arg back to the first argument.
590 VA_START (Args
, Handle
);
591 for (; Index
> 1; Index
--) {
592 Protocol
= VA_ARG (Args
, EFI_GUID
*);
593 Interface
= VA_ARG (Args
, VOID
*);
594 CoreUninstallProtocolInterface (*Handle
, Protocol
, Interface
);
602 CoreRestoreTpl (OldTpl
);
608 Attempts to disconnect all drivers that are using the protocol interface being queried.
609 If failed, reconnect all drivers disconnected.
610 Note: This function doesn't do parameters checking, it's caller's responsibility
611 to pass in valid parameters.
613 @param UserHandle The handle on which the protocol is installed
614 @param Prot The protocol to disconnect drivers from
616 @retval EFI_SUCCESS Drivers using the protocol interface are all
618 @retval EFI_ACCESS_DENIED Failed to disconnect one or all of the drivers
622 CoreDisconnectControllersUsingProtocolInterface (
623 IN EFI_HANDLE UserHandle
,
624 IN PROTOCOL_INTERFACE
*Prot
630 OPEN_PROTOCOL_DATA
*OpenData
;
632 Status
= EFI_SUCCESS
;
635 // Attempt to disconnect all drivers from this protocol interface
639 for ( Link
= Prot
->OpenList
.ForwardLink
;
640 (Link
!= &Prot
->OpenList
) && !ItemFound
;
641 Link
= Link
->ForwardLink
) {
642 OpenData
= CR (Link
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
643 if (OpenData
->Attributes
& EFI_OPEN_PROTOCOL_BY_DRIVER
) {
645 CoreReleaseProtocolLock ();
646 Status
= CoreDisconnectController (UserHandle
, OpenData
->AgentHandle
, NULL
);
647 CoreAcquireProtocolLock ();
648 if (EFI_ERROR (Status
)) {
656 if (!EFI_ERROR (Status
)) {
658 // Attempt to remove BY_HANDLE_PROTOOCL and GET_PROTOCOL and TEST_PROTOCOL Open List items
662 for ( Link
= Prot
->OpenList
.ForwardLink
;
663 (Link
!= &Prot
->OpenList
) && !ItemFound
;
664 Link
= Link
->ForwardLink
) {
665 OpenData
= CR (Link
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
666 if (OpenData
->Attributes
&
667 (EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
| EFI_OPEN_PROTOCOL_GET_PROTOCOL
| EFI_OPEN_PROTOCOL_TEST_PROTOCOL
)) {
669 RemoveEntryList (&OpenData
->Link
);
670 Prot
->OpenListCount
--;
671 CoreFreePool (OpenData
);
678 // If there are errors or still has open items in the list, then reconnect all the drivers and return an error
680 if (EFI_ERROR (Status
) || (Prot
->OpenListCount
> 0)) {
681 CoreReleaseProtocolLock ();
682 CoreConnectController (UserHandle
, NULL
, NULL
, TRUE
);
683 CoreAcquireProtocolLock ();
684 Status
= EFI_ACCESS_DENIED
;
693 Uninstalls all instances of a protocol:interfacer from a handle.
694 If the last protocol interface is remove from the handle, the
697 @param UserHandle The handle to remove the protocol handler from
698 @param Protocol The protocol, of protocol:interface, to remove
699 @param Interface The interface, of protocol:interface, to remove
701 @retval EFI_INVALID_PARAMETER Protocol is NULL.
702 @retval EFI_SUCCESS Protocol interface successfully uninstalled.
707 CoreUninstallProtocolInterface (
708 IN EFI_HANDLE UserHandle
,
709 IN EFI_GUID
*Protocol
,
715 PROTOCOL_INTERFACE
*Prot
;
718 // Check that Protocol is valid
720 if (Protocol
== NULL
) {
721 return EFI_INVALID_PARAMETER
;
725 // Check that UserHandle is a valid handle
727 Status
= CoreValidateHandle (UserHandle
);
728 if (EFI_ERROR (Status
)) {
733 // Lock the protocol database
735 CoreAcquireProtocolLock ();
738 // Check that Protocol exists on UserHandle, and Interface matches the interface in the database
740 Prot
= CoreFindProtocolInterface (UserHandle
, Protocol
, Interface
);
742 Status
= EFI_NOT_FOUND
;
747 // Attempt to disconnect all drivers that are using the protocol interface that is about to be removed
749 Status
= CoreDisconnectControllersUsingProtocolInterface (
753 if (EFI_ERROR (Status
)) {
755 // One or more drivers refused to release, so return the error
761 // Remove the protocol interface from the protocol
763 Status
= EFI_NOT_FOUND
;
764 Handle
= (IHANDLE
*)UserHandle
;
765 Prot
= CoreRemoveInterfaceFromProtocol (Handle
, Protocol
, Interface
);
769 // Update the Key to show that the handle has been created/modified
771 gHandleDatabaseKey
++;
772 Handle
->Key
= gHandleDatabaseKey
;
775 // Remove the protocol interface from the handle
777 RemoveEntryList (&Prot
->Link
);
784 Status
= EFI_SUCCESS
;
788 // If there are no more handlers for the handle, free the handle
790 if (IsListEmpty (&Handle
->Protocols
)) {
791 Handle
->Signature
= 0;
792 RemoveEntryList (&Handle
->AllHandles
);
793 CoreFreePool (Handle
);
798 // Done, unlock the database and return
800 CoreReleaseProtocolLock ();
808 Uninstalls a list of protocol interface in the boot services environment.
809 This function calls UnisatllProtocolInterface() in a loop. This is
810 basically a lib function to save space.
812 @param Handle The handle to uninstall the protocol
813 @param ... EFI_GUID followed by protocol instance. A NULL
814 terminates the list. The pairs are the
815 arguments to UninstallProtocolInterface(). All
816 the protocols are added to Handle.
823 CoreUninstallMultipleProtocolInterfaces (
824 IN EFI_HANDLE Handle
,
834 VA_START (Args
, Handle
);
835 for (Index
= 0, Status
= EFI_SUCCESS
; !EFI_ERROR (Status
); Index
++) {
837 // If protocol is NULL, then it's the end of the list
839 Protocol
= VA_ARG (Args
, EFI_GUID
*);
840 if (Protocol
== NULL
) {
844 Interface
= VA_ARG (Args
, VOID
*);
849 Status
= CoreUninstallProtocolInterface (Handle
, Protocol
, Interface
);
853 // If there was an error, add all the interfaces that were
854 // uninstalled without any errors
856 if (EFI_ERROR (Status
)) {
858 // Reset the va_arg back to the first argument.
860 VA_START (Args
, Handle
);
861 for (; Index
> 1; Index
--) {
862 Protocol
= VA_ARG(Args
, EFI_GUID
*);
863 Interface
= VA_ARG(Args
, VOID
*);
864 CoreInstallProtocolInterface (&Handle
, Protocol
, EFI_NATIVE_INTERFACE
, Interface
);
873 Locate a certain GUID protocol interface in a Handle's protocols.
875 @param UserHandle The handle to obtain the protocol interface on
876 @param Protocol The GUID of the protocol
878 @return The requested protocol interface for the handle
883 CoreGetProtocolInterface (
884 IN EFI_HANDLE UserHandle
,
885 IN EFI_GUID
*Protocol
889 PROTOCOL_ENTRY
*ProtEntry
;
890 PROTOCOL_INTERFACE
*Prot
;
894 Status
= CoreValidateHandle (UserHandle
);
895 if (EFI_ERROR (Status
)) {
899 Handle
= (IHANDLE
*)UserHandle
;
902 // Look at each protocol interface for a match
904 for (Link
= Handle
->Protocols
.ForwardLink
; Link
!= &Handle
->Protocols
; Link
= Link
->ForwardLink
) {
905 Prot
= CR(Link
, PROTOCOL_INTERFACE
, Link
, PROTOCOL_INTERFACE_SIGNATURE
);
906 ProtEntry
= Prot
->Protocol
;
907 if (CompareGuid (&ProtEntry
->ProtocolID
, Protocol
)) {
917 Queries a handle to determine if it supports a specified protocol.
919 @param UserHandle The handle being queried.
920 @param Protocol The published unique identifier of the protocol.
921 @param Interface Supplies the address where a pointer to the
922 corresponding Protocol Interface is returned.
924 @return The requested protocol interface for the handle
930 IN EFI_HANDLE UserHandle
,
931 IN EFI_GUID
*Protocol
,
935 return CoreOpenProtocol (
941 EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
948 Locates the installed protocol handler for the handle, and
949 invokes it to obtain the protocol interface. Usage information
950 is registered in the protocol data base.
952 @param UserHandle The handle to obtain the protocol interface on
953 @param Protocol The ID of the protocol
954 @param Interface The location to return the protocol interface
955 @param ImageHandle The handle of the Image that is opening the
956 protocol interface specified by Protocol and
958 @param ControllerHandle The controller handle that is requiring this
960 @param Attributes The open mode of the protocol interface
961 specified by Handle and Protocol.
963 @retval EFI_INVALID_PARAMETER Protocol is NULL.
964 @retval EFI_SUCCESS Get the protocol interface.
970 IN EFI_HANDLE UserHandle
,
971 IN EFI_GUID
*Protocol
,
972 OUT VOID
**Interface OPTIONAL
,
973 IN EFI_HANDLE ImageHandle
,
974 IN EFI_HANDLE ControllerHandle
,
979 PROTOCOL_INTERFACE
*Prot
;
981 OPEN_PROTOCOL_DATA
*OpenData
;
988 // Check for invalid Protocol
990 if (Protocol
== NULL
) {
991 return EFI_INVALID_PARAMETER
;
995 // Check for invalid Interface
997 if (Attributes
!= EFI_OPEN_PROTOCOL_TEST_PROTOCOL
) {
998 if (Interface
== NULL
) {
999 return EFI_INVALID_PARAMETER
;
1006 // Check for invalid UserHandle
1008 Status
= CoreValidateHandle (UserHandle
);
1009 if (EFI_ERROR (Status
)) {
1014 // Check for invalid Attributes
1016 switch (Attributes
) {
1017 case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
:
1018 Status
= CoreValidateHandle (ImageHandle
);
1019 if (EFI_ERROR (Status
)) {
1022 Status
= CoreValidateHandle (ControllerHandle
);
1023 if (EFI_ERROR (Status
)) {
1026 if (UserHandle
== ControllerHandle
) {
1027 return EFI_INVALID_PARAMETER
;
1030 case EFI_OPEN_PROTOCOL_BY_DRIVER
:
1031 case EFI_OPEN_PROTOCOL_BY_DRIVER
| EFI_OPEN_PROTOCOL_EXCLUSIVE
:
1032 Status
= CoreValidateHandle (ImageHandle
);
1033 if (EFI_ERROR (Status
)) {
1036 Status
= CoreValidateHandle (ControllerHandle
);
1037 if (EFI_ERROR (Status
)) {
1041 case EFI_OPEN_PROTOCOL_EXCLUSIVE
:
1042 Status
= CoreValidateHandle (ImageHandle
);
1043 if (EFI_ERROR (Status
)) {
1047 case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
:
1048 case EFI_OPEN_PROTOCOL_GET_PROTOCOL
:
1049 case EFI_OPEN_PROTOCOL_TEST_PROTOCOL
:
1052 return EFI_INVALID_PARAMETER
;
1056 // Lock the protocol database
1058 CoreAcquireProtocolLock ();
1061 // Look at each protocol interface for a match
1063 Prot
= CoreGetProtocolInterface (UserHandle
, Protocol
);
1065 Status
= EFI_UNSUPPORTED
;
1070 // This is the protocol interface entry for this protocol
1072 if (Attributes
!= EFI_OPEN_PROTOCOL_TEST_PROTOCOL
) {
1073 *Interface
= Prot
->Interface
;
1075 Status
= EFI_SUCCESS
;
1079 for ( Link
= Prot
->OpenList
.ForwardLink
; Link
!= &Prot
->OpenList
; Link
= Link
->ForwardLink
) {
1080 OpenData
= CR (Link
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
1081 ExactMatch
= (BOOLEAN
)((OpenData
->AgentHandle
== ImageHandle
) &&
1082 (OpenData
->Attributes
== Attributes
) &&
1083 (OpenData
->ControllerHandle
== ControllerHandle
));
1084 if (OpenData
->Attributes
& EFI_OPEN_PROTOCOL_BY_DRIVER
) {
1087 Status
= EFI_ALREADY_STARTED
;
1091 if (OpenData
->Attributes
& EFI_OPEN_PROTOCOL_EXCLUSIVE
) {
1093 } else if (ExactMatch
) {
1094 OpenData
->OpenCount
++;
1095 Status
= EFI_SUCCESS
;
1101 // ByDriver TRUE -> A driver is managing (UserHandle, Protocol)
1102 // ByDriver FALSE -> There are no drivers managing (UserHandle, Protocol)
1103 // Exclusive TRUE -> Something has exclusive access to (UserHandle, Protocol)
1104 // Exclusive FALSE -> Nothing has exclusive access to (UserHandle, Protocol)
1107 switch (Attributes
) {
1108 case EFI_OPEN_PROTOCOL_BY_DRIVER
:
1109 if (Exclusive
|| ByDriver
) {
1110 Status
= EFI_ACCESS_DENIED
;
1114 case EFI_OPEN_PROTOCOL_BY_DRIVER
| EFI_OPEN_PROTOCOL_EXCLUSIVE
:
1115 case EFI_OPEN_PROTOCOL_EXCLUSIVE
:
1117 Status
= EFI_ACCESS_DENIED
;
1123 for ( Link
= Prot
->OpenList
.ForwardLink
; (Link
!= &Prot
->OpenList
) && (!Disconnect
); Link
= Link
->ForwardLink
) {
1124 OpenData
= CR (Link
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
1125 if (OpenData
->Attributes
& EFI_OPEN_PROTOCOL_BY_DRIVER
) {
1127 CoreReleaseProtocolLock ();
1128 Status
= CoreDisconnectController (UserHandle
, OpenData
->AgentHandle
, NULL
);
1129 CoreAcquireProtocolLock ();
1130 if (EFI_ERROR (Status
)) {
1131 Status
= EFI_ACCESS_DENIED
;
1136 } while (Disconnect
);
1139 case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
:
1140 case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
:
1141 case EFI_OPEN_PROTOCOL_GET_PROTOCOL
:
1142 case EFI_OPEN_PROTOCOL_TEST_PROTOCOL
:
1146 if (ImageHandle
== NULL
) {
1147 Status
= EFI_SUCCESS
;
1153 OpenData
= CoreAllocateBootServicesPool (sizeof(OPEN_PROTOCOL_DATA
));
1154 if (OpenData
== NULL
) {
1155 Status
= EFI_OUT_OF_RESOURCES
;
1157 OpenData
->Signature
= OPEN_PROTOCOL_DATA_SIGNATURE
;
1158 OpenData
->AgentHandle
= ImageHandle
;
1159 OpenData
->ControllerHandle
= ControllerHandle
;
1160 OpenData
->Attributes
= Attributes
;
1161 OpenData
->OpenCount
= 1;
1162 InsertTailList (&Prot
->OpenList
, &OpenData
->Link
);
1163 Prot
->OpenListCount
++;
1164 Status
= EFI_SUCCESS
;
1169 // Done. Release the database lock are return
1171 CoreReleaseProtocolLock ();
1178 Closes a protocol on a handle that was opened using OpenProtocol().
1180 @param UserHandle The handle for the protocol interface that was
1181 previously opened with OpenProtocol(), and is
1183 @param Protocol The published unique identifier of the protocol.
1184 It is the caller's responsibility to pass in a
1186 @param AgentHandle The handle of the agent that is closing the
1188 @param ControllerHandle If the agent that opened a protocol is a driver
1189 that follows the EFI Driver Model, then this
1190 parameter is the controller handle that required
1191 the protocol interface. If the agent does not
1192 follow the EFI Driver Model, then this parameter
1193 is optional and may be NULL.
1195 @retval EFI_SUCCESS The protocol instance was closed.
1196 @retval EFI_INVALID_PARAMETER Handle, AgentHandle or ControllerHandle is not a
1198 @retval EFI_NOT_FOUND Can not find the specified protocol or
1205 IN EFI_HANDLE UserHandle
,
1206 IN EFI_GUID
*Protocol
,
1207 IN EFI_HANDLE AgentHandle
,
1208 IN EFI_HANDLE ControllerHandle
1212 PROTOCOL_INTERFACE
*ProtocolInterface
;
1214 OPEN_PROTOCOL_DATA
*OpenData
;
1217 // Check for invalid parameters
1219 Status
= CoreValidateHandle (UserHandle
);
1220 if (EFI_ERROR (Status
)) {
1223 Status
= CoreValidateHandle (AgentHandle
);
1224 if (EFI_ERROR (Status
)) {
1227 if (ControllerHandle
!= NULL_HANDLE
) {
1228 Status
= CoreValidateHandle (ControllerHandle
);
1229 if (EFI_ERROR (Status
)) {
1233 if (Protocol
== NULL
) {
1234 return EFI_INVALID_PARAMETER
;
1238 // Lock the protocol database
1240 CoreAcquireProtocolLock ();
1243 // Look at each protocol interface for a match
1245 Status
= EFI_NOT_FOUND
;
1246 ProtocolInterface
= CoreGetProtocolInterface (UserHandle
, Protocol
);
1247 if (ProtocolInterface
== NULL
) {
1252 // Walk the Open data base looking for AgentHandle
1254 Link
= ProtocolInterface
->OpenList
.ForwardLink
;
1255 while (Link
!= &ProtocolInterface
->OpenList
) {
1256 OpenData
= CR (Link
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
1257 Link
= Link
->ForwardLink
;
1258 if ((OpenData
->AgentHandle
== AgentHandle
) && (OpenData
->ControllerHandle
== ControllerHandle
)) {
1259 RemoveEntryList (&OpenData
->Link
);
1260 ProtocolInterface
->OpenListCount
--;
1261 CoreFreePool (OpenData
);
1262 Status
= EFI_SUCCESS
;
1268 // Done. Release the database lock and return.
1270 CoreReleaseProtocolLock ();
1278 Return information about Opened protocols in the system
1280 @param UserHandle The handle to close the protocol interface on
1281 @param Protocol The ID of the protocol
1282 @param EntryBuffer A pointer to a buffer of open protocol
1283 information in the form of
1284 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY structures.
1285 @param EntryCount Number of EntryBuffer entries
1290 CoreOpenProtocolInformation (
1291 IN EFI_HANDLE UserHandle
,
1292 IN EFI_GUID
*Protocol
,
1293 OUT EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
**EntryBuffer
,
1294 OUT UINTN
*EntryCount
1298 PROTOCOL_INTERFACE
*ProtocolInterface
;
1300 OPEN_PROTOCOL_DATA
*OpenData
;
1301 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*Buffer
;
1305 *EntryBuffer
= NULL
;
1309 // Lock the protocol database
1311 CoreAcquireProtocolLock ();
1314 // Look at each protocol interface for a match
1316 Status
= EFI_NOT_FOUND
;
1317 ProtocolInterface
= CoreGetProtocolInterface (UserHandle
, Protocol
);
1318 if (ProtocolInterface
== NULL
) {
1323 // Count the number of Open Entries
1325 for ( Link
= ProtocolInterface
->OpenList
.ForwardLink
, Count
= 0;
1326 (Link
!= &ProtocolInterface
->OpenList
) ;
1327 Link
= Link
->ForwardLink
) {
1331 ASSERT (Count
== ProtocolInterface
->OpenListCount
);
1334 Size
= sizeof(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
);
1336 Size
= Count
* sizeof(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
);
1339 Buffer
= CoreAllocateBootServicesPool (Size
);
1340 if (Buffer
== NULL
) {
1341 Status
= EFI_OUT_OF_RESOURCES
;
1345 Status
= EFI_SUCCESS
;
1346 for ( Link
= ProtocolInterface
->OpenList
.ForwardLink
, Count
= 0;
1347 (Link
!= &ProtocolInterface
->OpenList
);
1348 Link
= Link
->ForwardLink
, Count
++ ) {
1349 OpenData
= CR (Link
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
1351 Buffer
[Count
].AgentHandle
= OpenData
->AgentHandle
;
1352 Buffer
[Count
].ControllerHandle
= OpenData
->ControllerHandle
;
1353 Buffer
[Count
].Attributes
= OpenData
->Attributes
;
1354 Buffer
[Count
].OpenCount
= OpenData
->OpenCount
;
1357 *EntryBuffer
= Buffer
;
1358 *EntryCount
= Count
;
1362 // Done. Release the database lock are return
1364 CoreReleaseProtocolLock ();
1372 Retrieves the list of protocol interface GUIDs that are installed on a handle in a buffer allocated
1375 @param UserHandle The handle from which to retrieve the list of
1376 protocol interface GUIDs.
1377 @param ProtocolBuffer A pointer to the list of protocol interface GUID
1378 pointers that are installed on Handle.
1379 @param ProtocolBufferCount A pointer to the number of GUID pointers present
1382 @retval EFI_SUCCESS The list of protocol interface GUIDs installed
1383 on Handle was returned in ProtocolBuffer. The
1384 number of protocol interface GUIDs was returned
1385 in ProtocolBufferCount.
1386 @retval EFI_INVALID_PARAMETER Handle is NULL.
1387 @retval EFI_INVALID_PARAMETER Handle is not a valid EFI_HANDLE.
1388 @retval EFI_INVALID_PARAMETER ProtocolBuffer is NULL.
1389 @retval EFI_INVALID_PARAMETER ProtocolBufferCount is NULL.
1390 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the
1396 CoreProtocolsPerHandle (
1397 IN EFI_HANDLE UserHandle
,
1398 OUT EFI_GUID
***ProtocolBuffer
,
1399 OUT UINTN
*ProtocolBufferCount
1404 PROTOCOL_INTERFACE
*Prot
;
1406 UINTN ProtocolCount
;
1409 Status
= CoreValidateHandle (UserHandle
);
1410 if (EFI_ERROR (Status
)) {
1414 Handle
= (IHANDLE
*)UserHandle
;
1416 if (ProtocolBuffer
== NULL
) {
1417 return EFI_INVALID_PARAMETER
;
1420 if (ProtocolBufferCount
== NULL
) {
1421 return EFI_INVALID_PARAMETER
;
1424 *ProtocolBufferCount
= 0;
1428 CoreAcquireProtocolLock ();
1430 for (Link
= Handle
->Protocols
.ForwardLink
; Link
!= &Handle
->Protocols
; Link
= Link
->ForwardLink
) {
1435 // If there are no protocol interfaces installed on Handle, then Handle is not a valid EFI_HANDLE
1437 if (ProtocolCount
== 0) {
1438 Status
= EFI_INVALID_PARAMETER
;
1442 Buffer
= CoreAllocateBootServicesPool (sizeof (EFI_GUID
*) * ProtocolCount
);
1443 if (Buffer
== NULL
) {
1444 Status
= EFI_OUT_OF_RESOURCES
;
1448 *ProtocolBuffer
= Buffer
;
1449 *ProtocolBufferCount
= ProtocolCount
;
1451 for ( Link
= Handle
->Protocols
.ForwardLink
, ProtocolCount
= 0;
1452 Link
!= &Handle
->Protocols
;
1453 Link
= Link
->ForwardLink
, ProtocolCount
++) {
1454 Prot
= CR(Link
, PROTOCOL_INTERFACE
, Link
, PROTOCOL_INTERFACE_SIGNATURE
);
1455 Buffer
[ProtocolCount
] = &(Prot
->Protocol
->ProtocolID
);
1457 Status
= EFI_SUCCESS
;
1460 CoreReleaseProtocolLock ();
1467 return handle database key.
1470 @return Handle database key.
1474 CoreGetHandleDatabaseKey (
1478 return gHandleDatabaseKey
;
1484 Go connect any handles that were created or modified while a image executed.
1486 @param Key The Key to show that the handle has been
1491 CoreConnectHandlesByKey (
1497 EFI_HANDLE
*HandleBuffer
;
1502 // Lock the protocol database
1504 CoreAcquireProtocolLock ();
1506 for (Link
= gHandleList
.ForwardLink
, Count
= 0; Link
!= &gHandleList
; Link
= Link
->ForwardLink
) {
1507 Handle
= CR (Link
, IHANDLE
, AllHandles
, EFI_HANDLE_SIGNATURE
);
1508 if (Handle
->Key
> Key
) {
1513 HandleBuffer
= CoreAllocateBootServicesPool (Count
* sizeof (EFI_HANDLE
));
1514 if (HandleBuffer
== NULL
) {
1515 CoreReleaseProtocolLock ();
1519 for (Link
= gHandleList
.ForwardLink
, Count
= 0; Link
!= &gHandleList
; Link
= Link
->ForwardLink
) {
1520 Handle
= CR (Link
, IHANDLE
, AllHandles
, EFI_HANDLE_SIGNATURE
);
1521 if (Handle
->Key
> Key
) {
1522 HandleBuffer
[Count
++] = Handle
;
1527 // Unlock the protocol database
1529 CoreReleaseProtocolLock ();
1532 // Connect all handles whose Key value is greater than Key
1534 for (Index
= 0; Index
< Count
; Index
++) {
1535 CoreConnectController (HandleBuffer
[Index
], NULL
, NULL
, TRUE
);
1538 CoreFreePool(HandleBuffer
);