--- /dev/null
+/** @file\r
+ Locate handle functions\r
+\r
+ Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.<BR>\r
+ Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.<BR>\r
+ This program and the accompanying materials are licensed and made available\r
+ under the terms and conditions of the BSD License which accompanies this\r
+ distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "StandaloneMmCore.h"\r
+\r
+//\r
+// ProtocolRequest - Last LocateHandle request ID\r
+//\r
+UINTN mEfiLocateHandleRequest = 0;\r
+\r
+//\r
+// Internal prototypes\r
+//\r
+\r
+typedef struct {\r
+ EFI_GUID *Protocol;\r
+ VOID *SearchKey;\r
+ LIST_ENTRY *Position;\r
+ PROTOCOL_ENTRY *ProtEntry;\r
+} LOCATE_POSITION;\r
+\r
+typedef\r
+IHANDLE *\r
+(* CORE_GET_NEXT) (\r
+ IN OUT LOCATE_POSITION *Position,\r
+ OUT VOID **Interface\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
+MmGetNextLocateAllHandles (\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
+ 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
+MmGetNextLocateByRegisterNotify (\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
+ 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
+MmGetNextLocateByProtocol (\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
+ return Handle;\r
+}\r
+\r
+/**\r
+ Return the first Protocol Interface that matches the Protocol GUID. If\r
+ Registration is pasased in return a Protocol Instance that was just add\r
+ to the system. If Retistration 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
+MmLocateProtocol (\r
+ IN EFI_GUID *Protocol,\r
+ IN VOID *Registration OPTIONAL,\r
+ OUT VOID **Interface\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LOCATE_POSITION Position;\r
+ PROTOCOL_NOTIFY *ProtNotify;\r
+ IHANDLE *Handle;\r
+\r
+ if ((Interface == NULL) || (Protocol == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ *Interface = NULL;\r
+ Status = EFI_SUCCESS;\r
+\r
+ //\r
+ // Set initial position\r
+ //\r
+ Position.Protocol = Protocol;\r
+ Position.SearchKey = Registration;\r
+ Position.Position = &gHandleList;\r
+\r
+ mEfiLocateHandleRequest += 1;\r
+\r
+ if (Registration == NULL) {\r
+ //\r
+ // Look up the protocol entry and set the head pointer\r
+ //\r
+ Position.ProtEntry = MmFindProtocolEntry (Protocol, FALSE);\r
+ if (Position.ProtEntry == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ Position.Position = &Position.ProtEntry->Protocols;\r
+\r
+ Handle = MmGetNextLocateByProtocol (&Position, Interface);\r
+ } else {\r
+ Handle = MmGetNextLocateByRegisterNotify (&Position, Interface);\r
+ }\r
+\r
+ if (Handle == NULL) {\r
+ Status = EFI_NOT_FOUND;\r
+ } else if (Registration != NULL) {\r
+ //\r
+ // If this is a search by register notify and a handle was\r
+ // returned, update the register notification position\r
+ //\r
+ ProtNotify = Registration;\r
+ ProtNotify->Position = ProtNotify->Position->ForwardLink;\r
+ }\r
+\r
+ return Status;\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
+MmLocateHandle (\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
+ CORE_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 = MmGetNextLocateAllHandles;\r
+ break;\r
+\r
+ case ByRegisterNotify:\r
+ GetNext = MmGetNextLocateByRegisterNotify;\r
+ //\r
+ // Must have SearchKey for locate ByRegisterNotify\r
+ //\r
+ if (SearchKey == NULL) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ }\r
+ break;\r
+\r
+ case ByProtocol:\r
+ GetNext = MmGetNextLocateByProtocol;\r
+ if (Protocol == NULL) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ break;\r
+ }\r
+ //\r
+ // Look up the protocol entry and set the head pointer\r
+ //\r
+ Position.ProtEntry = MmFindProtocolEntry (Protocol, FALSE);\r
+ if (Position.ProtEntry == NULL) {\r
+ Status = EFI_NOT_FOUND;\r
+ break;\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
+ //\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
+ ASSERT (SearchKey != NULL);\r
+ //\r
+ // If this is a search by register notify and a handle was\r
+ // returned, update the register notification position\r
+ //\r
+ ProtNotify = SearchKey;\r
+ ProtNotify->Position = ProtNotify->Position->ForwardLink;\r
+ }\r
+ }\r
+\r
+ return Status;\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 MmLocateHandle()\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
+MmLocateHandleBuffer (\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 = MmLocateHandle (\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 MmLocateHandle().\r
+ //\r
+ if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {\r
+ if (Status != EFI_INVALID_PARAMETER) {\r
+ Status = EFI_NOT_FOUND;\r
+ }\r
+ return Status;\r
+ }\r
+\r
+ *Buffer = AllocatePool (BufferSize);\r
+ if (*Buffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Status = MmLocateHandle (\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