+++ /dev/null
-/** @file \r
-\r
- Locate handle functions \r
-\r
-Copyright (c) 2006 - 2008, Intel Corporation \r
-All rights reserved. This program and the accompanying materials \r
-are licensed and made available under the terms and conditions of the BSD License \r
-which accompanies this 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 <DxeMain.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
- @retval IHANDLE An IHANDLE is returned if the next Position is \r
- not the end of the list. A NULL_HANDLE is \r
- returned if it's the end of the list.\r
-\r
-**/\r
-STATIC\r
-IHANDLE *\r
-CoreGetNextLocateAllHandles (\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 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
- @retval IHANDLE An IHANDLE is returned if the next Position is \r
- not the end of the list. A NULL_HANDLE is \r
- returned if it's the end of the list.\r
-\r
-**/\r
-STATIC\r
-IHANDLE *\r
-CoreGetNextLocateByRegisterNotify (\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 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
- @retval IHANDLE An IHANDLE is returned if the next Position is \r
- not the end of the list. A NULL_HANDLE is \r
- returned if it's the end of the list.\r
-\r
-**/\r
-STATIC\r
-IHANDLE *\r
-CoreGetNextLocateByProtocol (\r
- IN OUT LOCATE_POSITION *Position,\r
- OUT VOID **Interface\r
- );\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
-CoreLocateHandle (\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
- Status = EFI_INVALID_PARAMETER;\r
- }\r
- \r
- if ((*BufferSize > 0) && (Buffer == NULL)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- \r
- GetNext = NULL;\r
- //\r
- // Set initial position\r
- //\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
- // Lock the protocol database\r
- //\r
- \r
- CoreAcquireProtocolLock ();\r
-\r
- //\r
- // Get the search function based on type\r
- //\r
- switch (SearchType) {\r
- case AllHandles: \r
- GetNext = CoreGetNextLocateAllHandles; \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
- GetNext = CoreGetNextLocateByRegisterNotify; \r
- break;\r
-\r
- case ByProtocol: \r
- GetNext = CoreGetNextLocateByProtocol;\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 = CoreFindProtocolEntry (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
- CoreReleaseProtocolLock ();\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
- //\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
- CoreReleaseProtocolLock ();\r
- return Status;\r
-}\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
- @retval IHANDLE An IHANDLE is returned if the next Position is \r
- not the end of the list. A NULL_HANDLE is \r
- returned if it's the end of the list.\r
-\r
-**/\r
-STATIC\r
-IHANDLE *\r
-CoreGetNextLocateAllHandles (\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_HANDLE;\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
-\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
- @retval IHANDLE An IHANDLE is returned if the next Position is \r
- not the end of the list. A NULL_HANDLE is \r
- returned if it's the end of the list.\r
-\r
-**/\r
-STATIC\r
-IHANDLE *\r
-CoreGetNextLocateByRegisterNotify (\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_HANDLE;\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 = (IHANDLE *) Prot->Handle;\r
- *Interface = Prot->Interface;\r
- } \r
- }\r
-\r
- return Handle;\r
-}\r
-\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
- @retval IHANDLE An IHANDLE is returned if the next Position is \r
- not the end of the list. A NULL_HANDLE is \r
- returned if it's the end of the list.\r
-\r
-**/\r
-STATIC\r
-IHANDLE *\r
-CoreGetNextLocateByProtocol (\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_HANDLE;\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_HANDLE;\r
- break;\r
- }\r
-\r
- //\r
- // Get the handle\r
- //\r
- Prot = CR(Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE);\r
- Handle = (IHANDLE *) 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
-\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
-CoreLocateDevicePath (\r
- IN EFI_GUID *Protocol,\r
- IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath,\r
- OUT EFI_HANDLE *Device\r
- )\r
-{\r
- INTN SourceSize;\r
- INTN Size;\r
- INTN BestMatch;\r
- UINTN HandleCount;\r
- UINTN Index;\r
- EFI_STATUS Status;\r
- EFI_HANDLE *Handles;\r
- EFI_HANDLE Handle;\r
- EFI_DEVICE_PATH_PROTOCOL *SourcePath;\r
- EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath;\r
- \r
- if (Protocol == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- \r
- if ((DevicePath == NULL) || (*DevicePath == NULL)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- \r
- if (Device == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- \r
- *Device = NULL_HANDLE;\r
- SourcePath = *DevicePath;\r
- SourceSize = CoreDevicePathSize (SourcePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL);\r
- \r
- //\r
- // The source path can only have 1 instance\r
- //\r
- if (CoreIsDevicePathMultiInstance (SourcePath)) {\r
- DEBUG((DEBUG_ERROR, "LocateDevicePath: Device path has too many instances\n"));\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- //\r
- // Get a list of all handles that support the requested protocol\r
- //\r
- Status = CoreLocateHandleBuffer (ByProtocol, Protocol, NULL, &HandleCount, &Handles);\r
- if (EFI_ERROR (Status) || HandleCount == 0) {\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- BestMatch = -1;\r
- for(Index = 0; Index < HandleCount; Index += 1) {\r
- Handle = Handles[Index];\r
- Status = CoreHandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&TmpDevicePath);\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // If this handle doesn't support device path, then skip it\r
- //\r
- continue;\r
- }\r
-\r
- //\r
- // Check if DevicePath is first part of SourcePath\r
- //\r
- Size = CoreDevicePathSize (TmpDevicePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL);\r
- if ((Size <= SourceSize) && CompareMem (SourcePath, TmpDevicePath, Size) == 0) {\r
- //\r
- // If the size is equal to the best match, then we\r
- // have a duplice device path for 2 different device\r
- // handles\r
- //\r
- ASSERT (Size != BestMatch);\r
- \r
- //\r
- // We've got a match, see if it's the best match so far\r
- //\r
- if (Size > BestMatch) {\r
- BestMatch = Size;\r
- *Device = Handle;\r
- }\r
- }\r
- }\r
-\r
- CoreFreePool (Handles);\r
- \r
- //\r
- // If there wasn't any match, then no parts of the device path was found. \r
- // Which is strange since there is likely a "root level" device path in the system.\r
- //\r
- if (BestMatch == -1) {\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- //\r
- // Return the remaining part of the device path\r
- //\r
- *DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) (((UINT8 *) SourcePath) + BestMatch);\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\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
-CoreLocateProtocol (\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) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- \r
- if (Protocol == NULL) {\r
- return EFI_NOT_FOUND;\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
- //\r
- // Lock the protocol database\r
- //\r
- CoreAcquireProtocolLock ();\r
-\r
- mEfiLocateHandleRequest += 1;\r
-\r
- if (NULL == Registration) {\r
- //\r
- // Look up the protocol entry and set the head pointer\r
- //\r
- Position.ProtEntry = CoreFindProtocolEntry (Protocol, FALSE);\r
- if (Position.ProtEntry == NULL) {\r
- Status = EFI_NOT_FOUND;\r
- goto Done;\r
- }\r
- Position.Position = &Position.ProtEntry->Protocols;\r
-\r
- Handle = CoreGetNextLocateByProtocol (&Position, Interface);\r
- } else {\r
- Handle = CoreGetNextLocateByRegisterNotify (&Position, Interface); \r
- }\r
-\r
- if (NULL == Handle) {\r
- Status = EFI_NOT_FOUND;\r
- } else if (NULL != Registration) {\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
-Done:\r
- CoreReleaseProtocolLock ();\r
- return Status;\r
-}\r
-\r
-\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 CoreLocateHandle()\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 Invalid parameter\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-CoreLocateHandleBuffer (\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 = CoreLocateHandle (\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 CoreLocateHandle().\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 = CoreAllocateBootServicesPool (BufferSize);\r
- if (*Buffer == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- Status = CoreLocateHandle (\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
-\r