]> git.proxmox.com Git - mirror_edk2.git/blobdiff - StandaloneMmPkg/Core/Locate.c
StandaloneMmPkg/Core: Implementation of Standalone MM Core Module.
[mirror_edk2.git] / StandaloneMmPkg / Core / Locate.c
diff --git a/StandaloneMmPkg/Core/Locate.c b/StandaloneMmPkg/Core/Locate.c
new file mode 100644 (file)
index 0000000..9129718
--- /dev/null
@@ -0,0 +1,496 @@
+/** @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