2 Locate handle functions
4 Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.<BR>
5 Copyright (c) 2016 - 2018, 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
);
71 Routine to get the next Handle, when you are searching for register protocol
74 @param Position Information about which Handle to seach for.
75 @param Interface Return the interface structure for the matching
78 @return An pointer to IHANDLE if the next Position is not the end of the list.
79 Otherwise,NULL is returned.
83 MmGetNextLocateByRegisterNotify (
84 IN OUT LOCATE_POSITION
*Position
,
89 PROTOCOL_NOTIFY
*ProtNotify
;
90 PROTOCOL_INTERFACE
*Prot
;
95 ProtNotify
= Position
->SearchKey
;
98 // If this is the first request, get the next handle
100 if (ProtNotify
!= NULL
) {
101 ASSERT (ProtNotify
->Signature
== PROTOCOL_NOTIFY_SIGNATURE
);
102 Position
->SearchKey
= NULL
;
105 // If not at the end of the list, get the next handle
107 Link
= ProtNotify
->Position
->ForwardLink
;
108 if (Link
!= &ProtNotify
->Protocol
->Protocols
) {
109 Prot
= CR (Link
, PROTOCOL_INTERFACE
, ByProtocol
, PROTOCOL_INTERFACE_SIGNATURE
);
110 Handle
= Prot
->Handle
;
111 *Interface
= Prot
->Interface
;
118 Routine to get the next Handle, when you are searching for a given protocol.
120 @param Position Information about which Handle to seach for.
121 @param Interface Return the interface structure for the matching
124 @return An pointer to IHANDLE if the next Position is not the end of the list.
125 Otherwise,NULL is returned.
129 MmGetNextLocateByProtocol (
130 IN OUT LOCATE_POSITION
*Position
,
136 PROTOCOL_INTERFACE
*Prot
;
144 Link
= Position
->Position
->ForwardLink
;
145 Position
->Position
= Link
;
148 // If not at the end, return the handle
150 if (Link
== &Position
->ProtEntry
->Protocols
) {
158 Prot
= CR (Link
, PROTOCOL_INTERFACE
, ByProtocol
, PROTOCOL_INTERFACE_SIGNATURE
);
159 Handle
= Prot
->Handle
;
160 *Interface
= Prot
->Interface
;
163 // If this handle has not been returned this request, then
166 if (Handle
->LocateRequest
!= mEfiLocateHandleRequest
) {
167 Handle
->LocateRequest
= mEfiLocateHandleRequest
;
175 Return the first Protocol Interface that matches the Protocol GUID. If
176 Registration is pasased in return a Protocol Instance that was just add
177 to the system. If Retistration is NULL return the first Protocol Interface
180 @param Protocol The protocol to search for
181 @param Registration Optional Registration Key returned from
182 RegisterProtocolNotify()
183 @param Interface Return the Protocol interface (instance).
185 @retval EFI_SUCCESS If a valid Interface is returned
186 @retval EFI_INVALID_PARAMETER Invalid parameter
187 @retval EFI_NOT_FOUND Protocol interface not found
193 IN EFI_GUID
*Protocol
,
194 IN VOID
*Registration OPTIONAL
,
199 LOCATE_POSITION Position
;
200 PROTOCOL_NOTIFY
*ProtNotify
;
203 if ((Interface
== NULL
) || (Protocol
== NULL
)) {
204 return EFI_INVALID_PARAMETER
;
208 Status
= EFI_SUCCESS
;
211 // Set initial position
213 Position
.Protocol
= Protocol
;
214 Position
.SearchKey
= Registration
;
215 Position
.Position
= &gHandleList
;
217 mEfiLocateHandleRequest
+= 1;
219 if (Registration
== NULL
) {
221 // Look up the protocol entry and set the head pointer
223 Position
.ProtEntry
= MmFindProtocolEntry (Protocol
, FALSE
);
224 if (Position
.ProtEntry
== NULL
) {
225 return EFI_NOT_FOUND
;
227 Position
.Position
= &Position
.ProtEntry
->Protocols
;
229 Handle
= MmGetNextLocateByProtocol (&Position
, Interface
);
231 Handle
= MmGetNextLocateByRegisterNotify (&Position
, Interface
);
234 if (Handle
== NULL
) {
235 Status
= EFI_NOT_FOUND
;
236 } else if (Registration
!= NULL
) {
238 // If this is a search by register notify and a handle was
239 // returned, update the register notification position
241 ProtNotify
= Registration
;
242 ProtNotify
->Position
= ProtNotify
->Position
->ForwardLink
;
249 Locates the requested handle(s) and returns them in Buffer.
251 @param SearchType The type of search to perform to locate the
253 @param Protocol The protocol to search for
254 @param SearchKey Dependant on SearchType
255 @param BufferSize On input the size of Buffer. On output the
256 size of data returned.
257 @param Buffer The buffer to return the results in
259 @retval EFI_BUFFER_TOO_SMALL Buffer too small, required buffer size is
260 returned in BufferSize.
261 @retval EFI_INVALID_PARAMETER Invalid parameter
262 @retval EFI_SUCCESS Successfully found the requested handle(s) and
263 returns them in Buffer.
269 IN EFI_LOCATE_SEARCH_TYPE SearchType
,
270 IN EFI_GUID
*Protocol OPTIONAL
,
271 IN VOID
*SearchKey OPTIONAL
,
272 IN OUT UINTN
*BufferSize
,
273 OUT EFI_HANDLE
*Buffer
277 LOCATE_POSITION Position
;
278 PROTOCOL_NOTIFY
*ProtNotify
;
279 CORE_GET_NEXT GetNext
;
282 IHANDLE
**ResultBuffer
;
285 if (BufferSize
== NULL
) {
286 return EFI_INVALID_PARAMETER
;
289 if ((*BufferSize
> 0) && (Buffer
== NULL
)) {
290 return EFI_INVALID_PARAMETER
;
296 // Set initial position
298 Position
.Protocol
= Protocol
;
299 Position
.SearchKey
= SearchKey
;
300 Position
.Position
= &gHandleList
;
303 ResultBuffer
= (IHANDLE
**) Buffer
;
304 Status
= EFI_SUCCESS
;
307 // Get the search function based on type
309 switch (SearchType
) {
311 GetNext
= MmGetNextLocateAllHandles
;
314 case ByRegisterNotify
:
315 GetNext
= MmGetNextLocateByRegisterNotify
;
317 // Must have SearchKey for locate ByRegisterNotify
319 if (SearchKey
== NULL
) {
320 Status
= EFI_INVALID_PARAMETER
;
325 GetNext
= MmGetNextLocateByProtocol
;
326 if (Protocol
== NULL
) {
327 Status
= EFI_INVALID_PARAMETER
;
331 // Look up the protocol entry and set the head pointer
333 Position
.ProtEntry
= MmFindProtocolEntry (Protocol
, FALSE
);
334 if (Position
.ProtEntry
== NULL
) {
335 Status
= EFI_NOT_FOUND
;
338 Position
.Position
= &Position
.ProtEntry
->Protocols
;
342 Status
= EFI_INVALID_PARAMETER
;
346 if (EFI_ERROR (Status
)) {
351 // Enumerate out the matching handles
353 mEfiLocateHandleRequest
+= 1;
356 // Get the next handle. If no more handles, stop
358 Handle
= GetNext (&Position
, &Interface
);
359 if (NULL
== Handle
) {
364 // Increase the resulting buffer size, and if this handle
367 ResultSize
+= sizeof (Handle
);
368 if (ResultSize
<= *BufferSize
) {
369 *ResultBuffer
= Handle
;
375 // If the result is a zero length buffer, then there were no
378 if (ResultSize
== 0) {
379 Status
= EFI_NOT_FOUND
;
382 // Return the resulting buffer size. If it's larger than what
383 // was passed, then set the error code
385 if (ResultSize
> *BufferSize
) {
386 Status
= EFI_BUFFER_TOO_SMALL
;
389 *BufferSize
= ResultSize
;
391 if (SearchType
== ByRegisterNotify
&& !EFI_ERROR (Status
)) {
392 ASSERT (SearchKey
!= NULL
);
394 // If this is a search by register notify and a handle was
395 // returned, update the register notification position
397 ProtNotify
= SearchKey
;
398 ProtNotify
->Position
= ProtNotify
->Position
->ForwardLink
;
406 Function returns an array of handles that support the requested protocol
407 in a buffer allocated from pool. This is a version of MmLocateHandle()
408 that allocates a buffer for the caller.
410 @param SearchType Specifies which handle(s) are to be returned.
411 @param Protocol Provides the protocol to search by. This
412 parameter is only valid for SearchType
414 @param SearchKey Supplies the search key depending on the
416 @param NumberHandles The number of handles returned in Buffer.
417 @param Buffer A pointer to the buffer to return the requested
418 array of handles that support Protocol.
420 @retval EFI_SUCCESS The result array of handles was returned.
421 @retval EFI_NOT_FOUND No handles match the search.
422 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the
424 @retval EFI_INVALID_PARAMETER One or more parameters are not valid.
429 MmLocateHandleBuffer (
430 IN EFI_LOCATE_SEARCH_TYPE SearchType
,
431 IN EFI_GUID
*Protocol OPTIONAL
,
432 IN VOID
*SearchKey OPTIONAL
,
433 IN OUT UINTN
*NumberHandles
,
434 OUT EFI_HANDLE
**Buffer
440 if (NumberHandles
== NULL
) {
441 return EFI_INVALID_PARAMETER
;
444 if (Buffer
== NULL
) {
445 return EFI_INVALID_PARAMETER
;
451 Status
= MmLocateHandle (
459 // LocateHandleBuffer() returns incorrect status code if SearchType is
462 // Add code to correctly handle expected errors from MmLocateHandle().
464 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
465 if (Status
!= EFI_INVALID_PARAMETER
) {
466 Status
= EFI_NOT_FOUND
;
471 *Buffer
= AllocatePool (BufferSize
);
472 if (*Buffer
== NULL
) {
473 return EFI_OUT_OF_RESOURCES
;
476 Status
= MmLocateHandle (
484 *NumberHandles
= BufferSize
/ sizeof(EFI_HANDLE
);
485 if (EFI_ERROR (Status
)) {