2 Locate handle functions
4 Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.<BR>
5 Copyright (c) 2016 - 2021, Arm Limited. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include "StandaloneMmCore.h"
13 // ProtocolRequest - Last LocateHandle request ID
15 UINTN mEfiLocateHandleRequest
= 0;
18 // Internal prototypes
25 PROTOCOL_ENTRY
*ProtEntry
;
31 IN OUT LOCATE_POSITION
*Position
,
36 Routine to get the next Handle, when you are searching for all handles.
38 @param Position Information about which Handle to seach for.
39 @param Interface Return the interface structure for the matching
42 @return An pointer to IHANDLE if the next Position is not the end of the list.
43 Otherwise,NULL is returned.
47 MmGetNextLocateAllHandles (
48 IN OUT LOCATE_POSITION
*Position
,
57 Position
->Position
= Position
->Position
->ForwardLink
;
60 // If not at the end of the list, get the handle
64 if (Position
->Position
!= &gHandleList
) {
65 Handle
= CR (Position
->Position
, IHANDLE
, AllHandles
, EFI_HANDLE_SIGNATURE
);
72 Routine to get the next Handle, when you are searching for register protocol
75 @param Position Information about which Handle to seach for.
76 @param Interface Return the interface structure for the matching
79 @return An pointer to IHANDLE if the next Position is not the end of the list.
80 Otherwise,NULL is returned.
84 MmGetNextLocateByRegisterNotify (
85 IN OUT LOCATE_POSITION
*Position
,
90 PROTOCOL_NOTIFY
*ProtNotify
;
91 PROTOCOL_INTERFACE
*Prot
;
96 ProtNotify
= Position
->SearchKey
;
99 // If this is the first request, get the next handle
101 if (ProtNotify
!= NULL
) {
102 ASSERT (ProtNotify
->Signature
== PROTOCOL_NOTIFY_SIGNATURE
);
103 Position
->SearchKey
= NULL
;
106 // If not at the end of the list, get the next handle
108 Link
= ProtNotify
->Position
->ForwardLink
;
109 if (Link
!= &ProtNotify
->Protocol
->Protocols
) {
110 Prot
= CR (Link
, PROTOCOL_INTERFACE
, ByProtocol
, PROTOCOL_INTERFACE_SIGNATURE
);
111 Handle
= Prot
->Handle
;
112 *Interface
= Prot
->Interface
;
120 Routine to get the next Handle, when you are searching for a given protocol.
122 @param Position Information about which Handle to seach for.
123 @param Interface Return the interface structure for the matching
126 @return An pointer to IHANDLE if the next Position is not the end of the list.
127 Otherwise,NULL is returned.
131 MmGetNextLocateByProtocol (
132 IN OUT LOCATE_POSITION
*Position
,
138 PROTOCOL_INTERFACE
*Prot
;
146 Link
= Position
->Position
->ForwardLink
;
147 Position
->Position
= Link
;
150 // If not at the end, return the handle
152 if (Link
== &Position
->ProtEntry
->Protocols
) {
160 Prot
= CR (Link
, PROTOCOL_INTERFACE
, ByProtocol
, PROTOCOL_INTERFACE_SIGNATURE
);
161 Handle
= Prot
->Handle
;
162 *Interface
= Prot
->Interface
;
165 // If this handle has not been returned this request, then
168 if (Handle
->LocateRequest
!= mEfiLocateHandleRequest
) {
169 Handle
->LocateRequest
= mEfiLocateHandleRequest
;
178 Return the first Protocol Interface that matches the Protocol GUID. If
179 Registration is passed in return a Protocol Instance that was just add
180 to the system. If Registration is NULL return the first Protocol Interface
183 @param Protocol The protocol to search for
184 @param Registration Optional Registration Key returned from
185 RegisterProtocolNotify()
186 @param Interface Return the Protocol interface (instance).
188 @retval EFI_SUCCESS If a valid Interface is returned
189 @retval EFI_INVALID_PARAMETER Invalid parameter
190 @retval EFI_NOT_FOUND Protocol interface not found
196 IN EFI_GUID
*Protocol
,
197 IN VOID
*Registration OPTIONAL
,
202 LOCATE_POSITION Position
;
203 PROTOCOL_NOTIFY
*ProtNotify
;
206 if ((Interface
== NULL
) || (Protocol
== NULL
)) {
207 return EFI_INVALID_PARAMETER
;
211 Status
= EFI_SUCCESS
;
214 // Set initial position
216 Position
.Protocol
= Protocol
;
217 Position
.SearchKey
= Registration
;
218 Position
.Position
= &gHandleList
;
220 mEfiLocateHandleRequest
+= 1;
222 if (Registration
== NULL
) {
224 // Look up the protocol entry and set the head pointer
226 Position
.ProtEntry
= MmFindProtocolEntry (Protocol
, FALSE
);
227 if (Position
.ProtEntry
== NULL
) {
228 return EFI_NOT_FOUND
;
231 Position
.Position
= &Position
.ProtEntry
->Protocols
;
233 Handle
= MmGetNextLocateByProtocol (&Position
, Interface
);
235 Handle
= MmGetNextLocateByRegisterNotify (&Position
, Interface
);
238 if (Handle
== NULL
) {
239 Status
= EFI_NOT_FOUND
;
240 } else if (Registration
!= NULL
) {
242 // If this is a search by register notify and a handle was
243 // returned, update the register notification position
245 ProtNotify
= Registration
;
246 ProtNotify
->Position
= ProtNotify
->Position
->ForwardLink
;
253 Locates the requested handle(s) and returns them in Buffer.
255 @param SearchType The type of search to perform to locate the
257 @param Protocol The protocol to search for
258 @param SearchKey Dependant on SearchType
259 @param BufferSize On input the size of Buffer. On output the
260 size of data returned.
261 @param Buffer The buffer to return the results in
263 @retval EFI_BUFFER_TOO_SMALL Buffer too small, required buffer size is
264 returned in BufferSize.
265 @retval EFI_INVALID_PARAMETER Invalid parameter
266 @retval EFI_SUCCESS Successfully found the requested handle(s) and
267 returns them in Buffer.
273 IN EFI_LOCATE_SEARCH_TYPE SearchType
,
274 IN EFI_GUID
*Protocol OPTIONAL
,
275 IN VOID
*SearchKey OPTIONAL
,
276 IN OUT UINTN
*BufferSize
,
277 OUT EFI_HANDLE
*Buffer
281 LOCATE_POSITION Position
;
282 PROTOCOL_NOTIFY
*ProtNotify
;
283 CORE_GET_NEXT GetNext
;
286 IHANDLE
**ResultBuffer
;
289 if (BufferSize
== NULL
) {
290 return EFI_INVALID_PARAMETER
;
293 if ((*BufferSize
> 0) && (Buffer
== NULL
)) {
294 return EFI_INVALID_PARAMETER
;
300 // Set initial position
302 Position
.Protocol
= Protocol
;
303 Position
.SearchKey
= SearchKey
;
304 Position
.Position
= &gHandleList
;
307 ResultBuffer
= (IHANDLE
**)Buffer
;
308 Status
= EFI_SUCCESS
;
311 // Get the search function based on type
313 switch (SearchType
) {
315 GetNext
= MmGetNextLocateAllHandles
;
318 case ByRegisterNotify
:
319 GetNext
= MmGetNextLocateByRegisterNotify
;
321 // Must have SearchKey for locate ByRegisterNotify
323 if (SearchKey
== NULL
) {
324 Status
= EFI_INVALID_PARAMETER
;
330 GetNext
= MmGetNextLocateByProtocol
;
331 if (Protocol
== NULL
) {
332 Status
= EFI_INVALID_PARAMETER
;
337 // Look up the protocol entry and set the head pointer
339 Position
.ProtEntry
= MmFindProtocolEntry (Protocol
, FALSE
);
340 if (Position
.ProtEntry
== NULL
) {
341 Status
= EFI_NOT_FOUND
;
345 Position
.Position
= &Position
.ProtEntry
->Protocols
;
349 Status
= EFI_INVALID_PARAMETER
;
353 if (EFI_ERROR (Status
)) {
358 // Enumerate out the matching handles
360 mEfiLocateHandleRequest
+= 1;
363 // Get the next handle. If no more handles, stop
365 Handle
= GetNext (&Position
, &Interface
);
366 if (NULL
== Handle
) {
371 // Increase the resulting buffer size, and if this handle
374 ResultSize
+= sizeof (Handle
);
375 if (ResultSize
<= *BufferSize
) {
376 *ResultBuffer
= Handle
;
382 // If the result is a zero length buffer, then there were no
385 if (ResultSize
== 0) {
386 Status
= EFI_NOT_FOUND
;
389 // Return the resulting buffer size. If it's larger than what
390 // was passed, then set the error code
392 if (ResultSize
> *BufferSize
) {
393 Status
= EFI_BUFFER_TOO_SMALL
;
396 *BufferSize
= ResultSize
;
398 if ((SearchType
== ByRegisterNotify
) && !EFI_ERROR (Status
)) {
399 ASSERT (SearchKey
!= NULL
);
401 // If this is a search by register notify and a handle was
402 // returned, update the register notification position
404 ProtNotify
= SearchKey
;
405 ProtNotify
->Position
= ProtNotify
->Position
->ForwardLink
;
413 Function returns an array of handles that support the requested protocol
414 in a buffer allocated from pool. This is a version of MmLocateHandle()
415 that allocates a buffer for the caller.
417 @param SearchType Specifies which handle(s) are to be returned.
418 @param Protocol Provides the protocol to search by. This
419 parameter is only valid for SearchType
421 @param SearchKey Supplies the search key depending on the
423 @param NumberHandles The number of handles returned in Buffer.
424 @param Buffer A pointer to the buffer to return the requested
425 array of handles that support Protocol.
427 @retval EFI_SUCCESS The result array of handles was returned.
428 @retval EFI_NOT_FOUND No handles match the search.
429 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the
431 @retval EFI_INVALID_PARAMETER One or more parameters are not valid.
436 MmLocateHandleBuffer (
437 IN EFI_LOCATE_SEARCH_TYPE SearchType
,
438 IN EFI_GUID
*Protocol OPTIONAL
,
439 IN VOID
*SearchKey OPTIONAL
,
440 IN OUT UINTN
*NumberHandles
,
441 OUT EFI_HANDLE
**Buffer
447 if (NumberHandles
== NULL
) {
448 return EFI_INVALID_PARAMETER
;
451 if (Buffer
== NULL
) {
452 return EFI_INVALID_PARAMETER
;
458 Status
= MmLocateHandle (
466 // LocateHandleBuffer() returns incorrect status code if SearchType is
469 // Add code to correctly handle expected errors from MmLocateHandle().
471 if (EFI_ERROR (Status
) && (Status
!= EFI_BUFFER_TOO_SMALL
)) {
472 if (Status
!= EFI_INVALID_PARAMETER
) {
473 Status
= EFI_NOT_FOUND
;
479 *Buffer
= AllocatePool (BufferSize
);
480 if (*Buffer
== NULL
) {
481 return EFI_OUT_OF_RESOURCES
;
484 Status
= MmLocateHandle (
492 *NumberHandles
= BufferSize
/ sizeof (EFI_HANDLE
);
493 if (EFI_ERROR (Status
)) {