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 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
= AllocatePool (sizeof(PROTOCOL_ENTRY
));
137 if (ProtEntry
!= NULL
) {
139 // Initialize new protocol entry structure
141 ProtEntry
->Signature
= PROTOCOL_ENTRY_SIGNATURE
;
142 CopyGuid ((VOID
*)&ProtEntry
->ProtocolID
, Protocol
);
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_LOAD
| DEBUG_INFO
, "InstallProtocolInterface: %g %p\n", Protocol
, Interface
));
369 Status
= EFI_OUT_OF_RESOURCES
;
373 if (*UserHandle
!= NULL
) {
374 Status
= CoreHandleProtocol (*UserHandle
, Protocol
, (VOID
**)&ExistingInterface
);
375 if (!EFI_ERROR (Status
)) {
376 return EFI_INVALID_PARAMETER
;
381 // Lock the protocol database
383 CoreAcquireProtocolLock ();
386 // Lookup the Protocol Entry for the requested protocol
388 ProtEntry
= CoreFindProtocolEntry (Protocol
, TRUE
);
389 if (ProtEntry
== NULL
) {
394 // Allocate a new protocol interface structure
396 Prot
= AllocateZeroPool (sizeof(PROTOCOL_INTERFACE
));
398 Status
= EFI_OUT_OF_RESOURCES
;
403 // If caller didn't supply a handle, allocate a new one
405 Handle
= (IHANDLE
*)*UserHandle
;
406 if (Handle
== NULL
) {
407 Handle
= AllocateZeroPool (sizeof(IHANDLE
));
408 if (Handle
== NULL
) {
409 Status
= EFI_OUT_OF_RESOURCES
;
414 // Initialize new handler structure
416 Handle
->Signature
= EFI_HANDLE_SIGNATURE
;
417 InitializeListHead (&Handle
->Protocols
);
420 // Initialize the Key to show that the handle has been created/modified
422 gHandleDatabaseKey
++;
423 Handle
->Key
= gHandleDatabaseKey
;
426 // Add this handle to the list global list of all handles
429 InsertTailList (&gHandleList
, &Handle
->AllHandles
);
432 Status
= CoreValidateHandle (Handle
);
433 if (EFI_ERROR (Status
)) {
438 // Each interface that is added must be unique
440 ASSERT (CoreFindProtocolInterface (Handle
, Protocol
, Interface
) == NULL
);
443 // Initialize the protocol interface structure
445 Prot
->Signature
= PROTOCOL_INTERFACE_SIGNATURE
;
446 Prot
->Handle
= Handle
;
447 Prot
->Protocol
= ProtEntry
;
448 Prot
->Interface
= Interface
;
451 // Initalize OpenProtocol Data base
453 InitializeListHead (&Prot
->OpenList
);
454 Prot
->OpenListCount
= 0;
457 // Add this protocol interface to the head of the supported
458 // protocol list for this handle
460 InsertHeadList (&Handle
->Protocols
, &Prot
->Link
);
463 // Add this protocol interface to the tail of the
466 InsertTailList (&ProtEntry
->Protocols
, &Prot
->ByProtocol
);
469 // Notify the notification list for this protocol
472 CoreNotifyProtocolEntry (ProtEntry
);
474 Status
= EFI_SUCCESS
;
478 // Done, unlock the database and return
480 CoreReleaseProtocolLock ();
481 if (!EFI_ERROR (Status
)) {
483 // Return the new handle back to the caller
485 *UserHandle
= Handle
;
488 // There was an error, clean up
502 Installs a list of protocol interface into the boot services environment.
503 This function calls InstallProtocolInterface() in a loop. If any error
504 occures all the protocols added by this function are removed. This is
505 basically a lib function to save space.
507 @param Handle The handle to install the protocol handlers on,
508 or NULL if a new handle is to be allocated
509 @param ... EFI_GUID followed by protocol instance. A NULL
510 terminates the list. The pairs are the
511 arguments to InstallProtocolInterface(). All the
512 protocols are added to Handle.
514 @retval EFI_INVALID_PARAMETER Handle is NULL.
515 @retval EFI_SUCCESS Protocol interfaces successfully installed.
520 CoreInstallMultipleProtocolInterfaces (
521 IN OUT EFI_HANDLE
*Handle
,
531 EFI_HANDLE OldHandle
;
532 EFI_HANDLE DeviceHandle
;
533 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
535 if (Handle
== NULL
) {
536 return EFI_INVALID_PARAMETER
;
540 // Syncronize with notifcations.
542 OldTpl
= CoreRaiseTpl (TPL_NOTIFY
);
546 // Check for duplicate device path and install the protocol interfaces
548 VA_START (Args
, Handle
);
549 for (Index
= 0, Status
= EFI_SUCCESS
; !EFI_ERROR (Status
); Index
++) {
551 // If protocol is NULL, then it's the end of the list
553 Protocol
= VA_ARG (Args
, EFI_GUID
*);
554 if (Protocol
== NULL
) {
558 Interface
= VA_ARG (Args
, VOID
*);
561 // Make sure you are installing on top a device path that has already been added.
563 if (CompareGuid (Protocol
, &gEfiDevicePathProtocolGuid
)) {
565 DevicePath
= Interface
;
566 Status
= CoreLocateDevicePath (&gEfiDevicePathProtocolGuid
, &DevicePath
, &DeviceHandle
);
567 if (!EFI_ERROR (Status
) && (DeviceHandle
!= NULL
) && IsDevicePathEnd(DevicePath
)) {
568 Status
= EFI_ALREADY_STARTED
;
576 Status
= CoreInstallProtocolInterface (Handle
, Protocol
, EFI_NATIVE_INTERFACE
, Interface
);
581 // If there was an error, remove all the interfaces that were installed without any errors
583 if (EFI_ERROR (Status
)) {
585 // Reset the va_arg back to the first argument.
587 VA_START (Args
, Handle
);
588 for (; Index
> 1; Index
--) {
589 Protocol
= VA_ARG (Args
, EFI_GUID
*);
590 Interface
= VA_ARG (Args
, VOID
*);
591 CoreUninstallProtocolInterface (*Handle
, Protocol
, Interface
);
601 CoreRestoreTpl (OldTpl
);
607 Attempts to disconnect all drivers that are using the protocol interface being queried.
608 If failed, reconnect all drivers disconnected.
609 Note: This function doesn't do parameters checking, it's caller's responsibility
610 to pass in valid parameters.
612 @param UserHandle The handle on which the protocol is installed
613 @param Prot The protocol to disconnect drivers from
615 @retval EFI_SUCCESS Drivers using the protocol interface are all
617 @retval EFI_ACCESS_DENIED Failed to disconnect one or all of the drivers
621 CoreDisconnectControllersUsingProtocolInterface (
622 IN EFI_HANDLE UserHandle
,
623 IN PROTOCOL_INTERFACE
*Prot
629 OPEN_PROTOCOL_DATA
*OpenData
;
631 Status
= EFI_SUCCESS
;
634 // Attempt to disconnect all drivers from this protocol interface
638 for ( Link
= Prot
->OpenList
.ForwardLink
;
639 (Link
!= &Prot
->OpenList
) && !ItemFound
;
640 Link
= Link
->ForwardLink
) {
641 OpenData
= CR (Link
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
642 if (OpenData
->Attributes
& EFI_OPEN_PROTOCOL_BY_DRIVER
) {
644 CoreReleaseProtocolLock ();
645 Status
= CoreDisconnectController (UserHandle
, OpenData
->AgentHandle
, NULL
);
646 CoreAcquireProtocolLock ();
647 if (EFI_ERROR (Status
)) {
655 if (!EFI_ERROR (Status
)) {
657 // Attempt to remove BY_HANDLE_PROTOOCL and GET_PROTOCOL and TEST_PROTOCOL Open List items
661 for ( Link
= Prot
->OpenList
.ForwardLink
;
662 (Link
!= &Prot
->OpenList
) && !ItemFound
;
663 Link
= Link
->ForwardLink
) {
664 OpenData
= CR (Link
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
665 if (OpenData
->Attributes
&
666 (EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
| EFI_OPEN_PROTOCOL_GET_PROTOCOL
| EFI_OPEN_PROTOCOL_TEST_PROTOCOL
)) {
668 RemoveEntryList (&OpenData
->Link
);
669 Prot
->OpenListCount
--;
670 CoreFreePool (OpenData
);
677 // If there are errors or still has open items in the list, then reconnect all the drivers and return an error
679 if (EFI_ERROR (Status
) || (Prot
->OpenListCount
> 0)) {
680 CoreReleaseProtocolLock ();
681 CoreConnectController (UserHandle
, NULL
, NULL
, TRUE
);
682 CoreAcquireProtocolLock ();
683 Status
= EFI_ACCESS_DENIED
;
692 Uninstalls all instances of a protocol:interfacer from a handle.
693 If the last protocol interface is remove from the handle, the
696 @param UserHandle The handle to remove the protocol handler from
697 @param Protocol The protocol, of protocol:interface, to remove
698 @param Interface The interface, of protocol:interface, to remove
700 @retval EFI_INVALID_PARAMETER Protocol is NULL.
701 @retval EFI_SUCCESS Protocol interface successfully uninstalled.
706 CoreUninstallProtocolInterface (
707 IN EFI_HANDLE UserHandle
,
708 IN EFI_GUID
*Protocol
,
714 PROTOCOL_INTERFACE
*Prot
;
717 // Check that Protocol is valid
719 if (Protocol
== NULL
) {
720 return EFI_INVALID_PARAMETER
;
724 // Check that UserHandle is a valid handle
726 Status
= CoreValidateHandle (UserHandle
);
727 if (EFI_ERROR (Status
)) {
732 // Lock the protocol database
734 CoreAcquireProtocolLock ();
737 // Check that Protocol exists on UserHandle, and Interface matches the interface in the database
739 Prot
= CoreFindProtocolInterface (UserHandle
, Protocol
, Interface
);
741 Status
= EFI_NOT_FOUND
;
746 // Attempt to disconnect all drivers that are using the protocol interface that is about to be removed
748 Status
= CoreDisconnectControllersUsingProtocolInterface (
752 if (EFI_ERROR (Status
)) {
754 // One or more drivers refused to release, so return the error
760 // Remove the protocol interface from the protocol
762 Status
= EFI_NOT_FOUND
;
763 Handle
= (IHANDLE
*)UserHandle
;
764 Prot
= CoreRemoveInterfaceFromProtocol (Handle
, Protocol
, Interface
);
768 // Update the Key to show that the handle has been created/modified
770 gHandleDatabaseKey
++;
771 Handle
->Key
= gHandleDatabaseKey
;
774 // Remove the protocol interface from the handle
776 RemoveEntryList (&Prot
->Link
);
783 Status
= EFI_SUCCESS
;
787 // If there are no more handlers for the handle, free the handle
789 if (IsListEmpty (&Handle
->Protocols
)) {
790 Handle
->Signature
= 0;
791 RemoveEntryList (&Handle
->AllHandles
);
792 CoreFreePool (Handle
);
797 // Done, unlock the database and return
799 CoreReleaseProtocolLock ();
807 Uninstalls a list of protocol interface in the boot services environment.
808 This function calls UnisatllProtocolInterface() in a loop. This is
809 basically a lib function to save space.
811 @param Handle The handle to uninstall the protocol
812 @param ... EFI_GUID followed by protocol instance. A NULL
813 terminates the list. The pairs are the
814 arguments to UninstallProtocolInterface(). All
815 the protocols are added to Handle.
822 CoreUninstallMultipleProtocolInterfaces (
823 IN EFI_HANDLE Handle
,
833 VA_START (Args
, Handle
);
834 for (Index
= 0, Status
= EFI_SUCCESS
; !EFI_ERROR (Status
); Index
++) {
836 // If protocol is NULL, then it's the end of the list
838 Protocol
= VA_ARG (Args
, EFI_GUID
*);
839 if (Protocol
== NULL
) {
843 Interface
= VA_ARG (Args
, VOID
*);
848 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
);
874 Locate a certain GUID protocol interface in a Handle's protocols.
876 @param UserHandle The handle to obtain the protocol interface on
877 @param Protocol The GUID of the protocol
879 @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 @retval EFI_SUCCESS The interface information for the specified protocol was returned.
925 @retval EFI_UNSUPPORTED The device does not support the specified protocol.
926 @retval EFI_INVALID_PARAMETER Handle is not a valid EFI_HANDLE..
927 @retval EFI_INVALID_PARAMETER Protocol is NULL.
928 @retval EFI_INVALID_PARAMETER Interface is NULL.
934 IN EFI_HANDLE UserHandle
,
935 IN EFI_GUID
*Protocol
,
939 return CoreOpenProtocol (
945 EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
952 Locates the installed protocol handler for the handle, and
953 invokes it to obtain the protocol interface. Usage information
954 is registered in the protocol data base.
956 @param UserHandle The handle to obtain the protocol interface on
957 @param Protocol The ID of the protocol
958 @param Interface The location to return the protocol interface
959 @param ImageHandle The handle of the Image that is opening the
960 protocol interface specified by Protocol and
962 @param ControllerHandle The controller handle that is requiring this
964 @param Attributes The open mode of the protocol interface
965 specified by Handle and Protocol.
967 @retval EFI_INVALID_PARAMETER Protocol is NULL.
968 @retval EFI_SUCCESS Get the protocol interface.
974 IN EFI_HANDLE UserHandle
,
975 IN EFI_GUID
*Protocol
,
976 OUT VOID
**Interface OPTIONAL
,
977 IN EFI_HANDLE ImageHandle
,
978 IN EFI_HANDLE ControllerHandle
,
983 PROTOCOL_INTERFACE
*Prot
;
985 OPEN_PROTOCOL_DATA
*OpenData
;
992 // Check for invalid Protocol
994 if (Protocol
== NULL
) {
995 return EFI_INVALID_PARAMETER
;
999 // Check for invalid Interface
1001 if (Attributes
!= EFI_OPEN_PROTOCOL_TEST_PROTOCOL
) {
1002 if (Interface
== NULL
) {
1003 return EFI_INVALID_PARAMETER
;
1010 // Check for invalid UserHandle
1012 Status
= CoreValidateHandle (UserHandle
);
1013 if (EFI_ERROR (Status
)) {
1018 // Check for invalid Attributes
1020 switch (Attributes
) {
1021 case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
:
1022 Status
= CoreValidateHandle (ImageHandle
);
1023 if (EFI_ERROR (Status
)) {
1026 Status
= CoreValidateHandle (ControllerHandle
);
1027 if (EFI_ERROR (Status
)) {
1030 if (UserHandle
== ControllerHandle
) {
1031 return EFI_INVALID_PARAMETER
;
1034 case EFI_OPEN_PROTOCOL_BY_DRIVER
:
1035 case EFI_OPEN_PROTOCOL_BY_DRIVER
| EFI_OPEN_PROTOCOL_EXCLUSIVE
:
1036 Status
= CoreValidateHandle (ImageHandle
);
1037 if (EFI_ERROR (Status
)) {
1040 Status
= CoreValidateHandle (ControllerHandle
);
1041 if (EFI_ERROR (Status
)) {
1045 case EFI_OPEN_PROTOCOL_EXCLUSIVE
:
1046 Status
= CoreValidateHandle (ImageHandle
);
1047 if (EFI_ERROR (Status
)) {
1051 case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
:
1052 case EFI_OPEN_PROTOCOL_GET_PROTOCOL
:
1053 case EFI_OPEN_PROTOCOL_TEST_PROTOCOL
:
1056 return EFI_INVALID_PARAMETER
;
1060 // Lock the protocol database
1062 CoreAcquireProtocolLock ();
1065 // Look at each protocol interface for a match
1067 Prot
= CoreGetProtocolInterface (UserHandle
, Protocol
);
1069 Status
= EFI_UNSUPPORTED
;
1074 // This is the protocol interface entry for this protocol
1076 if (Attributes
!= EFI_OPEN_PROTOCOL_TEST_PROTOCOL
) {
1077 *Interface
= Prot
->Interface
;
1079 Status
= EFI_SUCCESS
;
1083 for ( Link
= Prot
->OpenList
.ForwardLink
; Link
!= &Prot
->OpenList
; Link
= Link
->ForwardLink
) {
1084 OpenData
= CR (Link
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
1085 ExactMatch
= (BOOLEAN
)((OpenData
->AgentHandle
== ImageHandle
) &&
1086 (OpenData
->Attributes
== Attributes
) &&
1087 (OpenData
->ControllerHandle
== ControllerHandle
));
1088 if (OpenData
->Attributes
& EFI_OPEN_PROTOCOL_BY_DRIVER
) {
1091 Status
= EFI_ALREADY_STARTED
;
1095 if (OpenData
->Attributes
& EFI_OPEN_PROTOCOL_EXCLUSIVE
) {
1097 } else if (ExactMatch
) {
1098 OpenData
->OpenCount
++;
1099 Status
= EFI_SUCCESS
;
1105 // ByDriver TRUE -> A driver is managing (UserHandle, Protocol)
1106 // ByDriver FALSE -> There are no drivers managing (UserHandle, Protocol)
1107 // Exclusive TRUE -> Something has exclusive access to (UserHandle, Protocol)
1108 // Exclusive FALSE -> Nothing has exclusive access to (UserHandle, Protocol)
1111 switch (Attributes
) {
1112 case EFI_OPEN_PROTOCOL_BY_DRIVER
:
1113 if (Exclusive
|| ByDriver
) {
1114 Status
= EFI_ACCESS_DENIED
;
1118 case EFI_OPEN_PROTOCOL_BY_DRIVER
| EFI_OPEN_PROTOCOL_EXCLUSIVE
:
1119 case EFI_OPEN_PROTOCOL_EXCLUSIVE
:
1121 Status
= EFI_ACCESS_DENIED
;
1127 for ( Link
= Prot
->OpenList
.ForwardLink
; (Link
!= &Prot
->OpenList
) && (!Disconnect
); Link
= Link
->ForwardLink
) {
1128 OpenData
= CR (Link
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
1129 if (OpenData
->Attributes
& EFI_OPEN_PROTOCOL_BY_DRIVER
) {
1131 CoreReleaseProtocolLock ();
1132 Status
= CoreDisconnectController (UserHandle
, OpenData
->AgentHandle
, NULL
);
1133 CoreAcquireProtocolLock ();
1134 if (EFI_ERROR (Status
)) {
1135 Status
= EFI_ACCESS_DENIED
;
1140 } while (Disconnect
);
1143 case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
:
1144 case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
:
1145 case EFI_OPEN_PROTOCOL_GET_PROTOCOL
:
1146 case EFI_OPEN_PROTOCOL_TEST_PROTOCOL
:
1150 if (ImageHandle
== NULL
) {
1151 Status
= EFI_SUCCESS
;
1157 OpenData
= AllocatePool (sizeof(OPEN_PROTOCOL_DATA
));
1158 if (OpenData
== NULL
) {
1159 Status
= EFI_OUT_OF_RESOURCES
;
1161 OpenData
->Signature
= OPEN_PROTOCOL_DATA_SIGNATURE
;
1162 OpenData
->AgentHandle
= ImageHandle
;
1163 OpenData
->ControllerHandle
= ControllerHandle
;
1164 OpenData
->Attributes
= Attributes
;
1165 OpenData
->OpenCount
= 1;
1166 InsertTailList (&Prot
->OpenList
, &OpenData
->Link
);
1167 Prot
->OpenListCount
++;
1168 Status
= EFI_SUCCESS
;
1173 // Done. Release the database lock are return
1175 CoreReleaseProtocolLock ();
1182 Closes a protocol on a handle that was opened using OpenProtocol().
1184 @param UserHandle The handle for the protocol interface that was
1185 previously opened with OpenProtocol(), and is
1187 @param Protocol The published unique identifier of the protocol.
1188 It is the caller's responsibility to pass in a
1190 @param AgentHandle The handle of the agent that is closing the
1192 @param ControllerHandle If the agent that opened a protocol is a driver
1193 that follows the EFI Driver Model, then this
1194 parameter is the controller handle that required
1195 the protocol interface. If the agent does not
1196 follow the EFI Driver Model, then this parameter
1197 is optional and may be NULL.
1199 @retval EFI_SUCCESS The protocol instance was closed.
1200 @retval EFI_INVALID_PARAMETER Handle, AgentHandle or ControllerHandle is not a
1202 @retval EFI_NOT_FOUND Can not find the specified protocol or
1209 IN EFI_HANDLE UserHandle
,
1210 IN EFI_GUID
*Protocol
,
1211 IN EFI_HANDLE AgentHandle
,
1212 IN EFI_HANDLE ControllerHandle
1216 PROTOCOL_INTERFACE
*ProtocolInterface
;
1218 OPEN_PROTOCOL_DATA
*OpenData
;
1221 // Check for invalid parameters
1223 Status
= CoreValidateHandle (UserHandle
);
1224 if (EFI_ERROR (Status
)) {
1227 Status
= CoreValidateHandle (AgentHandle
);
1228 if (EFI_ERROR (Status
)) {
1231 if (ControllerHandle
!= NULL
) {
1232 Status
= CoreValidateHandle (ControllerHandle
);
1233 if (EFI_ERROR (Status
)) {
1237 if (Protocol
== NULL
) {
1238 return EFI_INVALID_PARAMETER
;
1242 // Lock the protocol database
1244 CoreAcquireProtocolLock ();
1247 // Look at each protocol interface for a match
1249 Status
= EFI_NOT_FOUND
;
1250 ProtocolInterface
= CoreGetProtocolInterface (UserHandle
, Protocol
);
1251 if (ProtocolInterface
== NULL
) {
1256 // Walk the Open data base looking for AgentHandle
1258 Link
= ProtocolInterface
->OpenList
.ForwardLink
;
1259 while (Link
!= &ProtocolInterface
->OpenList
) {
1260 OpenData
= CR (Link
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
1261 Link
= Link
->ForwardLink
;
1262 if ((OpenData
->AgentHandle
== AgentHandle
) && (OpenData
->ControllerHandle
== ControllerHandle
)) {
1263 RemoveEntryList (&OpenData
->Link
);
1264 ProtocolInterface
->OpenListCount
--;
1265 CoreFreePool (OpenData
);
1266 Status
= EFI_SUCCESS
;
1272 // Done. Release the database lock and return.
1274 CoreReleaseProtocolLock ();
1282 Return information about Opened protocols in the system
1284 @param UserHandle The handle to close the protocol interface on
1285 @param Protocol The ID of the protocol
1286 @param EntryBuffer A pointer to a buffer of open protocol information in the
1287 form of EFI_OPEN_PROTOCOL_INFORMATION_ENTRY structures.
1288 @param EntryCount Number of EntryBuffer entries
1290 @retval EFI_SUCCESS The open protocol information was returned in EntryBuffer,
1291 and the number of entries was returned EntryCount.
1292 @retval EFI_NOT_FOUND Handle does not support the protocol specified by Protocol.
1293 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to allocate EntryBuffer.
1298 CoreOpenProtocolInformation (
1299 IN EFI_HANDLE UserHandle
,
1300 IN EFI_GUID
*Protocol
,
1301 OUT EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
**EntryBuffer
,
1302 OUT UINTN
*EntryCount
1306 PROTOCOL_INTERFACE
*ProtocolInterface
;
1308 OPEN_PROTOCOL_DATA
*OpenData
;
1309 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*Buffer
;
1313 *EntryBuffer
= NULL
;
1317 // Lock the protocol database
1319 CoreAcquireProtocolLock ();
1322 // Look at each protocol interface for a match
1324 Status
= EFI_NOT_FOUND
;
1325 ProtocolInterface
= CoreGetProtocolInterface (UserHandle
, Protocol
);
1326 if (ProtocolInterface
== NULL
) {
1331 // Count the number of Open Entries
1333 for ( Link
= ProtocolInterface
->OpenList
.ForwardLink
, Count
= 0;
1334 (Link
!= &ProtocolInterface
->OpenList
) ;
1335 Link
= Link
->ForwardLink
) {
1339 ASSERT (Count
== ProtocolInterface
->OpenListCount
);
1342 Size
= sizeof(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
);
1344 Size
= Count
* sizeof(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
);
1347 Buffer
= AllocatePool (Size
);
1348 if (Buffer
== NULL
) {
1349 Status
= EFI_OUT_OF_RESOURCES
;
1353 Status
= EFI_SUCCESS
;
1354 for ( Link
= ProtocolInterface
->OpenList
.ForwardLink
, Count
= 0;
1355 (Link
!= &ProtocolInterface
->OpenList
);
1356 Link
= Link
->ForwardLink
, Count
++ ) {
1357 OpenData
= CR (Link
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
1359 Buffer
[Count
].AgentHandle
= OpenData
->AgentHandle
;
1360 Buffer
[Count
].ControllerHandle
= OpenData
->ControllerHandle
;
1361 Buffer
[Count
].Attributes
= OpenData
->Attributes
;
1362 Buffer
[Count
].OpenCount
= OpenData
->OpenCount
;
1365 *EntryBuffer
= Buffer
;
1366 *EntryCount
= Count
;
1370 // Done. Release the database lock.
1372 CoreReleaseProtocolLock ();
1380 Retrieves the list of protocol interface GUIDs that are installed on a handle in a buffer allocated
1383 @param UserHandle The handle from which to retrieve the list of
1384 protocol interface GUIDs.
1385 @param ProtocolBuffer A pointer to the list of protocol interface GUID
1386 pointers that are installed on Handle.
1387 @param ProtocolBufferCount A pointer to the number of GUID pointers present
1390 @retval EFI_SUCCESS The list of protocol interface GUIDs installed
1391 on Handle was returned in ProtocolBuffer. The
1392 number of protocol interface GUIDs was returned
1393 in ProtocolBufferCount.
1394 @retval EFI_INVALID_PARAMETER Handle is NULL.
1395 @retval EFI_INVALID_PARAMETER Handle is not a valid EFI_HANDLE.
1396 @retval EFI_INVALID_PARAMETER ProtocolBuffer is NULL.
1397 @retval EFI_INVALID_PARAMETER ProtocolBufferCount is NULL.
1398 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the
1404 CoreProtocolsPerHandle (
1405 IN EFI_HANDLE UserHandle
,
1406 OUT EFI_GUID
***ProtocolBuffer
,
1407 OUT UINTN
*ProtocolBufferCount
1412 PROTOCOL_INTERFACE
*Prot
;
1414 UINTN ProtocolCount
;
1417 Status
= CoreValidateHandle (UserHandle
);
1418 if (EFI_ERROR (Status
)) {
1422 Handle
= (IHANDLE
*)UserHandle
;
1424 if (ProtocolBuffer
== NULL
) {
1425 return EFI_INVALID_PARAMETER
;
1428 if (ProtocolBufferCount
== NULL
) {
1429 return EFI_INVALID_PARAMETER
;
1432 *ProtocolBufferCount
= 0;
1436 CoreAcquireProtocolLock ();
1438 for (Link
= Handle
->Protocols
.ForwardLink
; Link
!= &Handle
->Protocols
; Link
= Link
->ForwardLink
) {
1443 // If there are no protocol interfaces installed on Handle, then Handle is not a valid EFI_HANDLE
1445 if (ProtocolCount
== 0) {
1446 Status
= EFI_INVALID_PARAMETER
;
1450 Buffer
= AllocatePool (sizeof (EFI_GUID
*) * ProtocolCount
);
1451 if (Buffer
== NULL
) {
1452 Status
= EFI_OUT_OF_RESOURCES
;
1456 *ProtocolBuffer
= Buffer
;
1457 *ProtocolBufferCount
= ProtocolCount
;
1459 for ( Link
= Handle
->Protocols
.ForwardLink
, ProtocolCount
= 0;
1460 Link
!= &Handle
->Protocols
;
1461 Link
= Link
->ForwardLink
, ProtocolCount
++) {
1462 Prot
= CR(Link
, PROTOCOL_INTERFACE
, Link
, PROTOCOL_INTERFACE_SIGNATURE
);
1463 Buffer
[ProtocolCount
] = &(Prot
->Protocol
->ProtocolID
);
1465 Status
= EFI_SUCCESS
;
1468 CoreReleaseProtocolLock ();
1475 return handle database key.
1478 @return Handle database key.
1482 CoreGetHandleDatabaseKey (
1486 return gHandleDatabaseKey
;
1492 Go connect any handles that were created or modified while a image executed.
1494 @param Key The Key to show that the handle has been
1499 CoreConnectHandlesByKey (
1505 EFI_HANDLE
*HandleBuffer
;
1510 // Lock the protocol database
1512 CoreAcquireProtocolLock ();
1514 for (Link
= gHandleList
.ForwardLink
, Count
= 0; Link
!= &gHandleList
; Link
= Link
->ForwardLink
) {
1515 Handle
= CR (Link
, IHANDLE
, AllHandles
, EFI_HANDLE_SIGNATURE
);
1516 if (Handle
->Key
> Key
) {
1521 HandleBuffer
= AllocatePool (Count
* sizeof (EFI_HANDLE
));
1522 if (HandleBuffer
== NULL
) {
1523 CoreReleaseProtocolLock ();
1527 for (Link
= gHandleList
.ForwardLink
, Count
= 0; Link
!= &gHandleList
; Link
= Link
->ForwardLink
) {
1528 Handle
= CR (Link
, IHANDLE
, AllHandles
, EFI_HANDLE_SIGNATURE
);
1529 if (Handle
->Key
> Key
) {
1530 HandleBuffer
[Count
++] = Handle
;
1535 // Unlock the protocol database
1537 CoreReleaseProtocolLock ();
1540 // Connect all handles whose Key value is greater than Key
1542 for (Index
= 0; Index
< Count
; Index
++) {
1543 CoreConnectController (HandleBuffer
[Index
], NULL
, NULL
, TRUE
);
1546 CoreFreePool(HandleBuffer
);