2008-05-21 03:40:12 +02:00
|
|
|
/** @file
|
|
|
|
Locate handle functions
|
2007-07-04 12:51:54 +02:00
|
|
|
|
MdeModulePkg: Fix memory leak in LocateHandleBuffer()
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4543
REF: https://uefi.org/specs/UEFI/2.10/07_Services_Boot_Services.html#efi-boot-services-locatehandlebuffer
CoreLocateHandleBuffer() can in certain cases, return an
error and not free an allocated buffer. This scenario
occurs if the first call to InternalCoreLocateHandle()
returns success and the second call returns an error.
On a successful return, LocateHandleBuffer() passes
ownership of the buffer to the caller. However, the UEFI
specification is not explicit about what the expected
ownership of this buffer is in the case of an error.
However, it is heavily implied by the code example given
in section 7.3.15 of v2.10 of the UEFI specificaton that
if LocateHandleBuffer() returns a non-successful status
code then the ownership of the buffer does NOT transfer
to the caller. This code example explicitly refrains from
calling FreePool() if LocateHandleBuffer() returns an
error.
From a practical standpoint, it is logical to assume that
a non-successful status code indicates that no buffer of
handles was ever allocated. Indeed, in most error cases,
LocateHandleBuffer() does not go far enough to get to the
point where a buffer is allocated. Therefore, all existing
users of this API must already be coded to support the case
of a non-successful status code resulting in an invalid
handle buffer being returned. Therefore, this change will
not cause any backwards compatibility issues with existing
code.
In conclusion, this boils down to a fix for a memory leak
that also brings the behavior of our LocateHandleBuffer()
implementation into alignment with the original intentions
of the UEFI specification authors.
Reviewed-by: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Dandan Bi <dandan.bi@intel.com>
Signed-off-by: Nate DeSimone <nathaniel.l.desimone@intel.com>
2023-08-30 16:51:43 +02:00
|
|
|
Copyright (c) 2006 - 2023, Intel Corporation. All rights reserved.<BR>
|
2019-04-04 01:05:13 +02:00
|
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
2007-07-04 12:51:54 +02:00
|
|
|
|
2008-04-09 09:07:50 +02:00
|
|
|
**/
|
2007-07-04 12:51:54 +02:00
|
|
|
|
2008-08-27 16:29:23 +02:00
|
|
|
#include "DxeMain.h"
|
2008-09-23 09:35:34 +02:00
|
|
|
#include "Handle.h"
|
2007-07-04 12:51:54 +02:00
|
|
|
|
|
|
|
//
|
|
|
|
// ProtocolRequest - Last LocateHandle request ID
|
|
|
|
//
|
|
|
|
UINTN mEfiLocateHandleRequest = 0;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Internal prototypes
|
|
|
|
//
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
EFI_GUID *Protocol;
|
|
|
|
VOID *SearchKey;
|
|
|
|
LIST_ENTRY *Position;
|
|
|
|
PROTOCOL_ENTRY *ProtEntry;
|
|
|
|
} LOCATE_POSITION;
|
|
|
|
|
2008-07-24 04:54:45 +02:00
|
|
|
typedef
|
2007-07-04 12:51:54 +02:00
|
|
|
IHANDLE *
|
|
|
|
(*CORE_GET_NEXT) (
|
|
|
|
IN OUT LOCATE_POSITION *Position,
|
|
|
|
OUT VOID **Interface
|
|
|
|
);
|
|
|
|
|
2008-05-09 09:08:30 +02:00
|
|
|
/**
|
|
|
|
Routine to get the next Handle, when you are searching for all handles.
|
|
|
|
|
2008-07-24 04:54:45 +02:00
|
|
|
@param Position Information about which Handle to seach for.
|
|
|
|
@param Interface Return the interface structure for the matching
|
|
|
|
protocol.
|
2008-05-09 09:08:30 +02:00
|
|
|
|
2008-07-24 04:54:45 +02:00
|
|
|
@return An pointer to IHANDLE if the next Position is not the end of the list.
|
2008-09-08 07:02:38 +02:00
|
|
|
Otherwise,NULL is returned.
|
2008-05-09 09:08:30 +02:00
|
|
|
|
|
|
|
**/
|
2007-07-04 12:51:54 +02:00
|
|
|
IHANDLE *
|
|
|
|
CoreGetNextLocateAllHandles (
|
|
|
|
IN OUT LOCATE_POSITION *Position,
|
|
|
|
OUT VOID **Interface
|
|
|
|
);
|
|
|
|
|
2008-05-09 09:08:30 +02:00
|
|
|
/**
|
|
|
|
Routine to get the next Handle, when you are searching for register protocol
|
|
|
|
notifies.
|
|
|
|
|
2008-07-24 04:54:45 +02:00
|
|
|
@param Position Information about which Handle to seach for.
|
|
|
|
@param Interface Return the interface structure for the matching
|
|
|
|
protocol.
|
2008-05-09 09:08:30 +02:00
|
|
|
|
2008-07-24 04:54:45 +02:00
|
|
|
@return An pointer to IHANDLE if the next Position is not the end of the list.
|
2008-09-08 07:02:38 +02:00
|
|
|
Otherwise,NULL is returned.
|
2008-05-09 09:08:30 +02:00
|
|
|
|
|
|
|
**/
|
2007-07-04 12:51:54 +02:00
|
|
|
IHANDLE *
|
|
|
|
CoreGetNextLocateByRegisterNotify (
|
|
|
|
IN OUT LOCATE_POSITION *Position,
|
|
|
|
OUT VOID **Interface
|
|
|
|
);
|
|
|
|
|
2008-05-09 09:08:30 +02:00
|
|
|
/**
|
|
|
|
Routine to get the next Handle, when you are searching for a given protocol.
|
|
|
|
|
2008-07-24 04:54:45 +02:00
|
|
|
@param Position Information about which Handle to seach for.
|
|
|
|
@param Interface Return the interface structure for the matching
|
|
|
|
protocol.
|
2008-05-09 09:08:30 +02:00
|
|
|
|
2008-07-24 04:54:45 +02:00
|
|
|
@return An pointer to IHANDLE if the next Position is not the end of the list.
|
2008-09-08 07:02:38 +02:00
|
|
|
Otherwise,NULL is returned.
|
2008-05-09 09:08:30 +02:00
|
|
|
|
|
|
|
**/
|
2007-07-04 12:51:54 +02:00
|
|
|
IHANDLE *
|
|
|
|
CoreGetNextLocateByProtocol (
|
|
|
|
IN OUT LOCATE_POSITION *Position,
|
|
|
|
OUT VOID **Interface
|
|
|
|
);
|
|
|
|
|
2008-05-09 09:08:30 +02:00
|
|
|
/**
|
2021-09-29 07:08:14 +02:00
|
|
|
Internal function for locating the requested handle(s) and returns them in Buffer.
|
|
|
|
The caller should already have acquired the ProtocolLock.
|
2008-05-09 09:08:30 +02:00
|
|
|
|
2008-07-24 04:54:45 +02:00
|
|
|
@param SearchType The type of search to perform to locate the
|
|
|
|
handles
|
|
|
|
@param Protocol The protocol to search for
|
|
|
|
@param SearchKey Dependant on SearchType
|
|
|
|
@param BufferSize On input the size of Buffer. On output the
|
|
|
|
size of data returned.
|
|
|
|
@param Buffer The buffer to return the results in
|
|
|
|
|
|
|
|
@retval EFI_BUFFER_TOO_SMALL Buffer too small, required buffer size is
|
|
|
|
returned in BufferSize.
|
|
|
|
@retval EFI_INVALID_PARAMETER Invalid parameter
|
|
|
|
@retval EFI_SUCCESS Successfully found the requested handle(s) and
|
2008-05-09 09:08:30 +02:00
|
|
|
returns them in Buffer.
|
2007-07-04 12:51:54 +02:00
|
|
|
|
2008-05-09 09:08:30 +02:00
|
|
|
**/
|
2007-07-04 12:51:54 +02:00
|
|
|
EFI_STATUS
|
2021-09-29 07:08:14 +02:00
|
|
|
InternalCoreLocateHandle (
|
2007-07-04 12:51:54 +02:00
|
|
|
IN EFI_LOCATE_SEARCH_TYPE SearchType,
|
|
|
|
IN EFI_GUID *Protocol OPTIONAL,
|
|
|
|
IN VOID *SearchKey OPTIONAL,
|
|
|
|
IN OUT UINTN *BufferSize,
|
|
|
|
OUT EFI_HANDLE *Buffer
|
|
|
|
)
|
|
|
|
{
|
|
|
|
EFI_STATUS Status;
|
|
|
|
LOCATE_POSITION Position;
|
|
|
|
PROTOCOL_NOTIFY *ProtNotify;
|
|
|
|
CORE_GET_NEXT GetNext;
|
|
|
|
UINTN ResultSize;
|
|
|
|
IHANDLE *Handle;
|
|
|
|
IHANDLE **ResultBuffer;
|
|
|
|
VOID *Interface;
|
2008-07-24 04:54:45 +02:00
|
|
|
|
2007-07-04 12:51:54 +02:00
|
|
|
if (BufferSize == NULL) {
|
2009-01-21 05:56:24 +01:00
|
|
|
return EFI_INVALID_PARAMETER;
|
2007-07-04 12:51:54 +02:00
|
|
|
}
|
2008-07-24 04:54:45 +02:00
|
|
|
|
2007-07-04 12:51:54 +02:00
|
|
|
if ((*BufferSize > 0) && (Buffer == NULL)) {
|
|
|
|
return EFI_INVALID_PARAMETER;
|
|
|
|
}
|
2008-07-24 04:54:45 +02:00
|
|
|
|
2007-07-04 12:51:54 +02:00
|
|
|
GetNext = NULL;
|
2008-07-18 11:50:09 +02:00
|
|
|
|
2007-07-04 12:51:54 +02:00
|
|
|
//
|
|
|
|
// Set initial position
|
|
|
|
//
|
|
|
|
Position.Protocol = Protocol;
|
|
|
|
Position.SearchKey = SearchKey;
|
|
|
|
Position.Position = &gHandleList;
|
|
|
|
|
|
|
|
ResultSize = 0;
|
|
|
|
ResultBuffer = (IHANDLE **)Buffer;
|
|
|
|
Status = EFI_SUCCESS;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Get the search function based on type
|
|
|
|
//
|
|
|
|
switch (SearchType) {
|
2008-07-24 04:54:45 +02:00
|
|
|
case AllHandles:
|
|
|
|
GetNext = CoreGetNextLocateAllHandles;
|
2007-07-04 12:51:54 +02:00
|
|
|
break;
|
|
|
|
|
2008-07-24 04:54:45 +02:00
|
|
|
case ByRegisterNotify:
|
2021-12-05 23:54:02 +01:00
|
|
|
//
|
2007-07-04 12:51:54 +02:00
|
|
|
// Must have SearchKey for locate ByRegisterNotify
|
2021-12-05 23:54:02 +01:00
|
|
|
//
|
2007-07-04 12:51:54 +02:00
|
|
|
if (SearchKey == NULL) {
|
|
|
|
Status = EFI_INVALID_PARAMETER;
|
2021-12-05 23:54:02 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2008-07-24 04:54:45 +02:00
|
|
|
GetNext = CoreGetNextLocateByRegisterNotify;
|
2007-07-04 12:51:54 +02:00
|
|
|
break;
|
2021-12-05 23:54:02 +01:00
|
|
|
|
2007-07-04 12:51:54 +02:00
|
|
|
case ByProtocol:
|
2008-07-24 04:54:45 +02:00
|
|
|
GetNext = CoreGetNextLocateByProtocol;
|
2007-07-04 12:51:54 +02:00
|
|
|
if (Protocol == NULL) {
|
|
|
|
Status = EFI_INVALID_PARAMETER;
|
2021-12-05 23:54:02 +01:00
|
|
|
break;
|
2007-07-04 12:51:54 +02:00
|
|
|
}
|
2021-12-05 23:54:02 +01:00
|
|
|
|
2007-07-04 12:51:54 +02:00
|
|
|
//
|
|
|
|
// Look up the protocol entry and set the head pointer
|
|
|
|
//
|
|
|
|
Position.ProtEntry = CoreFindProtocolEntry (Protocol, FALSE);
|
|
|
|
if (Position.ProtEntry == NULL) {
|
|
|
|
Status = EFI_NOT_FOUND;
|
2021-12-05 23:54:02 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2007-07-04 12:51:54 +02:00
|
|
|
Position.Position = &Position.ProtEntry->Protocols;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
Status = EFI_INVALID_PARAMETER;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
2010-02-26 09:53:27 +01:00
|
|
|
ASSERT (GetNext != NULL);
|
2007-07-04 12:51:54 +02:00
|
|
|
//
|
|
|
|
// Enumerate out the matching handles
|
|
|
|
//
|
|
|
|
mEfiLocateHandleRequest += 1;
|
|
|
|
for ( ; ;) {
|
|
|
|
//
|
|
|
|
// Get the next handle. If no more handles, stop
|
|
|
|
//
|
|
|
|
Handle = GetNext (&Position, &Interface);
|
|
|
|
if (NULL == Handle) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Increase the resulting buffer size, and if this handle
|
|
|
|
// fits return it
|
|
|
|
//
|
|
|
|
ResultSize += sizeof (Handle);
|
|
|
|
if (ResultSize <= *BufferSize) {
|
|
|
|
*ResultBuffer = Handle;
|
|
|
|
ResultBuffer += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// If the result is a zero length buffer, then there were no
|
|
|
|
// matching handles
|
|
|
|
//
|
|
|
|
if (ResultSize == 0) {
|
|
|
|
Status = EFI_NOT_FOUND;
|
|
|
|
} else {
|
|
|
|
//
|
|
|
|
// Return the resulting buffer size. If it's larger than what
|
|
|
|
// was passed, then set the error code
|
|
|
|
//
|
|
|
|
if (ResultSize > *BufferSize) {
|
|
|
|
Status = EFI_BUFFER_TOO_SMALL;
|
2008-07-24 04:54:45 +02:00
|
|
|
}
|
|
|
|
|
2007-07-04 12:51:54 +02:00
|
|
|
*BufferSize = ResultSize;
|
|
|
|
|
|
|
|
if ((SearchType == ByRegisterNotify) && !EFI_ERROR (Status)) {
|
|
|
|
//
|
|
|
|
// If this is a search by register notify and a handle was
|
|
|
|
// returned, update the register notification position
|
2008-07-24 04:54:45 +02:00
|
|
|
//
|
2010-02-26 09:53:27 +01:00
|
|
|
ASSERT (SearchKey != NULL);
|
2007-07-04 12:51:54 +02:00
|
|
|
ProtNotify = SearchKey;
|
|
|
|
ProtNotify->Position = ProtNotify->Position->ForwardLink;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
2021-09-29 07:08:14 +02:00
|
|
|
/**
|
|
|
|
Locates the requested handle(s) and returns them in Buffer.
|
|
|
|
|
|
|
|
@param SearchType The type of search to perform to locate the
|
|
|
|
handles
|
|
|
|
@param Protocol The protocol to search for
|
|
|
|
@param SearchKey Dependant on SearchType
|
|
|
|
@param BufferSize On input the size of Buffer. On output the
|
|
|
|
size of data returned.
|
|
|
|
@param Buffer The buffer to return the results in
|
|
|
|
|
|
|
|
@retval EFI_BUFFER_TOO_SMALL Buffer too small, required buffer size is
|
|
|
|
returned in BufferSize.
|
|
|
|
@retval EFI_INVALID_PARAMETER Invalid parameter
|
|
|
|
@retval EFI_SUCCESS Successfully found the requested handle(s) and
|
|
|
|
returns them in Buffer.
|
|
|
|
|
|
|
|
**/
|
|
|
|
EFI_STATUS
|
|
|
|
EFIAPI
|
|
|
|
CoreLocateHandle (
|
|
|
|
IN EFI_LOCATE_SEARCH_TYPE SearchType,
|
|
|
|
IN EFI_GUID *Protocol OPTIONAL,
|
|
|
|
IN VOID *SearchKey OPTIONAL,
|
|
|
|
IN OUT UINTN *BufferSize,
|
|
|
|
OUT EFI_HANDLE *Buffer
|
|
|
|
)
|
|
|
|
{
|
|
|
|
EFI_STATUS Status;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Lock the protocol database
|
|
|
|
//
|
|
|
|
CoreAcquireProtocolLock ();
|
|
|
|
Status = InternalCoreLocateHandle (SearchType, Protocol, SearchKey, BufferSize, Buffer);
|
|
|
|
CoreReleaseProtocolLock ();
|
|
|
|
return Status;
|
|
|
|
}
|
2007-07-04 12:51:54 +02:00
|
|
|
|
2008-05-09 09:08:30 +02:00
|
|
|
/**
|
|
|
|
Routine to get the next Handle, when you are searching for all handles.
|
|
|
|
|
2008-07-24 04:54:45 +02:00
|
|
|
@param Position Information about which Handle to seach for.
|
|
|
|
@param Interface Return the interface structure for the matching
|
|
|
|
protocol.
|
2008-05-09 09:08:30 +02:00
|
|
|
|
2008-07-18 11:50:09 +02:00
|
|
|
@return An pointer to IHANDLE if the next Position is not the end of the list.
|
2008-09-08 07:02:38 +02:00
|
|
|
Otherwise,NULL is returned.
|
2008-05-09 09:08:30 +02:00
|
|
|
|
|
|
|
**/
|
2007-07-04 12:51:54 +02:00
|
|
|
IHANDLE *
|
|
|
|
CoreGetNextLocateAllHandles (
|
|
|
|
IN OUT LOCATE_POSITION *Position,
|
|
|
|
OUT VOID **Interface
|
|
|
|
)
|
|
|
|
{
|
|
|
|
IHANDLE *Handle;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Next handle
|
|
|
|
//
|
|
|
|
Position->Position = Position->Position->ForwardLink;
|
|
|
|
|
|
|
|
//
|
|
|
|
// If not at the end of the list, get the handle
|
|
|
|
//
|
2008-09-08 07:02:38 +02:00
|
|
|
Handle = NULL;
|
2007-07-04 12:51:54 +02:00
|
|
|
*Interface = NULL;
|
|
|
|
if (Position->Position != &gHandleList) {
|
|
|
|
Handle = CR (Position->Position, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
return Handle;
|
|
|
|
}
|
|
|
|
|
2008-05-09 09:08:30 +02:00
|
|
|
/**
|
|
|
|
Routine to get the next Handle, when you are searching for register protocol
|
|
|
|
notifies.
|
|
|
|
|
2008-07-24 04:54:45 +02:00
|
|
|
@param Position Information about which Handle to seach for.
|
|
|
|
@param Interface Return the interface structure for the matching
|
|
|
|
protocol.
|
2008-05-09 09:08:30 +02:00
|
|
|
|
2008-07-18 11:50:09 +02:00
|
|
|
@return An pointer to IHANDLE if the next Position is not the end of the list.
|
2008-09-08 07:02:38 +02:00
|
|
|
Otherwise,NULL is returned.
|
2008-05-09 09:08:30 +02:00
|
|
|
|
|
|
|
**/
|
2007-07-04 12:51:54 +02:00
|
|
|
IHANDLE *
|
|
|
|
CoreGetNextLocateByRegisterNotify (
|
|
|
|
IN OUT LOCATE_POSITION *Position,
|
|
|
|
OUT VOID **Interface
|
|
|
|
)
|
|
|
|
{
|
|
|
|
IHANDLE *Handle;
|
|
|
|
PROTOCOL_NOTIFY *ProtNotify;
|
|
|
|
PROTOCOL_INTERFACE *Prot;
|
2008-07-24 04:54:45 +02:00
|
|
|
LIST_ENTRY *Link;
|
2007-07-04 12:51:54 +02:00
|
|
|
|
2008-09-08 07:02:38 +02:00
|
|
|
Handle = NULL;
|
2007-07-04 12:51:54 +02:00
|
|
|
*Interface = NULL;
|
|
|
|
ProtNotify = Position->SearchKey;
|
|
|
|
|
|
|
|
//
|
|
|
|
// If this is the first request, get the next handle
|
|
|
|
//
|
|
|
|
if (ProtNotify != NULL) {
|
|
|
|
ASSERT (ProtNotify->Signature == PROTOCOL_NOTIFY_SIGNATURE);
|
|
|
|
Position->SearchKey = NULL;
|
|
|
|
|
|
|
|
//
|
|
|
|
// If not at the end of the list, get the next handle
|
|
|
|
//
|
|
|
|
Link = ProtNotify->Position->ForwardLink;
|
|
|
|
if (Link != &ProtNotify->Protocol->Protocols) {
|
|
|
|
Prot = CR (Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE);
|
2008-09-08 14:50:40 +02:00
|
|
|
Handle = Prot->Handle;
|
2007-07-04 12:51:54 +02:00
|
|
|
*Interface = Prot->Interface;
|
2008-07-24 04:54:45 +02:00
|
|
|
}
|
2007-07-04 12:51:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return Handle;
|
|
|
|
}
|
|
|
|
|
2008-05-09 09:08:30 +02:00
|
|
|
/**
|
|
|
|
Routine to get the next Handle, when you are searching for a given protocol.
|
|
|
|
|
2008-07-24 04:54:45 +02:00
|
|
|
@param Position Information about which Handle to seach for.
|
|
|
|
@param Interface Return the interface structure for the matching
|
|
|
|
protocol.
|
2008-05-09 09:08:30 +02:00
|
|
|
|
2008-07-18 11:50:09 +02:00
|
|
|
@return An pointer to IHANDLE if the next Position is not the end of the list.
|
2008-09-08 07:02:38 +02:00
|
|
|
Otherwise,NULL is returned.
|
2008-05-09 09:08:30 +02:00
|
|
|
|
|
|
|
**/
|
2007-07-04 12:51:54 +02:00
|
|
|
IHANDLE *
|
|
|
|
CoreGetNextLocateByProtocol (
|
|
|
|
IN OUT LOCATE_POSITION *Position,
|
|
|
|
OUT VOID **Interface
|
|
|
|
)
|
|
|
|
{
|
|
|
|
IHANDLE *Handle;
|
|
|
|
LIST_ENTRY *Link;
|
|
|
|
PROTOCOL_INTERFACE *Prot;
|
2008-07-24 04:54:45 +02:00
|
|
|
|
2008-09-08 07:02:38 +02:00
|
|
|
Handle = NULL;
|
2007-07-04 12:51:54 +02:00
|
|
|
*Interface = NULL;
|
|
|
|
for ( ; ;) {
|
|
|
|
//
|
|
|
|
// Next entry
|
|
|
|
//
|
|
|
|
Link = Position->Position->ForwardLink;
|
|
|
|
Position->Position = Link;
|
|
|
|
|
|
|
|
//
|
|
|
|
// If not at the end, return the handle
|
|
|
|
//
|
|
|
|
if (Link == &Position->ProtEntry->Protocols) {
|
2008-09-08 07:02:38 +02:00
|
|
|
Handle = NULL;
|
2007-07-04 12:51:54 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Get the handle
|
|
|
|
//
|
|
|
|
Prot = CR (Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE);
|
2008-09-08 14:50:40 +02:00
|
|
|
Handle = Prot->Handle;
|
2007-07-04 12:51:54 +02:00
|
|
|
*Interface = Prot->Interface;
|
|
|
|
|
|
|
|
//
|
2008-07-24 04:54:45 +02:00
|
|
|
// If this handle has not been returned this request, then
|
2007-07-04 12:51:54 +02:00
|
|
|
// return it now
|
|
|
|
//
|
|
|
|
if (Handle->LocateRequest != mEfiLocateHandleRequest) {
|
|
|
|
Handle->LocateRequest = mEfiLocateHandleRequest;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return Handle;
|
|
|
|
}
|
|
|
|
|
2008-05-09 09:08:30 +02:00
|
|
|
/**
|
2011-03-16 17:17:09 +01:00
|
|
|
Locates the handle to a device on the device path that supports the specified protocol.
|
2008-05-09 09:08:30 +02:00
|
|
|
|
2011-03-16 17:17:09 +01:00
|
|
|
@param Protocol Specifies the protocol to search for.
|
|
|
|
@param DevicePath On input, a pointer to a pointer to the device path. On output, the device
|
|
|
|
path pointer is modified to point to the remaining part of the device
|
|
|
|
path.
|
|
|
|
@param Device A pointer to the returned device handle.
|
2008-05-09 09:08:30 +02:00
|
|
|
|
2011-03-16 17:17:09 +01:00
|
|
|
@retval EFI_SUCCESS The resulting handle was returned.
|
|
|
|
@retval EFI_NOT_FOUND No handles match the search.
|
|
|
|
@retval EFI_INVALID_PARAMETER Protocol is NULL.
|
|
|
|
@retval EFI_INVALID_PARAMETER DevicePath is NULL.
|
|
|
|
@retval EFI_INVALID_PARAMETER A handle matched the search and Device is NULL.
|
2008-05-09 09:08:30 +02:00
|
|
|
|
|
|
|
**/
|
2007-07-04 12:51:54 +02:00
|
|
|
EFI_STATUS
|
|
|
|
EFIAPI
|
|
|
|
CoreLocateDevicePath (
|
|
|
|
IN EFI_GUID *Protocol,
|
|
|
|
IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath,
|
|
|
|
OUT EFI_HANDLE *Device
|
|
|
|
)
|
|
|
|
{
|
|
|
|
INTN SourceSize;
|
|
|
|
INTN Size;
|
|
|
|
INTN BestMatch;
|
|
|
|
UINTN HandleCount;
|
|
|
|
UINTN Index;
|
|
|
|
EFI_STATUS Status;
|
|
|
|
EFI_HANDLE *Handles;
|
|
|
|
EFI_HANDLE Handle;
|
2011-03-16 17:17:09 +01:00
|
|
|
EFI_HANDLE BestDevice;
|
2007-07-04 12:51:54 +02:00
|
|
|
EFI_DEVICE_PATH_PROTOCOL *SourcePath;
|
|
|
|
EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath;
|
2008-07-24 04:54:45 +02:00
|
|
|
|
2007-07-04 12:51:54 +02:00
|
|
|
if (Protocol == NULL) {
|
|
|
|
return EFI_INVALID_PARAMETER;
|
|
|
|
}
|
2008-07-24 04:54:45 +02:00
|
|
|
|
2007-07-04 12:51:54 +02:00
|
|
|
if ((DevicePath == NULL) || (*DevicePath == NULL)) {
|
|
|
|
return EFI_INVALID_PARAMETER;
|
|
|
|
}
|
2008-07-24 04:54:45 +02:00
|
|
|
|
2014-07-28 09:52:57 +02:00
|
|
|
Handles = NULL;
|
2011-03-16 17:17:09 +01:00
|
|
|
BestDevice = NULL;
|
2007-07-04 12:51:54 +02:00
|
|
|
SourcePath = *DevicePath;
|
2009-09-21 16:26:05 +02:00
|
|
|
TmpDevicePath = SourcePath;
|
|
|
|
while (!IsDevicePathEnd (TmpDevicePath)) {
|
|
|
|
if (IsDevicePathEndInstance (TmpDevicePath)) {
|
|
|
|
//
|
|
|
|
// If DevicePath is a multi-instance device path,
|
2018-06-27 15:08:52 +02:00
|
|
|
// the function will operate on the first instance
|
2009-09-21 16:26:05 +02:00
|
|
|
//
|
|
|
|
break;
|
|
|
|
}
|
2021-12-05 23:54:02 +01:00
|
|
|
|
2009-09-21 16:26:05 +02:00
|
|
|
TmpDevicePath = NextDevicePathNode (TmpDevicePath);
|
|
|
|
}
|
|
|
|
|
|
|
|
SourceSize = (UINTN)TmpDevicePath - (UINTN)SourcePath;
|
2008-07-24 04:54:45 +02:00
|
|
|
|
2007-07-04 12:51:54 +02:00
|
|
|
//
|
|
|
|
// Get a list of all handles that support the requested protocol
|
|
|
|
//
|
|
|
|
Status = CoreLocateHandleBuffer (ByProtocol, Protocol, NULL, &HandleCount, &Handles);
|
|
|
|
if (EFI_ERROR (Status) || (HandleCount == 0)) {
|
|
|
|
return EFI_NOT_FOUND;
|
|
|
|
}
|
|
|
|
|
|
|
|
BestMatch = -1;
|
|
|
|
for (Index = 0; Index < HandleCount; Index += 1) {
|
|
|
|
Handle = Handles[Index];
|
|
|
|
Status = CoreHandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&TmpDevicePath);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
//
|
|
|
|
// If this handle doesn't support device path, then skip it
|
|
|
|
//
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Check if DevicePath is first part of SourcePath
|
|
|
|
//
|
2008-08-27 16:29:23 +02:00
|
|
|
Size = GetDevicePathSize (TmpDevicePath) - sizeof (EFI_DEVICE_PATH_PROTOCOL);
|
2010-09-16 06:51:25 +02:00
|
|
|
ASSERT (Size >= 0);
|
|
|
|
if ((Size <= SourceSize) && (CompareMem (SourcePath, TmpDevicePath, (UINTN)Size) == 0)) {
|
2007-07-04 12:51:54 +02:00
|
|
|
//
|
|
|
|
// If the size is equal to the best match, then we
|
2009-09-21 16:26:05 +02:00
|
|
|
// have a duplicate device path for 2 different device
|
2007-07-04 12:51:54 +02:00
|
|
|
// handles
|
|
|
|
//
|
|
|
|
ASSERT (Size != BestMatch);
|
2008-07-24 04:54:45 +02:00
|
|
|
|
2007-07-04 12:51:54 +02:00
|
|
|
//
|
|
|
|
// We've got a match, see if it's the best match so far
|
|
|
|
//
|
|
|
|
if (Size > BestMatch) {
|
|
|
|
BestMatch = Size;
|
2011-03-16 17:17:09 +01:00
|
|
|
BestDevice = Handle;
|
2007-07-04 12:51:54 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CoreFreePool (Handles);
|
2008-07-24 04:54:45 +02:00
|
|
|
|
2007-07-04 12:51:54 +02:00
|
|
|
//
|
2008-07-24 04:54:45 +02:00
|
|
|
// If there wasn't any match, then no parts of the device path was found.
|
2007-07-04 12:51:54 +02:00
|
|
|
// Which is strange since there is likely a "root level" device path in the system.
|
|
|
|
//
|
|
|
|
if (BestMatch == -1) {
|
|
|
|
return EFI_NOT_FOUND;
|
|
|
|
}
|
|
|
|
|
2011-03-16 17:17:09 +01:00
|
|
|
if (Device == NULL) {
|
|
|
|
return EFI_INVALID_PARAMETER;
|
|
|
|
}
|
2021-12-05 23:54:02 +01:00
|
|
|
|
2011-03-16 17:17:09 +01:00
|
|
|
*Device = BestDevice;
|
2018-06-27 15:08:52 +02:00
|
|
|
|
2007-07-04 12:51:54 +02:00
|
|
|
//
|
|
|
|
// Return the remaining part of the device path
|
|
|
|
//
|
|
|
|
*DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)(((UINT8 *)SourcePath) + BestMatch);
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2008-07-26 09:46:04 +02:00
|
|
|
/**
|
2007-07-04 12:51:54 +02:00
|
|
|
Return the first Protocol Interface that matches the Protocol GUID. If
|
2009-05-11 09:28:44 +02:00
|
|
|
Registration is passed in, return a Protocol Instance that was just add
|
|
|
|
to the system. If Registration is NULL return the first Protocol Interface
|
2007-07-04 12:51:54 +02:00
|
|
|
you find.
|
|
|
|
|
2008-07-24 04:54:45 +02:00
|
|
|
@param Protocol The protocol to search for
|
|
|
|
@param Registration Optional Registration Key returned from
|
|
|
|
RegisterProtocolNotify()
|
|
|
|
@param Interface Return the Protocol interface (instance).
|
2007-07-04 12:51:54 +02:00
|
|
|
|
2008-07-24 04:54:45 +02:00
|
|
|
@retval EFI_SUCCESS If a valid Interface is returned
|
|
|
|
@retval EFI_INVALID_PARAMETER Invalid parameter
|
2008-05-09 09:08:30 +02:00
|
|
|
@retval EFI_NOT_FOUND Protocol interface not found
|
2007-07-04 12:51:54 +02:00
|
|
|
|
2008-05-09 09:08:30 +02:00
|
|
|
**/
|
|
|
|
EFI_STATUS
|
|
|
|
EFIAPI
|
|
|
|
CoreLocateProtocol (
|
|
|
|
IN EFI_GUID *Protocol,
|
|
|
|
IN VOID *Registration OPTIONAL,
|
|
|
|
OUT VOID **Interface
|
|
|
|
)
|
2007-07-04 12:51:54 +02:00
|
|
|
{
|
|
|
|
EFI_STATUS Status;
|
|
|
|
LOCATE_POSITION Position;
|
|
|
|
PROTOCOL_NOTIFY *ProtNotify;
|
|
|
|
IHANDLE *Handle;
|
|
|
|
|
2017-06-20 12:25:29 +02:00
|
|
|
if ((Interface == NULL) || (Protocol == NULL)) {
|
2007-07-04 12:51:54 +02:00
|
|
|
return EFI_INVALID_PARAMETER;
|
|
|
|
}
|
2008-07-24 04:54:45 +02:00
|
|
|
|
2007-07-04 12:51:54 +02:00
|
|
|
*Interface = NULL;
|
|
|
|
Status = EFI_SUCCESS;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Set initial position
|
|
|
|
//
|
|
|
|
Position.Protocol = Protocol;
|
|
|
|
Position.SearchKey = Registration;
|
|
|
|
Position.Position = &gHandleList;
|
2008-07-24 04:54:45 +02:00
|
|
|
|
2007-07-04 12:51:54 +02:00
|
|
|
//
|
|
|
|
// Lock the protocol database
|
|
|
|
//
|
2016-04-22 11:08:49 +02:00
|
|
|
Status = CoreAcquireLockOrFail (&gProtocolDatabaseLock);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
return EFI_NOT_FOUND;
|
|
|
|
}
|
2007-07-04 12:51:54 +02:00
|
|
|
|
|
|
|
mEfiLocateHandleRequest += 1;
|
|
|
|
|
2008-07-18 11:50:09 +02:00
|
|
|
if (Registration == NULL) {
|
2007-07-04 12:51:54 +02:00
|
|
|
//
|
|
|
|
// Look up the protocol entry and set the head pointer
|
|
|
|
//
|
|
|
|
Position.ProtEntry = CoreFindProtocolEntry (Protocol, FALSE);
|
|
|
|
if (Position.ProtEntry == NULL) {
|
|
|
|
Status = EFI_NOT_FOUND;
|
|
|
|
goto Done;
|
|
|
|
}
|
2021-12-05 23:54:02 +01:00
|
|
|
|
2007-07-04 12:51:54 +02:00
|
|
|
Position.Position = &Position.ProtEntry->Protocols;
|
|
|
|
|
|
|
|
Handle = CoreGetNextLocateByProtocol (&Position, Interface);
|
|
|
|
} else {
|
2008-07-24 04:54:45 +02:00
|
|
|
Handle = CoreGetNextLocateByRegisterNotify (&Position, Interface);
|
2007-07-04 12:51:54 +02:00
|
|
|
}
|
|
|
|
|
2008-07-18 11:50:09 +02:00
|
|
|
if (Handle == NULL) {
|
2007-07-04 12:51:54 +02:00
|
|
|
Status = EFI_NOT_FOUND;
|
2008-07-18 11:50:09 +02:00
|
|
|
} else if (Registration != NULL) {
|
2007-07-04 12:51:54 +02:00
|
|
|
//
|
|
|
|
// If this is a search by register notify and a handle was
|
|
|
|
// returned, update the register notification position
|
2008-07-24 04:54:45 +02:00
|
|
|
//
|
2007-07-04 12:51:54 +02:00
|
|
|
ProtNotify = Registration;
|
|
|
|
ProtNotify->Position = ProtNotify->Position->ForwardLink;
|
|
|
|
}
|
|
|
|
|
|
|
|
Done:
|
|
|
|
CoreReleaseProtocolLock ();
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
2008-05-09 09:08:30 +02:00
|
|
|
/**
|
|
|
|
Function returns an array of handles that support the requested protocol
|
|
|
|
in a buffer allocated from pool. This is a version of CoreLocateHandle()
|
|
|
|
that allocates a buffer for the caller.
|
|
|
|
|
2008-07-24 04:54:45 +02:00
|
|
|
@param SearchType Specifies which handle(s) are to be returned.
|
|
|
|
@param Protocol Provides the protocol to search by. This
|
|
|
|
parameter is only valid for SearchType
|
|
|
|
ByProtocol.
|
|
|
|
@param SearchKey Supplies the search key depending on the
|
|
|
|
SearchType.
|
|
|
|
@param NumberHandles The number of handles returned in Buffer.
|
|
|
|
@param Buffer A pointer to the buffer to return the requested
|
|
|
|
array of handles that support Protocol.
|
|
|
|
|
|
|
|
@retval EFI_SUCCESS The result array of handles was returned.
|
|
|
|
@retval EFI_NOT_FOUND No handles match the search.
|
|
|
|
@retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the
|
|
|
|
matching results.
|
2016-10-19 09:01:23 +02:00
|
|
|
@retval EFI_INVALID_PARAMETER One or more parameters are not valid.
|
2008-05-09 09:08:30 +02:00
|
|
|
|
|
|
|
**/
|
2007-07-04 12:51:54 +02:00
|
|
|
EFI_STATUS
|
|
|
|
EFIAPI
|
|
|
|
CoreLocateHandleBuffer (
|
|
|
|
IN EFI_LOCATE_SEARCH_TYPE SearchType,
|
|
|
|
IN EFI_GUID *Protocol OPTIONAL,
|
|
|
|
IN VOID *SearchKey OPTIONAL,
|
|
|
|
IN OUT UINTN *NumberHandles,
|
|
|
|
OUT EFI_HANDLE **Buffer
|
|
|
|
)
|
|
|
|
{
|
|
|
|
EFI_STATUS Status;
|
|
|
|
UINTN BufferSize;
|
|
|
|
|
|
|
|
if (NumberHandles == NULL) {
|
|
|
|
return EFI_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Buffer == NULL) {
|
|
|
|
return EFI_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
|
|
|
BufferSize = 0;
|
|
|
|
*NumberHandles = 0;
|
|
|
|
*Buffer = NULL;
|
2021-09-29 07:08:14 +02:00
|
|
|
|
|
|
|
//
|
|
|
|
// Lock the protocol database
|
|
|
|
//
|
|
|
|
CoreAcquireProtocolLock ();
|
|
|
|
Status = InternalCoreLocateHandle (
|
2007-07-04 12:51:54 +02:00
|
|
|
SearchType,
|
|
|
|
Protocol,
|
|
|
|
SearchKey,
|
|
|
|
&BufferSize,
|
|
|
|
*Buffer
|
|
|
|
);
|
|
|
|
//
|
|
|
|
// LocateHandleBuffer() returns incorrect status code if SearchType is
|
|
|
|
// invalid.
|
|
|
|
//
|
|
|
|
// Add code to correctly handle expected errors from CoreLocateHandle().
|
|
|
|
//
|
|
|
|
if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) {
|
|
|
|
if (Status != EFI_INVALID_PARAMETER) {
|
|
|
|
Status = EFI_NOT_FOUND;
|
|
|
|
}
|
2021-12-05 23:54:02 +01:00
|
|
|
|
2021-09-29 07:08:14 +02:00
|
|
|
CoreReleaseProtocolLock ();
|
2007-07-04 12:51:54 +02:00
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
2008-08-27 16:29:23 +02:00
|
|
|
*Buffer = AllocatePool (BufferSize);
|
2007-07-04 12:51:54 +02:00
|
|
|
if (*Buffer == NULL) {
|
2021-09-29 07:08:14 +02:00
|
|
|
CoreReleaseProtocolLock ();
|
2007-07-04 12:51:54 +02:00
|
|
|
return EFI_OUT_OF_RESOURCES;
|
|
|
|
}
|
|
|
|
|
2021-09-29 07:08:14 +02:00
|
|
|
Status = InternalCoreLocateHandle (
|
2007-07-04 12:51:54 +02:00
|
|
|
SearchType,
|
|
|
|
Protocol,
|
|
|
|
SearchKey,
|
|
|
|
&BufferSize,
|
|
|
|
*Buffer
|
|
|
|
);
|
|
|
|
|
2008-07-18 11:50:09 +02:00
|
|
|
*NumberHandles = BufferSize / sizeof (EFI_HANDLE);
|
2007-07-04 12:51:54 +02:00
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
*NumberHandles = 0;
|
MdeModulePkg: Fix memory leak in LocateHandleBuffer()
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4543
REF: https://uefi.org/specs/UEFI/2.10/07_Services_Boot_Services.html#efi-boot-services-locatehandlebuffer
CoreLocateHandleBuffer() can in certain cases, return an
error and not free an allocated buffer. This scenario
occurs if the first call to InternalCoreLocateHandle()
returns success and the second call returns an error.
On a successful return, LocateHandleBuffer() passes
ownership of the buffer to the caller. However, the UEFI
specification is not explicit about what the expected
ownership of this buffer is in the case of an error.
However, it is heavily implied by the code example given
in section 7.3.15 of v2.10 of the UEFI specificaton that
if LocateHandleBuffer() returns a non-successful status
code then the ownership of the buffer does NOT transfer
to the caller. This code example explicitly refrains from
calling FreePool() if LocateHandleBuffer() returns an
error.
From a practical standpoint, it is logical to assume that
a non-successful status code indicates that no buffer of
handles was ever allocated. Indeed, in most error cases,
LocateHandleBuffer() does not go far enough to get to the
point where a buffer is allocated. Therefore, all existing
users of this API must already be coded to support the case
of a non-successful status code resulting in an invalid
handle buffer being returned. Therefore, this change will
not cause any backwards compatibility issues with existing
code.
In conclusion, this boils down to a fix for a memory leak
that also brings the behavior of our LocateHandleBuffer()
implementation into alignment with the original intentions
of the UEFI specification authors.
Reviewed-by: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Dandan Bi <dandan.bi@intel.com>
Signed-off-by: Nate DeSimone <nathaniel.l.desimone@intel.com>
2023-08-30 16:51:43 +02:00
|
|
|
if (*Buffer != NULL) {
|
|
|
|
CoreFreePool (*Buffer);
|
|
|
|
*Buffer = NULL;
|
|
|
|
}
|
2007-07-04 12:51:54 +02:00
|
|
|
}
|
|
|
|
|
2021-09-29 07:08:14 +02:00
|
|
|
CoreReleaseProtocolLock ();
|
2007-07-04 12:51:54 +02:00
|
|
|
return Status;
|
|
|
|
}
|