--- /dev/null
+/** @file\r
+ Implementation of protocol related services in the UEFI Boot Services table for use in unit tests.\r
+\r
+Copyright (c) Microsoft Corporation\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include "UnitTestUefiBootServicesTableLibProtocol.h"\r
+\r
+STATIC LIST_ENTRY mProtocolDatabase = INITIALIZE_LIST_HEAD_VARIABLE (mProtocolDatabase);\r
+STATIC LIST_ENTRY gHandleList = INITIALIZE_LIST_HEAD_VARIABLE (gHandleList);\r
+STATIC UINT64 gHandleDatabaseKey = 0;\r
+STATIC UINTN mEfiLocateHandleRequest = 0;\r
+\r
+//\r
+// Helper Functions\r
+//\r
+\r
+/**\r
+ Check whether a handle is a valid EFI_HANDLE\r
+\r
+ @param UserHandle The handle to check\r
+\r
+ @retval EFI_INVALID_PARAMETER The handle is NULL or not a valid EFI_HANDLE.\r
+ @retval EFI_SUCCESS The handle is valid EFI_HANDLE.\r
+\r
+**/\r
+EFI_STATUS\r
+UnitTestValidateHandle (\r
+ IN EFI_HANDLE UserHandle\r
+ )\r
+{\r
+ IHANDLE *Handle;\r
+ LIST_ENTRY *Link;\r
+\r
+ if (UserHandle == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ for (Link = gHandleList.BackLink; Link != &gHandleList; Link = Link->BackLink) {\r
+ Handle = CR (Link, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);\r
+ if (Handle == (IHANDLE *)UserHandle) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ return EFI_INVALID_PARAMETER;\r
+}\r
+\r
+/**\r
+ Finds the protocol entry for the requested protocol.\r
+\r
+ @param Protocol The ID of the protocol\r
+ @param Create Create a new entry if not found\r
+\r
+ @return Protocol entry\r
+\r
+**/\r
+PROTOCOL_ENTRY *\r
+UnitTestFindProtocolEntry (\r
+ IN EFI_GUID *Protocol,\r
+ IN BOOLEAN Create\r
+ )\r
+{\r
+ LIST_ENTRY *Link;\r
+ PROTOCOL_ENTRY *Item;\r
+ PROTOCOL_ENTRY *ProtEntry;\r
+\r
+ //\r
+ // Search the database for the matching GUID\r
+ //\r
+\r
+ ProtEntry = NULL;\r
+ for (Link = mProtocolDatabase.ForwardLink;\r
+ Link != &mProtocolDatabase;\r
+ Link = Link->ForwardLink)\r
+ {\r
+ Item = CR (Link, PROTOCOL_ENTRY, AllEntries, PROTOCOL_ENTRY_SIGNATURE);\r
+ if (CompareGuid (&Item->ProtocolID, Protocol)) {\r
+ //\r
+ // This is the protocol entry\r
+ //\r
+\r
+ ProtEntry = Item;\r
+ break;\r
+ }\r
+ }\r
+\r
+ //\r
+ // If the protocol entry was not found and Create is TRUE, then\r
+ // allocate a new entry\r
+ //\r
+ if ((ProtEntry == NULL) && Create) {\r
+ ProtEntry = AllocatePool (sizeof (PROTOCOL_ENTRY));\r
+\r
+ if (ProtEntry != NULL) {\r
+ //\r
+ // Initialize new protocol entry structure\r
+ //\r
+ ProtEntry->Signature = PROTOCOL_ENTRY_SIGNATURE;\r
+ CopyGuid ((VOID *)&ProtEntry->ProtocolID, Protocol);\r
+ InitializeListHead (&ProtEntry->Protocols);\r
+ InitializeListHead (&ProtEntry->Notify);\r
+\r
+ //\r
+ // Add it to protocol database\r
+ //\r
+ InsertTailList (&mProtocolDatabase, &ProtEntry->AllEntries);\r
+ }\r
+ }\r
+\r
+ return ProtEntry;\r
+}\r
+\r
+/**\r
+ Finds the protocol instance for the requested handle and protocol.\r
+ Note: This function doesn't do parameters checking, it's caller's responsibility\r
+ to pass in valid parameters.\r
+\r
+ @param Handle The handle to search the protocol on\r
+ @param Protocol GUID of the protocol\r
+ @param Interface The interface for the protocol being searched\r
+\r
+ @return Protocol instance (NULL: Not found)\r
+\r
+**/\r
+PROTOCOL_INTERFACE *\r
+UnitTestFindProtocolInterface (\r
+ IN IHANDLE *Handle,\r
+ IN EFI_GUID *Protocol,\r
+ IN VOID *Interface\r
+ )\r
+{\r
+ PROTOCOL_INTERFACE *Prot;\r
+ PROTOCOL_ENTRY *ProtEntry;\r
+ LIST_ENTRY *Link;\r
+\r
+ Prot = NULL;\r
+\r
+ //\r
+ // Lookup the protocol entry for this protocol ID\r
+ //\r
+\r
+ ProtEntry = UnitTestFindProtocolEntry (Protocol, FALSE);\r
+ if (ProtEntry != NULL) {\r
+ //\r
+ // Look at each protocol interface for any matches\r
+ //\r
+ for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {\r
+ //\r
+ // If this protocol interface matches, remove it\r
+ //\r
+ Prot = CR (Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);\r
+ if ((Prot->Interface == Interface) && (Prot->Protocol == ProtEntry)) {\r
+ break;\r
+ }\r
+\r
+ Prot = NULL;\r
+ }\r
+ }\r
+\r
+ return Prot;\r
+}\r
+\r
+/**\r
+ Signal event for every protocol in protocol entry.\r
+\r
+ @param ProtEntry Protocol entry\r
+\r
+**/\r
+VOID\r
+UnitTestNotifyProtocolEntry (\r
+ IN PROTOCOL_ENTRY *ProtEntry\r
+ )\r
+{\r
+ PROTOCOL_NOTIFY *ProtNotify;\r
+ LIST_ENTRY *Link;\r
+\r
+ for (Link = ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link = Link->ForwardLink) {\r
+ ProtNotify = CR (Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);\r
+ UnitTestSignalEvent (ProtNotify->Event);\r
+ }\r
+}\r
+\r
+/**\r
+ Routine to get the next Handle, when you are searching for all handles.\r
+\r
+ @param Position Information about which Handle to seach for.\r
+ @param Interface Return the interface structure for the matching\r
+ protocol.\r
+\r
+ @return An pointer to IHANDLE if the next Position is not the end of the list.\r
+ Otherwise,NULL is returned.\r
+\r
+**/\r
+IHANDLE *\r
+UnitTestGetNextLocateAllHandles (\r
+ IN OUT LOCATE_POSITION *Position,\r
+ OUT VOID **Interface\r
+ )\r
+{\r
+ IHANDLE *Handle;\r
+\r
+ //\r
+ // Next handle\r
+ //\r
+ Position->Position = Position->Position->ForwardLink;\r
+\r
+ //\r
+ // If not at the end of the list, get the handle\r
+ //\r
+ Handle = NULL;\r
+ *Interface = NULL;\r
+ if (Position->Position != &gHandleList) {\r
+ Handle = CR (Position->Position, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);\r
+ }\r
+\r
+ return Handle;\r
+}\r
+\r
+/**\r
+ Routine to get the next Handle, when you are searching for register protocol\r
+ notifies.\r
+\r
+ @param Position Information about which Handle to seach for.\r
+ @param Interface Return the interface structure for the matching\r
+ protocol.\r
+\r
+ @return An pointer to IHANDLE if the next Position is not the end of the list.\r
+ Otherwise,NULL is returned.\r
+\r
+**/\r
+IHANDLE *\r
+UnitTestGetNextLocateByRegisterNotify (\r
+ IN OUT LOCATE_POSITION *Position,\r
+ OUT VOID **Interface\r
+ )\r
+{\r
+ IHANDLE *Handle;\r
+ PROTOCOL_NOTIFY *ProtNotify;\r
+ PROTOCOL_INTERFACE *Prot;\r
+ LIST_ENTRY *Link;\r
+\r
+ Handle = NULL;\r
+ *Interface = NULL;\r
+ ProtNotify = Position->SearchKey;\r
+\r
+ //\r
+ // If this is the first request, get the next handle\r
+ //\r
+ if (ProtNotify != NULL) {\r
+ ASSERT (ProtNotify->Signature == PROTOCOL_NOTIFY_SIGNATURE);\r
+ Position->SearchKey = NULL;\r
+\r
+ //\r
+ // If not at the end of the list, get the next handle\r
+ //\r
+ Link = ProtNotify->Position->ForwardLink;\r
+ if (Link != &ProtNotify->Protocol->Protocols) {\r
+ Prot = CR (Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE);\r
+ Handle = Prot->Handle;\r
+ *Interface = Prot->Interface;\r
+ }\r
+ }\r
+\r
+ return Handle;\r
+}\r
+\r
+/**\r
+ Routine to get the next Handle, when you are searching for a given protocol.\r
+\r
+ @param Position Information about which Handle to seach for.\r
+ @param Interface Return the interface structure for the matching\r
+ protocol.\r
+\r
+ @return An pointer to IHANDLE if the next Position is not the end of the list.\r
+ Otherwise,NULL is returned.\r
+\r
+**/\r
+IHANDLE *\r
+UnitTestGetNextLocateByProtocol (\r
+ IN OUT LOCATE_POSITION *Position,\r
+ OUT VOID **Interface\r
+ )\r
+{\r
+ IHANDLE *Handle;\r
+ LIST_ENTRY *Link;\r
+ PROTOCOL_INTERFACE *Prot;\r
+\r
+ Handle = NULL;\r
+ *Interface = NULL;\r
+ for ( ; ;) {\r
+ //\r
+ // Next entry\r
+ //\r
+ Link = Position->Position->ForwardLink;\r
+ Position->Position = Link;\r
+\r
+ //\r
+ // If not at the end, return the handle\r
+ //\r
+ if (Link == &Position->ProtEntry->Protocols) {\r
+ Handle = NULL;\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Get the handle\r
+ //\r
+ Prot = CR (Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE);\r
+ Handle = Prot->Handle;\r
+ *Interface = Prot->Interface;\r
+\r
+ //\r
+ // If this handle has not been returned this request, then\r
+ // return it now\r
+ //\r
+ if (Handle->LocateRequest != mEfiLocateHandleRequest) {\r
+ Handle->LocateRequest = mEfiLocateHandleRequest;\r
+ break;\r
+ }\r
+ }\r
+\r
+ return Handle;\r
+}\r
+\r
+/**\r
+ Attempts to disconnect all drivers that are using the protocol interface being queried.\r
+ If failed, reconnect all drivers disconnected.\r
+ Note: This function doesn't do parameters checking, it's caller's responsibility\r
+ to pass in valid parameters.\r
+\r
+ @param UserHandle The handle on which the protocol is installed\r
+ @param Prot The protocol to disconnect drivers from\r
+\r
+ @retval EFI_SUCCESS Drivers using the protocol interface are all\r
+ disconnected\r
+ @retval EFI_ACCESS_DENIED Failed to disconnect one or all of the drivers\r
+\r
+**/\r
+EFI_STATUS\r
+UnitTestDisconnectControllersUsingProtocolInterface (\r
+ IN EFI_HANDLE UserHandle,\r
+ IN PROTOCOL_INTERFACE *Prot\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ BOOLEAN ItemFound;\r
+ LIST_ENTRY *Link;\r
+ OPEN_PROTOCOL_DATA *OpenData;\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ //\r
+ // Attempt to disconnect all drivers from this protocol interface\r
+ //\r
+ do {\r
+ ItemFound = FALSE;\r
+ for (Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList; Link = Link->ForwardLink) {\r
+ OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
+ if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {\r
+ Status = UnitTestDisconnectController (UserHandle, OpenData->AgentHandle, NULL);\r
+ if (!EFI_ERROR (Status)) {\r
+ ItemFound = TRUE;\r
+ }\r
+\r
+ break;\r
+ }\r
+ }\r
+ } while (ItemFound);\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Attempt to remove BY_HANDLE_PROTOCOL and GET_PROTOCOL and TEST_PROTOCOL Open List items\r
+ //\r
+ for (Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList;) {\r
+ OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
+ if ((OpenData->Attributes &\r
+ (EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL | EFI_OPEN_PROTOCOL_GET_PROTOCOL | EFI_OPEN_PROTOCOL_TEST_PROTOCOL)) != 0)\r
+ {\r
+ Link = RemoveEntryList (&OpenData->Link);\r
+ Prot->OpenListCount--;\r
+ FreePool (OpenData);\r
+ } else {\r
+ Link = Link->ForwardLink;\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // If there are errors or still has open items in the list, then reconnect all the drivers and return an error\r
+ //\r
+ if (EFI_ERROR (Status) || (Prot->OpenListCount > 0)) {\r
+ UnitTestConnectController (UserHandle, NULL, NULL, TRUE);\r
+ Status = EFI_ACCESS_DENIED;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Removes Protocol from the protocol list (but not the handle list).\r
+\r
+ @param Handle The handle to remove protocol on.\r
+ @param Protocol GUID of the protocol to be moved\r
+ @param Interface The interface of the protocol\r
+\r
+ @return Protocol Entry\r
+\r
+**/\r
+PROTOCOL_INTERFACE *\r
+UnitTestRemoveInterfaceFromProtocol (\r
+ IN IHANDLE *Handle,\r
+ IN EFI_GUID *Protocol,\r
+ IN VOID *Interface\r
+ )\r
+{\r
+ PROTOCOL_INTERFACE *Prot;\r
+ PROTOCOL_NOTIFY *ProtNotify;\r
+ PROTOCOL_ENTRY *ProtEntry;\r
+ LIST_ENTRY *Link;\r
+\r
+ Prot = UnitTestFindProtocolInterface (Handle, Protocol, Interface);\r
+ if (Prot != NULL) {\r
+ ProtEntry = Prot->Protocol;\r
+\r
+ //\r
+ // If there's a protocol notify location pointing to this entry, back it up one\r
+ //\r
+ for (Link = ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link = Link->ForwardLink) {\r
+ ProtNotify = CR (Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);\r
+\r
+ if (ProtNotify->Position == &Prot->ByProtocol) {\r
+ ProtNotify->Position = Prot->ByProtocol.BackLink;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Remove the protocol interface entry\r
+ //\r
+ RemoveEntryList (&Prot->ByProtocol);\r
+ }\r
+\r
+ return Prot;\r
+}\r
+\r
+//\r
+// Boot Services Function Implementation\r
+//\r
+\r
+/**\r
+ Locate a certain GUID protocol interface in a Handle's protocols.\r
+\r
+ @param UserHandle The handle to obtain the protocol interface on\r
+ @param Protocol The GUID of the protocol\r
+\r
+ @return The requested protocol interface for the handle\r
+\r
+**/\r
+PROTOCOL_INTERFACE *\r
+UnitTestGetProtocolInterface (\r
+ IN EFI_HANDLE UserHandle,\r
+ IN EFI_GUID *Protocol\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ PROTOCOL_ENTRY *ProtEntry;\r
+ PROTOCOL_INTERFACE *Prot;\r
+ IHANDLE *Handle;\r
+ LIST_ENTRY *Link;\r
+\r
+ Status = UnitTestValidateHandle (UserHandle);\r
+ if (EFI_ERROR (Status)) {\r
+ return NULL;\r
+ }\r
+\r
+ Handle = (IHANDLE *)UserHandle;\r
+\r
+ //\r
+ // Look at each protocol interface for a match\r
+ //\r
+ for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {\r
+ Prot = CR (Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);\r
+ ProtEntry = Prot->Protocol;\r
+ if (CompareGuid (&ProtEntry->ProtocolID, Protocol)) {\r
+ return Prot;\r
+ }\r
+ }\r
+\r
+ return NULL;\r
+}\r
+\r
+/**\r
+ Installs a protocol interface into the boot services environment.\r
+\r
+ @param UserHandle The handle to install the protocol handler on,\r
+ or NULL if a new handle is to be allocated\r
+ @param Protocol The protocol to add to the handle\r
+ @param InterfaceType Indicates whether Interface is supplied in\r
+ native form.\r
+ @param Interface The interface for the protocol being added\r
+ @param Notify indicates whether notify the notification list\r
+ for this protocol\r
+\r
+ @retval EFI_INVALID_PARAMETER Invalid parameter\r
+ @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate\r
+ @retval EFI_SUCCESS Protocol interface successfully installed\r
+\r
+**/\r
+EFI_STATUS\r
+UnitTestInstallProtocolInterfaceNotify (\r
+ IN OUT EFI_HANDLE *UserHandle,\r
+ IN EFI_GUID *Protocol,\r
+ IN EFI_INTERFACE_TYPE InterfaceType,\r
+ IN VOID *Interface,\r
+ IN BOOLEAN Notify\r
+ )\r
+{\r
+ PROTOCOL_INTERFACE *Prot;\r
+ PROTOCOL_ENTRY *ProtEntry;\r
+ IHANDLE *Handle;\r
+ EFI_STATUS Status;\r
+ VOID *ExistingInterface;\r
+\r
+ //\r
+ // returns EFI_INVALID_PARAMETER if InterfaceType is invalid.\r
+ // Also added check for invalid UserHandle and Protocol pointers.\r
+ //\r
+ if ((UserHandle == NULL) || (Protocol == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (InterfaceType != EFI_NATIVE_INTERFACE) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Print debug message\r
+ //\r
+ UT_LOG_INFO ("InstallProtocolInterface: %g %p\n", Protocol, Interface);\r
+\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ Prot = NULL;\r
+ Handle = NULL;\r
+\r
+ if (*UserHandle != NULL) {\r
+ Status = UnitTestHandleProtocol (*UserHandle, Protocol, (VOID **)&ExistingInterface);\r
+ if (!EFI_ERROR (Status)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Lookup the Protocol Entry for the requested protocol\r
+ //\r
+ ProtEntry = UnitTestFindProtocolEntry (Protocol, TRUE);\r
+ if (ProtEntry == NULL) {\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Allocate a new protocol interface structure\r
+ //\r
+ Prot = AllocateZeroPool (sizeof (PROTOCOL_INTERFACE));\r
+ if (Prot == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // If caller didn't supply a handle, allocate a new one\r
+ //\r
+ Handle = (IHANDLE *)*UserHandle;\r
+ if (Handle == NULL) {\r
+ Handle = AllocateZeroPool (sizeof (IHANDLE));\r
+ if (Handle == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Initialize new handler structure\r
+ //\r
+ Handle->Signature = EFI_HANDLE_SIGNATURE;\r
+ InitializeListHead (&Handle->Protocols);\r
+\r
+ //\r
+ // Initialize the Key to show that the handle has been created/modified\r
+ //\r
+ gHandleDatabaseKey++;\r
+ Handle->Key = gHandleDatabaseKey;\r
+\r
+ //\r
+ // Add this handle to the list global list of all handles\r
+ // in the system\r
+ //\r
+ InsertTailList (&gHandleList, &Handle->AllHandles);\r
+ } else {\r
+ Status = UnitTestValidateHandle (Handle);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "InstallProtocolInterface: input handle at 0x%x is invalid\n", Handle));\r
+ goto Done;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Each interface that is added must be unique\r
+ //\r
+ ASSERT (UnitTestFindProtocolInterface (Handle, Protocol, Interface) == NULL);\r
+\r
+ //\r
+ // Initialize the protocol interface structure\r
+ //\r
+ Prot->Signature = PROTOCOL_INTERFACE_SIGNATURE;\r
+ Prot->Handle = Handle;\r
+ Prot->Protocol = ProtEntry;\r
+ Prot->Interface = Interface;\r
+\r
+ //\r
+ // Initialize OpenProtocol Data base\r
+ //\r
+ InitializeListHead (&Prot->OpenList);\r
+ Prot->OpenListCount = 0;\r
+\r
+ //\r
+ // Add this protocol interface to the head of the supported\r
+ // protocol list for this handle\r
+ //\r
+ InsertHeadList (&Handle->Protocols, &Prot->Link);\r
+\r
+ //\r
+ // Add this protocol interface to the tail of the\r
+ // protocol entry\r
+ //\r
+ InsertTailList (&ProtEntry->Protocols, &Prot->ByProtocol);\r
+\r
+ //\r
+ // Notify the notification list for this protocol\r
+ //\r
+ if (Notify) {\r
+ UnitTestNotifyProtocolEntry (ProtEntry);\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+Done:\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Return the new handle back to the caller\r
+ //\r
+ *UserHandle = Handle;\r
+ } else {\r
+ //\r
+ // There was an error, clean up\r
+ //\r
+ if (Prot != NULL) {\r
+ UnitTestFreePool (Prot);\r
+ }\r
+\r
+ DEBUG ((DEBUG_ERROR, "InstallProtocolInterface: %g %p failed with %r\n", Protocol, Interface, Status));\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Wrapper function to UnitTestInstallProtocolInterfaceNotify. This is the public API which\r
+ Calls the private one which contains a BOOLEAN parameter for notifications\r
+\r
+ @param UserHandle The handle to install the protocol handler on,\r
+ or NULL if a new handle is to be allocated\r
+ @param Protocol The protocol to add to the handle\r
+ @param InterfaceType Indicates whether Interface is supplied in\r
+ native form.\r
+ @param Interface The interface for the protocol being added\r
+\r
+ @return Status code\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UnitTestInstallProtocolInterface (\r
+ IN OUT EFI_HANDLE *UserHandle,\r
+ IN EFI_GUID *Protocol,\r
+ IN EFI_INTERFACE_TYPE InterfaceType,\r
+ IN VOID *Interface\r
+ )\r
+{\r
+ return UnitTestInstallProtocolInterfaceNotify (\r
+ UserHandle,\r
+ Protocol,\r
+ InterfaceType,\r
+ Interface,\r
+ TRUE\r
+ );\r
+}\r
+\r
+/**\r
+ Reinstall a protocol interface on a device handle. The OldInterface for Protocol is replaced by the NewInterface.\r
+\r
+ @param UserHandle Handle on which the interface is to be\r
+ reinstalled\r
+ @param Protocol The numeric ID of the interface\r
+ @param OldInterface A pointer to the old interface\r
+ @param NewInterface A pointer to the new interface\r
+\r
+ @retval EFI_SUCCESS The protocol interface was installed\r
+ @retval EFI_NOT_FOUND The OldInterface on the handle was not found\r
+ @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UnitTestReinstallProtocolInterface (\r
+ IN EFI_HANDLE UserHandle,\r
+ IN EFI_GUID *Protocol,\r
+ IN VOID *OldInterface,\r
+ IN VOID *NewInterface\r
+ )\r
+{\r
+ return EFI_NOT_AVAILABLE_YET;\r
+}\r
+\r
+/**\r
+ Uninstalls all instances of a protocol:interfacer from a handle.\r
+ If the last protocol interface is remove from the handle, the\r
+ handle is freed.\r
+\r
+ @param UserHandle The handle to remove the protocol handler from\r
+ @param Protocol The protocol, of protocol:interface, to remove\r
+ @param Interface The interface, of protocol:interface, to remove\r
+\r
+ @retval EFI_INVALID_PARAMETER Protocol is NULL.\r
+ @retval EFI_SUCCESS Protocol interface successfully uninstalled.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UnitTestUninstallProtocolInterface (\r
+ IN EFI_HANDLE UserHandle,\r
+ IN EFI_GUID *Protocol,\r
+ IN VOID *Interface\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ IHANDLE *Handle;\r
+ PROTOCOL_INTERFACE *Prot;\r
+\r
+ //\r
+ // Check that Protocol is valid\r
+ //\r
+ if (Protocol == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Check that UserHandle is a valid handle\r
+ //\r
+ Status = UnitTestValidateHandle (UserHandle);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Check that Protocol exists on UserHandle, and Interface matches the interface in the database\r
+ //\r
+ Prot = UnitTestFindProtocolInterface (UserHandle, Protocol, Interface);\r
+ if (Prot == NULL) {\r
+ Status = EFI_NOT_FOUND;\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Attempt to disconnect all drivers that are using the protocol interface that is about to be removed\r
+ //\r
+ Status = UnitTestDisconnectControllersUsingProtocolInterface (\r
+ UserHandle,\r
+ Prot\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // One or more drivers refused to release, so return the error\r
+ //\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Remove the protocol interface from the protocol\r
+ //\r
+ Status = EFI_NOT_FOUND;\r
+ Handle = (IHANDLE *)UserHandle;\r
+ Prot = UnitTestRemoveInterfaceFromProtocol (Handle, Protocol, Interface);\r
+\r
+ if (Prot != NULL) {\r
+ //\r
+ // Update the Key to show that the handle has been created/modified\r
+ //\r
+ gHandleDatabaseKey++;\r
+ Handle->Key = gHandleDatabaseKey;\r
+\r
+ //\r
+ // Remove the protocol interface from the handle\r
+ //\r
+ RemoveEntryList (&Prot->Link);\r
+\r
+ //\r
+ // Free the memory\r
+ //\r
+ Prot->Signature = 0;\r
+ FreePool (Prot);\r
+ Status = EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // If there are no more handlers for the handle, free the handle\r
+ //\r
+ if (IsListEmpty (&Handle->Protocols)) {\r
+ Handle->Signature = 0;\r
+ RemoveEntryList (&Handle->AllHandles);\r
+ FreePool (Handle);\r
+ }\r
+\r
+Done:\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Queries a handle to determine if it supports a specified protocol.\r
+\r
+ @param UserHandle The handle being queried.\r
+ @param Protocol The published unique identifier of the protocol.\r
+ @param Interface Supplies the address where a pointer to the\r
+ corresponding Protocol Interface is returned.\r
+\r
+ @return The requested protocol interface for the handle\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UnitTestHandleProtocol (\r
+ IN EFI_HANDLE UserHandle,\r
+ IN EFI_GUID *Protocol,\r
+ OUT VOID **Interface\r
+ )\r
+{\r
+ return UnitTestOpenProtocol (\r
+ UserHandle,\r
+ Protocol,\r
+ Interface,\r
+ gImageHandle,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL\r
+ );\r
+}\r
+\r
+/**\r
+ Add a new protocol notification record for the request protocol.\r
+\r
+ @param Protocol The requested protocol to add the notify\r
+ registration\r
+ @param Event The event to signal\r
+ @param Registration Returns the registration record\r
+\r
+ @retval EFI_INVALID_PARAMETER Invalid parameter\r
+ @retval EFI_SUCCESS Successfully returned the registration record\r
+ that has been added\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UnitTestRegisterProtocolNotify (\r
+ IN EFI_GUID *Protocol,\r
+ IN EFI_EVENT Event,\r
+ OUT VOID **Registration\r
+ )\r
+{\r
+ return EFI_NOT_AVAILABLE_YET;\r
+}\r
+\r
+/**\r
+ Locates the requested handle(s) and returns them in Buffer.\r
+\r
+ @param SearchType The type of search to perform to locate the\r
+ handles\r
+ @param Protocol The protocol to search for\r
+ @param SearchKey Dependant on SearchType\r
+ @param BufferSize On input the size of Buffer. On output the\r
+ size of data returned.\r
+ @param Buffer The buffer to return the results in\r
+\r
+ @retval EFI_BUFFER_TOO_SMALL Buffer too small, required buffer size is\r
+ returned in BufferSize.\r
+ @retval EFI_INVALID_PARAMETER Invalid parameter\r
+ @retval EFI_SUCCESS Successfully found the requested handle(s) and\r
+ returns them in Buffer.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UnitTestLocateHandle (\r
+ IN EFI_LOCATE_SEARCH_TYPE SearchType,\r
+ IN EFI_GUID *Protocol OPTIONAL,\r
+ IN VOID *SearchKey OPTIONAL,\r
+ IN OUT UINTN *BufferSize,\r
+ OUT EFI_HANDLE *Buffer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LOCATE_POSITION Position;\r
+ PROTOCOL_NOTIFY *ProtNotify;\r
+ UNIT_TEST_GET_NEXT GetNext;\r
+ UINTN ResultSize;\r
+ IHANDLE *Handle;\r
+ IHANDLE **ResultBuffer;\r
+ VOID *Interface;\r
+\r
+ if (BufferSize == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if ((*BufferSize > 0) && (Buffer == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ GetNext = NULL;\r
+\r
+ //\r
+ // Set initial position\r
+ //\r
+ Position.Protocol = Protocol;\r
+ Position.SearchKey = SearchKey;\r
+ Position.Position = &gHandleList;\r
+\r
+ ResultSize = 0;\r
+ ResultBuffer = (IHANDLE **)Buffer;\r
+ Status = EFI_SUCCESS;\r
+\r
+ //\r
+ // Get the search function based on type\r
+ //\r
+ switch (SearchType) {\r
+ case AllHandles:\r
+ GetNext = UnitTestGetNextLocateAllHandles;\r
+ break;\r
+\r
+ case ByRegisterNotify:\r
+ //\r
+ // Must have SearchKey for locate ByRegisterNotify\r
+ //\r
+ if (SearchKey == NULL) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ break;\r
+ }\r
+\r
+ GetNext = UnitTestGetNextLocateByRegisterNotify;\r
+ break;\r
+\r
+ case ByProtocol:\r
+ GetNext = UnitTestGetNextLocateByProtocol;\r
+ if (Protocol == NULL) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Look up the protocol entry and set the head pointer\r
+ //\r
+ Position.ProtEntry = UnitTestFindProtocolEntry (Protocol, FALSE);\r
+ if (Position.ProtEntry == NULL) {\r
+ Status = EFI_NOT_FOUND;\r
+ break;\r
+ }\r
+\r
+ Position.Position = &Position.ProtEntry->Protocols;\r
+ break;\r
+\r
+ default:\r
+ Status = EFI_INVALID_PARAMETER;\r
+ break;\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ ASSERT (GetNext != NULL);\r
+ //\r
+ // Enumerate out the matching handles\r
+ //\r
+ mEfiLocateHandleRequest += 1;\r
+ for ( ; ;) {\r
+ //\r
+ // Get the next handle. If no more handles, stop\r
+ //\r
+ Handle = GetNext (&Position, &Interface);\r
+ if (NULL == Handle) {\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Increase the resulting buffer size, and if this handle\r
+ // fits return it\r
+ //\r
+ ResultSize += sizeof (Handle);\r
+ if (ResultSize <= *BufferSize) {\r
+ *ResultBuffer = Handle;\r
+ ResultBuffer += 1;\r
+ }\r
+ }\r
+\r
+ //\r
+ // If the result is a zero length buffer, then there were no\r
+ // matching handles\r
+ //\r
+ if (ResultSize == 0) {\r
+ Status = EFI_NOT_FOUND;\r
+ } else {\r
+ //\r
+ // Return the resulting buffer size. If it's larger than what\r
+ // was passed, then set the error code\r
+ //\r
+ if (ResultSize > *BufferSize) {\r
+ Status = EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ *BufferSize = ResultSize;\r
+\r
+ if ((SearchType == ByRegisterNotify) && !EFI_ERROR (Status)) {\r
+ //\r
+ // If this is a search by register notify and a handle was\r
+ // returned, update the register notification position\r
+ //\r
+ ASSERT (SearchKey != NULL);\r
+ ProtNotify = SearchKey;\r
+ ProtNotify->Position = ProtNotify->Position->ForwardLink;\r
+ }\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Locates the handle to a device on the device path that best matches the specified protocol.\r
+\r
+ @param Protocol The protocol to search for.\r
+ @param DevicePath On input, a pointer to a pointer to the device\r
+ path. On output, the device path pointer is\r
+ modified to point to the remaining part of the\r
+ devicepath.\r
+ @param Device A pointer to the returned device handle.\r
+\r
+ @retval EFI_SUCCESS The resulting handle was returned.\r
+ @retval EFI_NOT_FOUND No handles matched the search.\r
+ @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UnitTestLocateDevicePath (\r
+ IN EFI_GUID *Protocol,\r
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath,\r
+ OUT EFI_HANDLE *Device\r
+ )\r
+{\r
+ return EFI_NOT_AVAILABLE_YET;\r
+}\r
+\r
+/**\r
+ Boot Service called to add, modify, or remove a system configuration table from\r
+ the EFI System Table.\r
+\r
+ @param Guid Pointer to the GUID for the entry to add, update, or\r
+ remove\r
+ @param Table Pointer to the configuration table for the entry to add,\r
+ update, or remove, may be NULL.\r
+\r
+ @return EFI_SUCCESS Guid, Table pair added, updated, or removed.\r
+ @return EFI_INVALID_PARAMETER Input GUID not valid.\r
+ @return EFI_NOT_FOUND Attempted to delete non-existant entry\r
+ @return EFI_OUT_OF_RESOURCES Not enough memory available\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UnitTestInstallConfigurationTable (\r
+ IN EFI_GUID *Guid,\r
+ IN VOID *Table\r
+ )\r
+{\r
+ return EFI_NOT_AVAILABLE_YET;\r
+}\r
+\r
+/**\r
+ Locates the installed protocol handler for the handle, and\r
+ invokes it to obtain the protocol interface. Usage information\r
+ is registered in the protocol data base.\r
+\r
+ @param UserHandle The handle to obtain the protocol interface on\r
+ @param Protocol The ID of the protocol\r
+ @param Interface The location to return the protocol interface\r
+ @param ImageHandle The handle of the Image that is opening the\r
+ protocol interface specified by Protocol and\r
+ Interface.\r
+ @param ControllerHandle The controller handle that is requiring this\r
+ interface.\r
+ @param Attributes The open mode of the protocol interface\r
+ specified by Handle and Protocol.\r
+\r
+ @retval EFI_INVALID_PARAMETER Protocol is NULL.\r
+ @retval EFI_SUCCESS Get the protocol interface.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UnitTestOpenProtocol (\r
+ IN EFI_HANDLE UserHandle,\r
+ IN EFI_GUID *Protocol,\r
+ OUT VOID **Interface OPTIONAL,\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN UINT32 Attributes\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ PROTOCOL_INTERFACE *Prot;\r
+ LIST_ENTRY *Link;\r
+ OPEN_PROTOCOL_DATA *OpenData;\r
+ BOOLEAN ByDriver;\r
+ BOOLEAN Exclusive;\r
+ BOOLEAN Disconnect;\r
+ BOOLEAN ExactMatch;\r
+\r
+ //\r
+ // Check for invalid Protocol\r
+ //\r
+ if (Protocol == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Check for invalid Interface\r
+ //\r
+ if ((Attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL) && (Interface == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Check for invalid UserHandle\r
+ //\r
+ Status = UnitTestValidateHandle (UserHandle);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Check for invalid Attributes\r
+ //\r
+ switch (Attributes) {\r
+ case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER:\r
+ Status = UnitTestValidateHandle (ImageHandle);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = UnitTestValidateHandle (ControllerHandle);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if (UserHandle == ControllerHandle) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ break;\r
+ case EFI_OPEN_PROTOCOL_BY_DRIVER:\r
+ case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE:\r
+ Status = UnitTestValidateHandle (ImageHandle);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = UnitTestValidateHandle (ControllerHandle);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ break;\r
+ case EFI_OPEN_PROTOCOL_EXCLUSIVE:\r
+ Status = UnitTestValidateHandle (ImageHandle);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ break;\r
+ case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL:\r
+ case EFI_OPEN_PROTOCOL_GET_PROTOCOL:\r
+ case EFI_OPEN_PROTOCOL_TEST_PROTOCOL:\r
+ break;\r
+ default:\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Look at each protocol interface for a match\r
+ //\r
+ Prot = UnitTestGetProtocolInterface (UserHandle, Protocol);\r
+ if (Prot == NULL) {\r
+ Status = EFI_UNSUPPORTED;\r
+ goto Done;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ ByDriver = FALSE;\r
+ Exclusive = FALSE;\r
+ for ( Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList; Link = Link->ForwardLink) {\r
+ OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
+ ExactMatch = (BOOLEAN)((OpenData->AgentHandle == ImageHandle) &&\r
+ (OpenData->Attributes == Attributes) &&\r
+ (OpenData->ControllerHandle == ControllerHandle));\r
+ if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {\r
+ ByDriver = TRUE;\r
+ if (ExactMatch) {\r
+ Status = EFI_ALREADY_STARTED;\r
+ goto Done;\r
+ }\r
+ }\r
+\r
+ if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_EXCLUSIVE) != 0) {\r
+ Exclusive = TRUE;\r
+ } else if (ExactMatch) {\r
+ OpenData->OpenCount++;\r
+ Status = EFI_SUCCESS;\r
+ goto Done;\r
+ }\r
+ }\r
+\r
+ //\r
+ // ByDriver TRUE -> A driver is managing (UserHandle, Protocol)\r
+ // ByDriver FALSE -> There are no drivers managing (UserHandle, Protocol)\r
+ // Exclusive TRUE -> Something has exclusive access to (UserHandle, Protocol)\r
+ // Exclusive FALSE -> Nothing has exclusive access to (UserHandle, Protocol)\r
+ //\r
+\r
+ switch (Attributes) {\r
+ case EFI_OPEN_PROTOCOL_BY_DRIVER:\r
+ if (Exclusive || ByDriver) {\r
+ Status = EFI_ACCESS_DENIED;\r
+ goto Done;\r
+ }\r
+\r
+ break;\r
+ case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE:\r
+ case EFI_OPEN_PROTOCOL_EXCLUSIVE:\r
+ if (Exclusive) {\r
+ Status = EFI_ACCESS_DENIED;\r
+ goto Done;\r
+ }\r
+\r
+ if (ByDriver) {\r
+ do {\r
+ Disconnect = FALSE;\r
+ for (Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList; Link = Link->ForwardLink) {\r
+ OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
+ if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {\r
+ Disconnect = TRUE;\r
+ Status = UnitTestDisconnectController (UserHandle, OpenData->AgentHandle, NULL);\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_ACCESS_DENIED;\r
+ goto Done;\r
+ } else {\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ } while (Disconnect);\r
+ }\r
+\r
+ break;\r
+ case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER:\r
+ case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL:\r
+ case EFI_OPEN_PROTOCOL_GET_PROTOCOL:\r
+ case EFI_OPEN_PROTOCOL_TEST_PROTOCOL:\r
+ break;\r
+ }\r
+\r
+ if (ImageHandle == NULL) {\r
+ Status = EFI_SUCCESS;\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Create new entry\r
+ //\r
+ OpenData = AllocatePool (sizeof (OPEN_PROTOCOL_DATA));\r
+ if (OpenData == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ } else {\r
+ OpenData->Signature = OPEN_PROTOCOL_DATA_SIGNATURE;\r
+ OpenData->AgentHandle = ImageHandle;\r
+ OpenData->ControllerHandle = ControllerHandle;\r
+ OpenData->Attributes = Attributes;\r
+ OpenData->OpenCount = 1;\r
+ InsertTailList (&Prot->OpenList, &OpenData->Link);\r
+ Prot->OpenListCount++;\r
+ Status = EFI_SUCCESS;\r
+ }\r
+\r
+Done:\r
+\r
+ if (Attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL) {\r
+ //\r
+ // Keep Interface unmodified in case of any Error\r
+ // except EFI_ALREADY_STARTED and EFI_UNSUPPORTED.\r
+ //\r
+ if (!EFI_ERROR (Status) || (Status == EFI_ALREADY_STARTED)) {\r
+ //\r
+ // According to above logic, if 'Prot' is NULL, then the 'Status' must be\r
+ // EFI_UNSUPPORTED. Here the 'Status' is not EFI_UNSUPPORTED, so 'Prot'\r
+ // must be not NULL.\r
+ //\r
+ // The ASSERT here is for addressing a false positive NULL pointer\r
+ // dereference issue raised from static analysis.\r
+ //\r
+ ASSERT (Prot != NULL);\r
+ //\r
+ // EFI_ALREADY_STARTED is not an error for bus driver.\r
+ // Return the corresponding protocol interface.\r
+ //\r
+ *Interface = Prot->Interface;\r
+ } else if (Status == EFI_UNSUPPORTED) {\r
+ //\r
+ // Return NULL Interface if Unsupported Protocol.\r
+ //\r
+ *Interface = NULL;\r
+ }\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Closes a protocol on a handle that was opened using OpenProtocol().\r
+\r
+ @param UserHandle The handle for the protocol interface that was\r
+ previously opened with OpenProtocol(), and is\r
+ now being closed.\r
+ @param Protocol The published unique identifier of the protocol.\r
+ It is the caller's responsibility to pass in a\r
+ valid GUID.\r
+ @param AgentHandle The handle of the agent that is closing the\r
+ protocol interface.\r
+ @param ControllerHandle If the agent that opened a protocol is a driver\r
+ that follows the EFI Driver Model, then this\r
+ parameter is the controller handle that required\r
+ the protocol interface. If the agent does not\r
+ follow the EFI Driver Model, then this parameter\r
+ is optional and may be NULL.\r
+\r
+ @retval EFI_SUCCESS The protocol instance was closed.\r
+ @retval EFI_INVALID_PARAMETER Handle, AgentHandle or ControllerHandle is not a\r
+ valid EFI_HANDLE.\r
+ @retval EFI_NOT_FOUND Can not find the specified protocol or\r
+ AgentHandle.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UnitTestCloseProtocol (\r
+ IN EFI_HANDLE UserHandle,\r
+ IN EFI_GUID *Protocol,\r
+ IN EFI_HANDLE AgentHandle,\r
+ IN EFI_HANDLE ControllerHandle\r
+ )\r
+{\r
+ return EFI_NOT_AVAILABLE_YET;\r
+}\r
+\r
+/**\r
+ Return information about Opened protocols in the system\r
+\r
+ @param UserHandle The handle to close the protocol interface on\r
+ @param Protocol The ID of the protocol\r
+ @param EntryBuffer A pointer to a buffer of open protocol\r
+ information in the form of\r
+ EFI_OPEN_PROTOCOL_INFORMATION_ENTRY structures.\r
+ @param EntryCount Number of EntryBuffer entries\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UnitTestOpenProtocolInformation (\r
+ IN EFI_HANDLE UserHandle,\r
+ IN EFI_GUID *Protocol,\r
+ OUT EFI_OPEN_PROTOCOL_INFORMATION_ENTRY **EntryBuffer,\r
+ OUT UINTN *EntryCount\r
+ )\r
+{\r
+ return EFI_NOT_AVAILABLE_YET;\r
+}\r
+\r
+/**\r
+ Retrieves the list of protocol interface GUIDs that are installed on a handle in a buffer allocated\r
+ from pool.\r
+\r
+ @param UserHandle The handle from which to retrieve the list of\r
+ protocol interface GUIDs.\r
+ @param ProtocolBuffer A pointer to the list of protocol interface GUID\r
+ pointers that are installed on Handle.\r
+ @param ProtocolBufferCount A pointer to the number of GUID pointers present\r
+ in ProtocolBuffer.\r
+\r
+ @retval EFI_SUCCESS The list of protocol interface GUIDs installed\r
+ on Handle was returned in ProtocolBuffer. The\r
+ number of protocol interface GUIDs was returned\r
+ in ProtocolBufferCount.\r
+ @retval EFI_INVALID_PARAMETER Handle is NULL.\r
+ @retval EFI_INVALID_PARAMETER Handle is not a valid EFI_HANDLE.\r
+ @retval EFI_INVALID_PARAMETER ProtocolBuffer is NULL.\r
+ @retval EFI_INVALID_PARAMETER ProtocolBufferCount is NULL.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the\r
+ results.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UnitTestProtocolsPerHandle (\r
+ IN EFI_HANDLE UserHandle,\r
+ OUT EFI_GUID ***ProtocolBuffer,\r
+ OUT UINTN *ProtocolBufferCount\r
+ )\r
+{\r
+ return EFI_NOT_AVAILABLE_YET;\r
+}\r
+\r
+/**\r
+ Function returns an array of handles that support the requested protocol\r
+ in a buffer allocated from pool. This is a version of UnitTestLocateHandle()\r
+ that allocates a buffer for the caller.\r
+\r
+ @param SearchType Specifies which handle(s) are to be returned.\r
+ @param Protocol Provides the protocol to search by. This\r
+ parameter is only valid for SearchType\r
+ ByProtocol.\r
+ @param SearchKey Supplies the search key depending on the\r
+ SearchType.\r
+ @param NumberHandles The number of handles returned in Buffer.\r
+ @param Buffer A pointer to the buffer to return the requested\r
+ array of handles that support Protocol.\r
+\r
+ @retval EFI_SUCCESS The result array of handles was returned.\r
+ @retval EFI_NOT_FOUND No handles match the search.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the\r
+ matching results.\r
+ @retval EFI_INVALID_PARAMETER One or more parameters are not valid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UnitTestLocateHandleBuffer (\r
+ IN EFI_LOCATE_SEARCH_TYPE SearchType,\r
+ IN EFI_GUID *Protocol OPTIONAL,\r
+ IN VOID *SearchKey OPTIONAL,\r
+ IN OUT UINTN *NumberHandles,\r
+ OUT EFI_HANDLE **Buffer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN BufferSize;\r
+\r
+ if (NumberHandles == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Buffer == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ BufferSize = 0;\r
+ *NumberHandles = 0;\r
+ *Buffer = NULL;\r
+ Status = UnitTestLocateHandle (\r
+ SearchType,\r
+ Protocol,\r
+ SearchKey,\r
+ &BufferSize,\r
+ *Buffer\r
+ );\r
+ //\r
+ // LocateHandleBuffer() returns incorrect status code if SearchType is\r
+ // invalid.\r
+ //\r
+ // Add code to correctly handle expected errors from UnitTestLocateHandle().\r
+ //\r
+ if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) {\r
+ if (Status != EFI_INVALID_PARAMETER) {\r
+ Status = EFI_NOT_FOUND;\r
+ }\r
+\r
+ return Status;\r
+ }\r
+\r
+ *Buffer = AllocatePool (BufferSize);\r
+ if (*Buffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Status = UnitTestLocateHandle (\r
+ SearchType,\r
+ Protocol,\r
+ SearchKey,\r
+ &BufferSize,\r
+ *Buffer\r
+ );\r
+\r
+ *NumberHandles = BufferSize / sizeof (EFI_HANDLE);\r
+ if (EFI_ERROR (Status)) {\r
+ *NumberHandles = 0;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Return the first Protocol Interface that matches the Protocol GUID. If\r
+ Registration is passed in, return a Protocol Instance that was just add\r
+ to the system. If Registration is NULL return the first Protocol Interface\r
+ you find.\r
+\r
+ @param Protocol The protocol to search for\r
+ @param Registration Optional Registration Key returned from\r
+ RegisterProtocolNotify()\r
+ @param Interface Return the Protocol interface (instance).\r
+\r
+ @retval EFI_SUCCESS If a valid Interface is returned\r
+ @retval EFI_INVALID_PARAMETER Invalid parameter\r
+ @retval EFI_NOT_FOUND Protocol interface not found\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UnitTestLocateProtocol (\r
+ IN EFI_GUID *Protocol,\r
+ IN VOID *Registration OPTIONAL,\r
+ OUT VOID **Interface\r
+ )\r
+{\r
+ return EFI_NOT_AVAILABLE_YET;\r
+}\r
+\r
+/**\r
+ Installs a list of protocol interface into the boot services environment.\r
+ This function calls InstallProtocolInterface() in a loop. If any error\r
+ occurs all the protocols added by this function are removed. This is\r
+ basically a lib function to save space.\r
+\r
+ @param Handle The handle to install the protocol handlers on,\r
+ or NULL if a new handle is to be allocated\r
+ @param ... EFI_GUID followed by protocol instance. A NULL\r
+ terminates the list. The pairs are the\r
+ arguments to InstallProtocolInterface(). All the\r
+ protocols are added to Handle.\r
+\r
+ @retval EFI_SUCCESS All the protocol interface was installed.\r
+ @retval EFI_OUT_OF_RESOURCES There was not enough memory in pool to install all the protocols.\r
+ @retval EFI_ALREADY_STARTED A Device Path Protocol instance was passed in that is already present in\r
+ the handle database.\r
+ @retval EFI_INVALID_PARAMETER Handle is NULL.\r
+ @retval EFI_INVALID_PARAMETER Protocol is already installed on the handle specified by Handle.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UnitTestInstallMultipleProtocolInterfaces (\r
+ IN OUT EFI_HANDLE *Handle,\r
+ ...\r
+ )\r
+{\r
+ return EFI_NOT_AVAILABLE_YET;\r
+}\r
+\r
+/**\r
+ Uninstalls a list of protocol interface in the boot services environment.\r
+ This function calls UninstallProtocolInterface() in a loop. This is\r
+ basically a lib function to save space.\r
+\r
+ @param Handle The handle to uninstall the protocol\r
+ @param ... EFI_GUID followed by protocol instance. A NULL\r
+ terminates the list. The pairs are the\r
+ arguments to UninstallProtocolInterface(). All\r
+ the protocols are added to Handle.\r
+\r
+ @return Status code\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UnitTestUninstallMultipleProtocolInterfaces (\r
+ IN EFI_HANDLE Handle,\r
+ ...\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ VA_LIST Args;\r
+ EFI_GUID *Protocol;\r
+ VOID *Interface;\r
+ UINTN Index;\r
+\r
+ VA_START (Args, Handle);\r
+ for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) {\r
+ //\r
+ // If protocol is NULL, then it's the end of the list\r
+ //\r
+ Protocol = VA_ARG (Args, EFI_GUID *);\r
+ if (Protocol == NULL) {\r
+ break;\r
+ }\r
+\r
+ Interface = VA_ARG (Args, VOID *);\r
+\r
+ //\r
+ // Uninstall it\r
+ //\r
+ Status = UnitTestUninstallProtocolInterface (Handle, Protocol, Interface);\r
+ }\r
+\r
+ VA_END (Args);\r
+\r
+ //\r
+ // If there was an error, add all the interfaces that were\r
+ // uninstalled without any errors\r
+ //\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Reset the va_arg back to the first argument.\r
+ //\r
+ VA_START (Args, Handle);\r
+ for ( ; Index > 1; Index--) {\r
+ Protocol = VA_ARG (Args, EFI_GUID *);\r
+ Interface = VA_ARG (Args, VOID *);\r
+ UnitTestInstallProtocolInterface (&Handle, Protocol, EFI_NATIVE_INTERFACE, Interface);\r
+ }\r
+\r
+ VA_END (Args);\r
+ Status = EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ return Status;\r
+}\r