2 Implementation of protocol related services in the UEFI Boot Services table for use in unit tests.
4 Copyright (c) Microsoft Corporation
5 SPDX-License-Identifier: BSD-2-Clause-Patent
9 #include "UnitTestUefiBootServicesTableLibProtocol.h"
11 STATIC LIST_ENTRY mProtocolDatabase
= INITIALIZE_LIST_HEAD_VARIABLE (mProtocolDatabase
);
12 STATIC LIST_ENTRY gHandleList
= INITIALIZE_LIST_HEAD_VARIABLE (gHandleList
);
13 STATIC UINT64 gHandleDatabaseKey
= 0;
14 STATIC UINTN mEfiLocateHandleRequest
= 0;
21 Check whether a handle is a valid EFI_HANDLE
23 @param UserHandle The handle to check
25 @retval EFI_INVALID_PARAMETER The handle is NULL or not a valid EFI_HANDLE.
26 @retval EFI_SUCCESS The handle is valid EFI_HANDLE.
30 UnitTestValidateHandle (
31 IN EFI_HANDLE UserHandle
37 if (UserHandle
== NULL
) {
38 return EFI_INVALID_PARAMETER
;
41 for (Link
= gHandleList
.BackLink
; Link
!= &gHandleList
; Link
= Link
->BackLink
) {
42 Handle
= CR (Link
, IHANDLE
, AllHandles
, EFI_HANDLE_SIGNATURE
);
43 if (Handle
== (IHANDLE
*)UserHandle
) {
48 return EFI_INVALID_PARAMETER
;
52 Finds the protocol entry for the requested protocol.
54 @param Protocol The ID of the protocol
55 @param Create Create a new entry if not found
57 @return Protocol entry
61 UnitTestFindProtocolEntry (
62 IN EFI_GUID
*Protocol
,
68 PROTOCOL_ENTRY
*ProtEntry
;
71 // Search the database for the matching GUID
75 for (Link
= mProtocolDatabase
.ForwardLink
;
76 Link
!= &mProtocolDatabase
;
77 Link
= Link
->ForwardLink
)
79 Item
= CR (Link
, PROTOCOL_ENTRY
, AllEntries
, PROTOCOL_ENTRY_SIGNATURE
);
80 if (CompareGuid (&Item
->ProtocolID
, Protocol
)) {
82 // This is the protocol entry
91 // If the protocol entry was not found and Create is TRUE, then
92 // allocate a new entry
94 if ((ProtEntry
== NULL
) && Create
) {
95 ProtEntry
= AllocatePool (sizeof (PROTOCOL_ENTRY
));
97 if (ProtEntry
!= NULL
) {
99 // Initialize new protocol entry structure
101 ProtEntry
->Signature
= PROTOCOL_ENTRY_SIGNATURE
;
102 CopyGuid ((VOID
*)&ProtEntry
->ProtocolID
, Protocol
);
103 InitializeListHead (&ProtEntry
->Protocols
);
104 InitializeListHead (&ProtEntry
->Notify
);
107 // Add it to protocol database
109 InsertTailList (&mProtocolDatabase
, &ProtEntry
->AllEntries
);
117 Finds the protocol instance for the requested handle and protocol.
118 Note: This function doesn't do parameters checking, it's caller's responsibility
119 to pass in valid parameters.
121 @param Handle The handle to search the protocol on
122 @param Protocol GUID of the protocol
123 @param Interface The interface for the protocol being searched
125 @return Protocol instance (NULL: Not found)
129 UnitTestFindProtocolInterface (
131 IN EFI_GUID
*Protocol
,
135 PROTOCOL_INTERFACE
*Prot
;
136 PROTOCOL_ENTRY
*ProtEntry
;
142 // Lookup the protocol entry for this protocol ID
145 ProtEntry
= UnitTestFindProtocolEntry (Protocol
, FALSE
);
146 if (ProtEntry
!= NULL
) {
148 // Look at each protocol interface for any matches
150 for (Link
= Handle
->Protocols
.ForwardLink
; Link
!= &Handle
->Protocols
; Link
= Link
->ForwardLink
) {
152 // If this protocol interface matches, remove it
154 Prot
= CR (Link
, PROTOCOL_INTERFACE
, Link
, PROTOCOL_INTERFACE_SIGNATURE
);
155 if ((Prot
->Interface
== Interface
) && (Prot
->Protocol
== ProtEntry
)) {
167 Signal event for every protocol in protocol entry.
169 @param ProtEntry Protocol entry
173 UnitTestNotifyProtocolEntry (
174 IN PROTOCOL_ENTRY
*ProtEntry
177 PROTOCOL_NOTIFY
*ProtNotify
;
180 for (Link
= ProtEntry
->Notify
.ForwardLink
; Link
!= &ProtEntry
->Notify
; Link
= Link
->ForwardLink
) {
181 ProtNotify
= CR (Link
, PROTOCOL_NOTIFY
, Link
, PROTOCOL_NOTIFY_SIGNATURE
);
182 UnitTestSignalEvent (ProtNotify
->Event
);
187 Routine to get the next Handle, when you are searching for all handles.
189 @param Position Information about which Handle to seach for.
190 @param Interface Return the interface structure for the matching
193 @return An pointer to IHANDLE if the next Position is not the end of the list.
194 Otherwise,NULL is returned.
198 UnitTestGetNextLocateAllHandles (
199 IN OUT LOCATE_POSITION
*Position
,
208 Position
->Position
= Position
->Position
->ForwardLink
;
211 // If not at the end of the list, get the handle
215 if (Position
->Position
!= &gHandleList
) {
216 Handle
= CR (Position
->Position
, IHANDLE
, AllHandles
, EFI_HANDLE_SIGNATURE
);
223 Routine to get the next Handle, when you are searching for register protocol
226 @param Position Information about which Handle to seach for.
227 @param Interface Return the interface structure for the matching
230 @return An pointer to IHANDLE if the next Position is not the end of the list.
231 Otherwise,NULL is returned.
235 UnitTestGetNextLocateByRegisterNotify (
236 IN OUT LOCATE_POSITION
*Position
,
241 PROTOCOL_NOTIFY
*ProtNotify
;
242 PROTOCOL_INTERFACE
*Prot
;
247 ProtNotify
= Position
->SearchKey
;
250 // If this is the first request, get the next handle
252 if (ProtNotify
!= NULL
) {
253 ASSERT (ProtNotify
->Signature
== PROTOCOL_NOTIFY_SIGNATURE
);
254 Position
->SearchKey
= NULL
;
257 // If not at the end of the list, get the next handle
259 Link
= ProtNotify
->Position
->ForwardLink
;
260 if (Link
!= &ProtNotify
->Protocol
->Protocols
) {
261 Prot
= CR (Link
, PROTOCOL_INTERFACE
, ByProtocol
, PROTOCOL_INTERFACE_SIGNATURE
);
262 Handle
= Prot
->Handle
;
263 *Interface
= Prot
->Interface
;
271 Routine to get the next Handle, when you are searching for a given protocol.
273 @param Position Information about which Handle to seach for.
274 @param Interface Return the interface structure for the matching
277 @return An pointer to IHANDLE if the next Position is not the end of the list.
278 Otherwise,NULL is returned.
282 UnitTestGetNextLocateByProtocol (
283 IN OUT LOCATE_POSITION
*Position
,
289 PROTOCOL_INTERFACE
*Prot
;
297 Link
= Position
->Position
->ForwardLink
;
298 Position
->Position
= Link
;
301 // If not at the end, return the handle
303 if (Link
== &Position
->ProtEntry
->Protocols
) {
311 Prot
= CR (Link
, PROTOCOL_INTERFACE
, ByProtocol
, PROTOCOL_INTERFACE_SIGNATURE
);
312 Handle
= Prot
->Handle
;
313 *Interface
= Prot
->Interface
;
316 // If this handle has not been returned this request, then
319 if (Handle
->LocateRequest
!= mEfiLocateHandleRequest
) {
320 Handle
->LocateRequest
= mEfiLocateHandleRequest
;
329 Attempts to disconnect all drivers that are using the protocol interface being queried.
330 If failed, reconnect all drivers disconnected.
331 Note: This function doesn't do parameters checking, it's caller's responsibility
332 to pass in valid parameters.
334 @param UserHandle The handle on which the protocol is installed
335 @param Prot The protocol to disconnect drivers from
337 @retval EFI_SUCCESS Drivers using the protocol interface are all
339 @retval EFI_ACCESS_DENIED Failed to disconnect one or all of the drivers
343 UnitTestDisconnectControllersUsingProtocolInterface (
344 IN EFI_HANDLE UserHandle
,
345 IN PROTOCOL_INTERFACE
*Prot
351 OPEN_PROTOCOL_DATA
*OpenData
;
353 Status
= EFI_SUCCESS
;
356 // Attempt to disconnect all drivers from this protocol interface
360 for (Link
= Prot
->OpenList
.ForwardLink
; Link
!= &Prot
->OpenList
; Link
= Link
->ForwardLink
) {
361 OpenData
= CR (Link
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
362 if ((OpenData
->Attributes
& EFI_OPEN_PROTOCOL_BY_DRIVER
) != 0) {
363 Status
= UnitTestDisconnectController (UserHandle
, OpenData
->AgentHandle
, NULL
);
364 if (!EFI_ERROR (Status
)) {
373 if (!EFI_ERROR (Status
)) {
375 // Attempt to remove BY_HANDLE_PROTOCOL and GET_PROTOCOL and TEST_PROTOCOL Open List items
377 for (Link
= Prot
->OpenList
.ForwardLink
; Link
!= &Prot
->OpenList
;) {
378 OpenData
= CR (Link
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
379 if ((OpenData
->Attributes
&
380 (EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
| EFI_OPEN_PROTOCOL_GET_PROTOCOL
| EFI_OPEN_PROTOCOL_TEST_PROTOCOL
)) != 0)
382 Link
= RemoveEntryList (&OpenData
->Link
);
383 Prot
->OpenListCount
--;
386 Link
= Link
->ForwardLink
;
392 // If there are errors or still has open items in the list, then reconnect all the drivers and return an error
394 if (EFI_ERROR (Status
) || (Prot
->OpenListCount
> 0)) {
395 UnitTestConnectController (UserHandle
, NULL
, NULL
, TRUE
);
396 Status
= EFI_ACCESS_DENIED
;
403 Removes Protocol from the protocol list (but not the handle list).
405 @param Handle The handle to remove protocol on.
406 @param Protocol GUID of the protocol to be moved
407 @param Interface The interface of the protocol
409 @return Protocol Entry
413 UnitTestRemoveInterfaceFromProtocol (
415 IN EFI_GUID
*Protocol
,
419 PROTOCOL_INTERFACE
*Prot
;
420 PROTOCOL_NOTIFY
*ProtNotify
;
421 PROTOCOL_ENTRY
*ProtEntry
;
424 Prot
= UnitTestFindProtocolInterface (Handle
, Protocol
, Interface
);
426 ProtEntry
= Prot
->Protocol
;
429 // If there's a protocol notify location pointing to this entry, back it up one
431 for (Link
= ProtEntry
->Notify
.ForwardLink
; Link
!= &ProtEntry
->Notify
; Link
= Link
->ForwardLink
) {
432 ProtNotify
= CR (Link
, PROTOCOL_NOTIFY
, Link
, PROTOCOL_NOTIFY_SIGNATURE
);
434 if (ProtNotify
->Position
== &Prot
->ByProtocol
) {
435 ProtNotify
->Position
= Prot
->ByProtocol
.BackLink
;
440 // Remove the protocol interface entry
442 RemoveEntryList (&Prot
->ByProtocol
);
449 // Boot Services Function Implementation
453 Locate a certain GUID protocol interface in a Handle's protocols.
455 @param UserHandle The handle to obtain the protocol interface on
456 @param Protocol The GUID of the protocol
458 @return The requested protocol interface for the handle
462 UnitTestGetProtocolInterface (
463 IN EFI_HANDLE UserHandle
,
464 IN EFI_GUID
*Protocol
468 PROTOCOL_ENTRY
*ProtEntry
;
469 PROTOCOL_INTERFACE
*Prot
;
473 Status
= UnitTestValidateHandle (UserHandle
);
474 if (EFI_ERROR (Status
)) {
478 Handle
= (IHANDLE
*)UserHandle
;
481 // Look at each protocol interface for a match
483 for (Link
= Handle
->Protocols
.ForwardLink
; Link
!= &Handle
->Protocols
; Link
= Link
->ForwardLink
) {
484 Prot
= CR (Link
, PROTOCOL_INTERFACE
, Link
, PROTOCOL_INTERFACE_SIGNATURE
);
485 ProtEntry
= Prot
->Protocol
;
486 if (CompareGuid (&ProtEntry
->ProtocolID
, Protocol
)) {
495 Installs a protocol interface into the boot services environment.
497 @param UserHandle The handle to install the protocol handler on,
498 or NULL if a new handle is to be allocated
499 @param Protocol The protocol to add to the handle
500 @param InterfaceType Indicates whether Interface is supplied in
502 @param Interface The interface for the protocol being added
503 @param Notify indicates whether notify the notification list
506 @retval EFI_INVALID_PARAMETER Invalid parameter
507 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
508 @retval EFI_SUCCESS Protocol interface successfully installed
512 UnitTestInstallProtocolInterfaceNotify (
513 IN OUT EFI_HANDLE
*UserHandle
,
514 IN EFI_GUID
*Protocol
,
515 IN EFI_INTERFACE_TYPE InterfaceType
,
520 PROTOCOL_INTERFACE
*Prot
;
521 PROTOCOL_ENTRY
*ProtEntry
;
524 VOID
*ExistingInterface
;
527 // returns EFI_INVALID_PARAMETER if InterfaceType is invalid.
528 // Also added check for invalid UserHandle and Protocol pointers.
530 if ((UserHandle
== NULL
) || (Protocol
== NULL
)) {
531 return EFI_INVALID_PARAMETER
;
534 if (InterfaceType
!= EFI_NATIVE_INTERFACE
) {
535 return EFI_INVALID_PARAMETER
;
539 // Print debug message
541 UT_LOG_INFO ("InstallProtocolInterface: %g %p\n", Protocol
, Interface
);
543 Status
= EFI_OUT_OF_RESOURCES
;
547 if (*UserHandle
!= NULL
) {
548 Status
= UnitTestHandleProtocol (*UserHandle
, Protocol
, (VOID
**)&ExistingInterface
);
549 if (!EFI_ERROR (Status
)) {
550 return EFI_INVALID_PARAMETER
;
555 // Lookup the Protocol Entry for the requested protocol
557 ProtEntry
= UnitTestFindProtocolEntry (Protocol
, TRUE
);
558 if (ProtEntry
== NULL
) {
563 // Allocate a new protocol interface structure
565 Prot
= AllocateZeroPool (sizeof (PROTOCOL_INTERFACE
));
567 Status
= EFI_OUT_OF_RESOURCES
;
572 // If caller didn't supply a handle, allocate a new one
574 Handle
= (IHANDLE
*)*UserHandle
;
575 if (Handle
== NULL
) {
576 Handle
= AllocateZeroPool (sizeof (IHANDLE
));
577 if (Handle
== NULL
) {
578 Status
= EFI_OUT_OF_RESOURCES
;
583 // Initialize new handler structure
585 Handle
->Signature
= EFI_HANDLE_SIGNATURE
;
586 InitializeListHead (&Handle
->Protocols
);
589 // Initialize the Key to show that the handle has been created/modified
591 gHandleDatabaseKey
++;
592 Handle
->Key
= gHandleDatabaseKey
;
595 // Add this handle to the list global list of all handles
598 InsertTailList (&gHandleList
, &Handle
->AllHandles
);
600 Status
= UnitTestValidateHandle (Handle
);
601 if (EFI_ERROR (Status
)) {
602 DEBUG ((DEBUG_ERROR
, "InstallProtocolInterface: input handle at 0x%x is invalid\n", Handle
));
608 // Each interface that is added must be unique
610 ASSERT (UnitTestFindProtocolInterface (Handle
, Protocol
, Interface
) == NULL
);
613 // Initialize the protocol interface structure
615 Prot
->Signature
= PROTOCOL_INTERFACE_SIGNATURE
;
616 Prot
->Handle
= Handle
;
617 Prot
->Protocol
= ProtEntry
;
618 Prot
->Interface
= Interface
;
621 // Initialize OpenProtocol Data base
623 InitializeListHead (&Prot
->OpenList
);
624 Prot
->OpenListCount
= 0;
627 // Add this protocol interface to the head of the supported
628 // protocol list for this handle
630 InsertHeadList (&Handle
->Protocols
, &Prot
->Link
);
633 // Add this protocol interface to the tail of the
636 InsertTailList (&ProtEntry
->Protocols
, &Prot
->ByProtocol
);
639 // Notify the notification list for this protocol
642 UnitTestNotifyProtocolEntry (ProtEntry
);
645 Status
= EFI_SUCCESS
;
648 if (!EFI_ERROR (Status
)) {
650 // Return the new handle back to the caller
652 *UserHandle
= Handle
;
655 // There was an error, clean up
658 UnitTestFreePool (Prot
);
661 DEBUG ((DEBUG_ERROR
, "InstallProtocolInterface: %g %p failed with %r\n", Protocol
, Interface
, Status
));
668 Wrapper function to UnitTestInstallProtocolInterfaceNotify. This is the public API which
669 Calls the private one which contains a BOOLEAN parameter for notifications
671 @param UserHandle The handle to install the protocol handler on,
672 or NULL if a new handle is to be allocated
673 @param Protocol The protocol to add to the handle
674 @param InterfaceType Indicates whether Interface is supplied in
676 @param Interface The interface for the protocol being added
683 UnitTestInstallProtocolInterface (
684 IN OUT EFI_HANDLE
*UserHandle
,
685 IN EFI_GUID
*Protocol
,
686 IN EFI_INTERFACE_TYPE InterfaceType
,
690 return UnitTestInstallProtocolInterfaceNotify (
700 Reinstall a protocol interface on a device handle. The OldInterface for Protocol is replaced by the NewInterface.
702 @param UserHandle Handle on which the interface is to be
704 @param Protocol The numeric ID of the interface
705 @param OldInterface A pointer to the old interface
706 @param NewInterface A pointer to the new interface
708 @retval EFI_SUCCESS The protocol interface was installed
709 @retval EFI_NOT_FOUND The OldInterface on the handle was not found
710 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value
715 UnitTestReinstallProtocolInterface (
716 IN EFI_HANDLE UserHandle
,
717 IN EFI_GUID
*Protocol
,
718 IN VOID
*OldInterface
,
719 IN VOID
*NewInterface
722 return EFI_NOT_AVAILABLE_YET
;
726 Uninstalls all instances of a protocol:interfacer from a handle.
727 If the last protocol interface is remove from the handle, the
730 @param UserHandle The handle to remove the protocol handler from
731 @param Protocol The protocol, of protocol:interface, to remove
732 @param Interface The interface, of protocol:interface, to remove
734 @retval EFI_INVALID_PARAMETER Protocol is NULL.
735 @retval EFI_SUCCESS Protocol interface successfully uninstalled.
740 UnitTestUninstallProtocolInterface (
741 IN EFI_HANDLE UserHandle
,
742 IN EFI_GUID
*Protocol
,
748 PROTOCOL_INTERFACE
*Prot
;
751 // Check that Protocol is valid
753 if (Protocol
== NULL
) {
754 return EFI_INVALID_PARAMETER
;
758 // Check that UserHandle is a valid handle
760 Status
= UnitTestValidateHandle (UserHandle
);
761 if (EFI_ERROR (Status
)) {
766 // Check that Protocol exists on UserHandle, and Interface matches the interface in the database
768 Prot
= UnitTestFindProtocolInterface (UserHandle
, Protocol
, Interface
);
770 Status
= EFI_NOT_FOUND
;
775 // Attempt to disconnect all drivers that are using the protocol interface that is about to be removed
777 Status
= UnitTestDisconnectControllersUsingProtocolInterface (
781 if (EFI_ERROR (Status
)) {
783 // One or more drivers refused to release, so return the error
789 // Remove the protocol interface from the protocol
791 Status
= EFI_NOT_FOUND
;
792 Handle
= (IHANDLE
*)UserHandle
;
793 Prot
= UnitTestRemoveInterfaceFromProtocol (Handle
, Protocol
, Interface
);
797 // Update the Key to show that the handle has been created/modified
799 gHandleDatabaseKey
++;
800 Handle
->Key
= gHandleDatabaseKey
;
803 // Remove the protocol interface from the handle
805 RemoveEntryList (&Prot
->Link
);
812 Status
= EFI_SUCCESS
;
816 // If there are no more handlers for the handle, free the handle
818 if (IsListEmpty (&Handle
->Protocols
)) {
819 Handle
->Signature
= 0;
820 RemoveEntryList (&Handle
->AllHandles
);
829 Queries a handle to determine if it supports a specified protocol.
831 @param UserHandle The handle being queried.
832 @param Protocol The published unique identifier of the protocol.
833 @param Interface Supplies the address where a pointer to the
834 corresponding Protocol Interface is returned.
836 @return The requested protocol interface for the handle
841 UnitTestHandleProtocol (
842 IN EFI_HANDLE UserHandle
,
843 IN EFI_GUID
*Protocol
,
847 return UnitTestOpenProtocol (
853 EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
858 Add a new protocol notification record for the request protocol.
860 @param Protocol The requested protocol to add the notify
862 @param Event The event to signal
863 @param Registration Returns the registration record
865 @retval EFI_INVALID_PARAMETER Invalid parameter
866 @retval EFI_SUCCESS Successfully returned the registration record
872 UnitTestRegisterProtocolNotify (
873 IN EFI_GUID
*Protocol
,
875 OUT VOID
**Registration
878 return EFI_NOT_AVAILABLE_YET
;
882 Locates the requested handle(s) and returns them in Buffer.
884 @param SearchType The type of search to perform to locate the
886 @param Protocol The protocol to search for
887 @param SearchKey Dependant on SearchType
888 @param BufferSize On input the size of Buffer. On output the
889 size of data returned.
890 @param Buffer The buffer to return the results in
892 @retval EFI_BUFFER_TOO_SMALL Buffer too small, required buffer size is
893 returned in BufferSize.
894 @retval EFI_INVALID_PARAMETER Invalid parameter
895 @retval EFI_SUCCESS Successfully found the requested handle(s) and
896 returns them in Buffer.
901 UnitTestLocateHandle (
902 IN EFI_LOCATE_SEARCH_TYPE SearchType
,
903 IN EFI_GUID
*Protocol OPTIONAL
,
904 IN VOID
*SearchKey OPTIONAL
,
905 IN OUT UINTN
*BufferSize
,
906 OUT EFI_HANDLE
*Buffer
910 LOCATE_POSITION Position
;
911 PROTOCOL_NOTIFY
*ProtNotify
;
912 UNIT_TEST_GET_NEXT GetNext
;
915 IHANDLE
**ResultBuffer
;
918 if (BufferSize
== NULL
) {
919 return EFI_INVALID_PARAMETER
;
922 if ((*BufferSize
> 0) && (Buffer
== NULL
)) {
923 return EFI_INVALID_PARAMETER
;
929 // Set initial position
931 Position
.Protocol
= Protocol
;
932 Position
.SearchKey
= SearchKey
;
933 Position
.Position
= &gHandleList
;
936 ResultBuffer
= (IHANDLE
**)Buffer
;
937 Status
= EFI_SUCCESS
;
940 // Get the search function based on type
942 switch (SearchType
) {
944 GetNext
= UnitTestGetNextLocateAllHandles
;
947 case ByRegisterNotify
:
949 // Must have SearchKey for locate ByRegisterNotify
951 if (SearchKey
== NULL
) {
952 Status
= EFI_INVALID_PARAMETER
;
956 GetNext
= UnitTestGetNextLocateByRegisterNotify
;
960 GetNext
= UnitTestGetNextLocateByProtocol
;
961 if (Protocol
== NULL
) {
962 Status
= EFI_INVALID_PARAMETER
;
967 // Look up the protocol entry and set the head pointer
969 Position
.ProtEntry
= UnitTestFindProtocolEntry (Protocol
, FALSE
);
970 if (Position
.ProtEntry
== NULL
) {
971 Status
= EFI_NOT_FOUND
;
975 Position
.Position
= &Position
.ProtEntry
->Protocols
;
979 Status
= EFI_INVALID_PARAMETER
;
983 if (EFI_ERROR (Status
)) {
987 ASSERT (GetNext
!= NULL
);
989 // Enumerate out the matching handles
991 mEfiLocateHandleRequest
+= 1;
994 // Get the next handle. If no more handles, stop
996 Handle
= GetNext (&Position
, &Interface
);
997 if (NULL
== Handle
) {
1002 // Increase the resulting buffer size, and if this handle
1005 ResultSize
+= sizeof (Handle
);
1006 if (ResultSize
<= *BufferSize
) {
1007 *ResultBuffer
= Handle
;
1013 // If the result is a zero length buffer, then there were no
1016 if (ResultSize
== 0) {
1017 Status
= EFI_NOT_FOUND
;
1020 // Return the resulting buffer size. If it's larger than what
1021 // was passed, then set the error code
1023 if (ResultSize
> *BufferSize
) {
1024 Status
= EFI_BUFFER_TOO_SMALL
;
1027 *BufferSize
= ResultSize
;
1029 if ((SearchType
== ByRegisterNotify
) && !EFI_ERROR (Status
)) {
1031 // If this is a search by register notify and a handle was
1032 // returned, update the register notification position
1034 ASSERT (SearchKey
!= NULL
);
1035 ProtNotify
= SearchKey
;
1036 ProtNotify
->Position
= ProtNotify
->Position
->ForwardLink
;
1044 Locates the handle to a device on the device path that best matches the specified protocol.
1046 @param Protocol The protocol to search for.
1047 @param DevicePath On input, a pointer to a pointer to the device
1048 path. On output, the device path pointer is
1049 modified to point to the remaining part of the
1051 @param Device A pointer to the returned device handle.
1053 @retval EFI_SUCCESS The resulting handle was returned.
1054 @retval EFI_NOT_FOUND No handles matched the search.
1055 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
1060 UnitTestLocateDevicePath (
1061 IN EFI_GUID
*Protocol
,
1062 IN OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePath
,
1063 OUT EFI_HANDLE
*Device
1066 return EFI_NOT_AVAILABLE_YET
;
1070 Boot Service called to add, modify, or remove a system configuration table from
1071 the EFI System Table.
1073 @param Guid Pointer to the GUID for the entry to add, update, or
1075 @param Table Pointer to the configuration table for the entry to add,
1076 update, or remove, may be NULL.
1078 @return EFI_SUCCESS Guid, Table pair added, updated, or removed.
1079 @return EFI_INVALID_PARAMETER Input GUID not valid.
1080 @return EFI_NOT_FOUND Attempted to delete non-existant entry
1081 @return EFI_OUT_OF_RESOURCES Not enough memory available
1086 UnitTestInstallConfigurationTable (
1091 return EFI_NOT_AVAILABLE_YET
;
1095 Locates the installed protocol handler for the handle, and
1096 invokes it to obtain the protocol interface. Usage information
1097 is registered in the protocol data base.
1099 @param UserHandle The handle to obtain the protocol interface on
1100 @param Protocol The ID of the protocol
1101 @param Interface The location to return the protocol interface
1102 @param ImageHandle The handle of the Image that is opening the
1103 protocol interface specified by Protocol and
1105 @param ControllerHandle The controller handle that is requiring this
1107 @param Attributes The open mode of the protocol interface
1108 specified by Handle and Protocol.
1110 @retval EFI_INVALID_PARAMETER Protocol is NULL.
1111 @retval EFI_SUCCESS Get the protocol interface.
1116 UnitTestOpenProtocol (
1117 IN EFI_HANDLE UserHandle
,
1118 IN EFI_GUID
*Protocol
,
1119 OUT VOID
**Interface OPTIONAL
,
1120 IN EFI_HANDLE ImageHandle
,
1121 IN EFI_HANDLE ControllerHandle
,
1122 IN UINT32 Attributes
1126 PROTOCOL_INTERFACE
*Prot
;
1128 OPEN_PROTOCOL_DATA
*OpenData
;
1135 // Check for invalid Protocol
1137 if (Protocol
== NULL
) {
1138 return EFI_INVALID_PARAMETER
;
1142 // Check for invalid Interface
1144 if ((Attributes
!= EFI_OPEN_PROTOCOL_TEST_PROTOCOL
) && (Interface
== NULL
)) {
1145 return EFI_INVALID_PARAMETER
;
1149 // Check for invalid UserHandle
1151 Status
= UnitTestValidateHandle (UserHandle
);
1152 if (EFI_ERROR (Status
)) {
1157 // Check for invalid Attributes
1159 switch (Attributes
) {
1160 case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
:
1161 Status
= UnitTestValidateHandle (ImageHandle
);
1162 if (EFI_ERROR (Status
)) {
1166 Status
= UnitTestValidateHandle (ControllerHandle
);
1167 if (EFI_ERROR (Status
)) {
1171 if (UserHandle
== ControllerHandle
) {
1172 return EFI_INVALID_PARAMETER
;
1176 case EFI_OPEN_PROTOCOL_BY_DRIVER
:
1177 case EFI_OPEN_PROTOCOL_BY_DRIVER
| EFI_OPEN_PROTOCOL_EXCLUSIVE
:
1178 Status
= UnitTestValidateHandle (ImageHandle
);
1179 if (EFI_ERROR (Status
)) {
1183 Status
= UnitTestValidateHandle (ControllerHandle
);
1184 if (EFI_ERROR (Status
)) {
1189 case EFI_OPEN_PROTOCOL_EXCLUSIVE
:
1190 Status
= UnitTestValidateHandle (ImageHandle
);
1191 if (EFI_ERROR (Status
)) {
1196 case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
:
1197 case EFI_OPEN_PROTOCOL_GET_PROTOCOL
:
1198 case EFI_OPEN_PROTOCOL_TEST_PROTOCOL
:
1201 return EFI_INVALID_PARAMETER
;
1205 // Look at each protocol interface for a match
1207 Prot
= UnitTestGetProtocolInterface (UserHandle
, Protocol
);
1209 Status
= EFI_UNSUPPORTED
;
1213 Status
= EFI_SUCCESS
;
1217 for ( Link
= Prot
->OpenList
.ForwardLink
; Link
!= &Prot
->OpenList
; Link
= Link
->ForwardLink
) {
1218 OpenData
= CR (Link
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
1219 ExactMatch
= (BOOLEAN
)((OpenData
->AgentHandle
== ImageHandle
) &&
1220 (OpenData
->Attributes
== Attributes
) &&
1221 (OpenData
->ControllerHandle
== ControllerHandle
));
1222 if ((OpenData
->Attributes
& EFI_OPEN_PROTOCOL_BY_DRIVER
) != 0) {
1225 Status
= EFI_ALREADY_STARTED
;
1230 if ((OpenData
->Attributes
& EFI_OPEN_PROTOCOL_EXCLUSIVE
) != 0) {
1232 } else if (ExactMatch
) {
1233 OpenData
->OpenCount
++;
1234 Status
= EFI_SUCCESS
;
1240 // ByDriver TRUE -> A driver is managing (UserHandle, Protocol)
1241 // ByDriver FALSE -> There are no drivers managing (UserHandle, Protocol)
1242 // Exclusive TRUE -> Something has exclusive access to (UserHandle, Protocol)
1243 // Exclusive FALSE -> Nothing has exclusive access to (UserHandle, Protocol)
1246 switch (Attributes
) {
1247 case EFI_OPEN_PROTOCOL_BY_DRIVER
:
1248 if (Exclusive
|| ByDriver
) {
1249 Status
= EFI_ACCESS_DENIED
;
1254 case EFI_OPEN_PROTOCOL_BY_DRIVER
| EFI_OPEN_PROTOCOL_EXCLUSIVE
:
1255 case EFI_OPEN_PROTOCOL_EXCLUSIVE
:
1257 Status
= EFI_ACCESS_DENIED
;
1264 for (Link
= Prot
->OpenList
.ForwardLink
; Link
!= &Prot
->OpenList
; Link
= Link
->ForwardLink
) {
1265 OpenData
= CR (Link
, OPEN_PROTOCOL_DATA
, Link
, OPEN_PROTOCOL_DATA_SIGNATURE
);
1266 if ((OpenData
->Attributes
& EFI_OPEN_PROTOCOL_BY_DRIVER
) != 0) {
1268 Status
= UnitTestDisconnectController (UserHandle
, OpenData
->AgentHandle
, NULL
);
1269 if (EFI_ERROR (Status
)) {
1270 Status
= EFI_ACCESS_DENIED
;
1277 } while (Disconnect
);
1281 case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
:
1282 case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
:
1283 case EFI_OPEN_PROTOCOL_GET_PROTOCOL
:
1284 case EFI_OPEN_PROTOCOL_TEST_PROTOCOL
:
1288 if (ImageHandle
== NULL
) {
1289 Status
= EFI_SUCCESS
;
1296 OpenData
= AllocatePool (sizeof (OPEN_PROTOCOL_DATA
));
1297 if (OpenData
== NULL
) {
1298 Status
= EFI_OUT_OF_RESOURCES
;
1300 OpenData
->Signature
= OPEN_PROTOCOL_DATA_SIGNATURE
;
1301 OpenData
->AgentHandle
= ImageHandle
;
1302 OpenData
->ControllerHandle
= ControllerHandle
;
1303 OpenData
->Attributes
= Attributes
;
1304 OpenData
->OpenCount
= 1;
1305 InsertTailList (&Prot
->OpenList
, &OpenData
->Link
);
1306 Prot
->OpenListCount
++;
1307 Status
= EFI_SUCCESS
;
1312 if (Attributes
!= EFI_OPEN_PROTOCOL_TEST_PROTOCOL
) {
1314 // Keep Interface unmodified in case of any Error
1315 // except EFI_ALREADY_STARTED and EFI_UNSUPPORTED.
1317 if (!EFI_ERROR (Status
) || (Status
== EFI_ALREADY_STARTED
)) {
1319 // According to above logic, if 'Prot' is NULL, then the 'Status' must be
1320 // EFI_UNSUPPORTED. Here the 'Status' is not EFI_UNSUPPORTED, so 'Prot'
1321 // must be not NULL.
1323 // The ASSERT here is for addressing a false positive NULL pointer
1324 // dereference issue raised from static analysis.
1326 ASSERT (Prot
!= NULL
);
1328 // EFI_ALREADY_STARTED is not an error for bus driver.
1329 // Return the corresponding protocol interface.
1331 *Interface
= Prot
->Interface
;
1332 } else if (Status
== EFI_UNSUPPORTED
) {
1334 // Return NULL Interface if Unsupported Protocol.
1344 Closes a protocol on a handle that was opened using OpenProtocol().
1346 @param UserHandle The handle for the protocol interface that was
1347 previously opened with OpenProtocol(), and is
1349 @param Protocol The published unique identifier of the protocol.
1350 It is the caller's responsibility to pass in a
1352 @param AgentHandle The handle of the agent that is closing the
1354 @param ControllerHandle If the agent that opened a protocol is a driver
1355 that follows the EFI Driver Model, then this
1356 parameter is the controller handle that required
1357 the protocol interface. If the agent does not
1358 follow the EFI Driver Model, then this parameter
1359 is optional and may be NULL.
1361 @retval EFI_SUCCESS The protocol instance was closed.
1362 @retval EFI_INVALID_PARAMETER Handle, AgentHandle or ControllerHandle is not a
1364 @retval EFI_NOT_FOUND Can not find the specified protocol or
1370 UnitTestCloseProtocol (
1371 IN EFI_HANDLE UserHandle
,
1372 IN EFI_GUID
*Protocol
,
1373 IN EFI_HANDLE AgentHandle
,
1374 IN EFI_HANDLE ControllerHandle
1377 return EFI_NOT_AVAILABLE_YET
;
1381 Return information about Opened protocols in the system
1383 @param UserHandle The handle to close the protocol interface on
1384 @param Protocol The ID of the protocol
1385 @param EntryBuffer A pointer to a buffer of open protocol
1386 information in the form of
1387 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY structures.
1388 @param EntryCount Number of EntryBuffer entries
1393 UnitTestOpenProtocolInformation (
1394 IN EFI_HANDLE UserHandle
,
1395 IN EFI_GUID
*Protocol
,
1396 OUT EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
**EntryBuffer
,
1397 OUT UINTN
*EntryCount
1400 return EFI_NOT_AVAILABLE_YET
;
1404 Retrieves the list of protocol interface GUIDs that are installed on a handle in a buffer allocated
1407 @param UserHandle The handle from which to retrieve the list of
1408 protocol interface GUIDs.
1409 @param ProtocolBuffer A pointer to the list of protocol interface GUID
1410 pointers that are installed on Handle.
1411 @param ProtocolBufferCount A pointer to the number of GUID pointers present
1414 @retval EFI_SUCCESS The list of protocol interface GUIDs installed
1415 on Handle was returned in ProtocolBuffer. The
1416 number of protocol interface GUIDs was returned
1417 in ProtocolBufferCount.
1418 @retval EFI_INVALID_PARAMETER Handle is NULL.
1419 @retval EFI_INVALID_PARAMETER Handle is not a valid EFI_HANDLE.
1420 @retval EFI_INVALID_PARAMETER ProtocolBuffer is NULL.
1421 @retval EFI_INVALID_PARAMETER ProtocolBufferCount is NULL.
1422 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the
1428 UnitTestProtocolsPerHandle (
1429 IN EFI_HANDLE UserHandle
,
1430 OUT EFI_GUID
***ProtocolBuffer
,
1431 OUT UINTN
*ProtocolBufferCount
1434 return EFI_NOT_AVAILABLE_YET
;
1438 Function returns an array of handles that support the requested protocol
1439 in a buffer allocated from pool. This is a version of UnitTestLocateHandle()
1440 that allocates a buffer for the caller.
1442 @param SearchType Specifies which handle(s) are to be returned.
1443 @param Protocol Provides the protocol to search by. This
1444 parameter is only valid for SearchType
1446 @param SearchKey Supplies the search key depending on the
1448 @param NumberHandles The number of handles returned in Buffer.
1449 @param Buffer A pointer to the buffer to return the requested
1450 array of handles that support Protocol.
1452 @retval EFI_SUCCESS The result array of handles was returned.
1453 @retval EFI_NOT_FOUND No handles match the search.
1454 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the
1456 @retval EFI_INVALID_PARAMETER One or more parameters are not valid.
1461 UnitTestLocateHandleBuffer (
1462 IN EFI_LOCATE_SEARCH_TYPE SearchType
,
1463 IN EFI_GUID
*Protocol OPTIONAL
,
1464 IN VOID
*SearchKey OPTIONAL
,
1465 IN OUT UINTN
*NumberHandles
,
1466 OUT EFI_HANDLE
**Buffer
1472 if (NumberHandles
== NULL
) {
1473 return EFI_INVALID_PARAMETER
;
1476 if (Buffer
== NULL
) {
1477 return EFI_INVALID_PARAMETER
;
1483 Status
= UnitTestLocateHandle (
1491 // LocateHandleBuffer() returns incorrect status code if SearchType is
1494 // Add code to correctly handle expected errors from UnitTestLocateHandle().
1496 if (EFI_ERROR (Status
) && (Status
!= EFI_BUFFER_TOO_SMALL
)) {
1497 if (Status
!= EFI_INVALID_PARAMETER
) {
1498 Status
= EFI_NOT_FOUND
;
1504 *Buffer
= AllocatePool (BufferSize
);
1505 if (*Buffer
== NULL
) {
1506 return EFI_OUT_OF_RESOURCES
;
1509 Status
= UnitTestLocateHandle (
1517 *NumberHandles
= BufferSize
/ sizeof (EFI_HANDLE
);
1518 if (EFI_ERROR (Status
)) {
1526 Return the first Protocol Interface that matches the Protocol GUID. If
1527 Registration is passed in, return a Protocol Instance that was just add
1528 to the system. If Registration is NULL return the first Protocol Interface
1531 @param Protocol The protocol to search for
1532 @param Registration Optional Registration Key returned from
1533 RegisterProtocolNotify()
1534 @param Interface Return the Protocol interface (instance).
1536 @retval EFI_SUCCESS If a valid Interface is returned
1537 @retval EFI_INVALID_PARAMETER Invalid parameter
1538 @retval EFI_NOT_FOUND Protocol interface not found
1543 UnitTestLocateProtocol (
1544 IN EFI_GUID
*Protocol
,
1545 IN VOID
*Registration OPTIONAL
,
1546 OUT VOID
**Interface
1549 return EFI_NOT_AVAILABLE_YET
;
1553 Installs a list of protocol interface into the boot services environment.
1554 This function calls InstallProtocolInterface() in a loop. If any error
1555 occurs all the protocols added by this function are removed. This is
1556 basically a lib function to save space.
1558 @param Handle The handle to install the protocol handlers on,
1559 or NULL if a new handle is to be allocated
1560 @param ... EFI_GUID followed by protocol instance. A NULL
1561 terminates the list. The pairs are the
1562 arguments to InstallProtocolInterface(). All the
1563 protocols are added to Handle.
1565 @retval EFI_SUCCESS All the protocol interface was installed.
1566 @retval EFI_OUT_OF_RESOURCES There was not enough memory in pool to install all the protocols.
1567 @retval EFI_ALREADY_STARTED A Device Path Protocol instance was passed in that is already present in
1568 the handle database.
1569 @retval EFI_INVALID_PARAMETER Handle is NULL.
1570 @retval EFI_INVALID_PARAMETER Protocol is already installed on the handle specified by Handle.
1575 UnitTestInstallMultipleProtocolInterfaces (
1576 IN OUT EFI_HANDLE
*Handle
,
1580 return EFI_NOT_AVAILABLE_YET
;
1584 Uninstalls a list of protocol interface in the boot services environment.
1585 This function calls UninstallProtocolInterface() in a loop. This is
1586 basically a lib function to save space.
1588 @param Handle The handle to uninstall the protocol
1589 @param ... EFI_GUID followed by protocol instance. A NULL
1590 terminates the list. The pairs are the
1591 arguments to UninstallProtocolInterface(). All
1592 the protocols are added to Handle.
1599 UnitTestUninstallMultipleProtocolInterfaces (
1600 IN EFI_HANDLE Handle
,
1610 VA_START (Args
, Handle
);
1611 for (Index
= 0, Status
= EFI_SUCCESS
; !EFI_ERROR (Status
); Index
++) {
1613 // If protocol is NULL, then it's the end of the list
1615 Protocol
= VA_ARG (Args
, EFI_GUID
*);
1616 if (Protocol
== NULL
) {
1620 Interface
= VA_ARG (Args
, VOID
*);
1625 Status
= UnitTestUninstallProtocolInterface (Handle
, Protocol
, Interface
);
1631 // If there was an error, add all the interfaces that were
1632 // uninstalled without any errors
1634 if (EFI_ERROR (Status
)) {
1636 // Reset the va_arg back to the first argument.
1638 VA_START (Args
, Handle
);
1639 for ( ; Index
> 1; Index
--) {
1640 Protocol
= VA_ARG (Args
, EFI_GUID
*);
1641 Interface
= VA_ARG (Args
, VOID
*);
1642 UnitTestInstallProtocolInterface (&Handle
, Protocol
, EFI_NATIVE_INTERFACE
, Interface
);
1646 Status
= EFI_INVALID_PARAMETER
;