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 This program and the accompanying materials are licensed and made available
7 under the terms and conditions of the BSD License which accompanies this
8 distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "StandaloneMmCore.h"
19 // ProtocolRequest - Last LocateHandle request ID
21 UINTN mEfiLocateHandleRequest
= 0;
24 // Internal prototypes
31 PROTOCOL_ENTRY
*ProtEntry
;
37 IN OUT LOCATE_POSITION
*Position
,
42 Routine to get the next Handle, when you are searching for all handles.
44 @param Position Information about which Handle to seach for.
45 @param Interface Return the interface structure for the matching
48 @return An pointer to IHANDLE if the next Position is not the end of the list.
49 Otherwise,NULL is returned.
53 MmGetNextLocateAllHandles (
54 IN OUT LOCATE_POSITION
*Position
,
63 Position
->Position
= Position
->Position
->ForwardLink
;
66 // If not at the end of the list, get the handle
70 if (Position
->Position
!= &gHandleList
) {
71 Handle
= CR (Position
->Position
, IHANDLE
, AllHandles
, EFI_HANDLE_SIGNATURE
);
77 Routine to get the next Handle, when you are searching for register protocol
80 @param Position Information about which Handle to seach for.
81 @param Interface Return the interface structure for the matching
84 @return An pointer to IHANDLE if the next Position is not the end of the list.
85 Otherwise,NULL is returned.
89 MmGetNextLocateByRegisterNotify (
90 IN OUT LOCATE_POSITION
*Position
,
95 PROTOCOL_NOTIFY
*ProtNotify
;
96 PROTOCOL_INTERFACE
*Prot
;
101 ProtNotify
= Position
->SearchKey
;
104 // If this is the first request, get the next handle
106 if (ProtNotify
!= NULL
) {
107 ASSERT (ProtNotify
->Signature
== PROTOCOL_NOTIFY_SIGNATURE
);
108 Position
->SearchKey
= NULL
;
111 // If not at the end of the list, get the next handle
113 Link
= ProtNotify
->Position
->ForwardLink
;
114 if (Link
!= &ProtNotify
->Protocol
->Protocols
) {
115 Prot
= CR (Link
, PROTOCOL_INTERFACE
, ByProtocol
, PROTOCOL_INTERFACE_SIGNATURE
);
116 Handle
= Prot
->Handle
;
117 *Interface
= Prot
->Interface
;
124 Routine to get the next Handle, when you are searching for a given protocol.
126 @param Position Information about which Handle to seach for.
127 @param Interface Return the interface structure for the matching
130 @return An pointer to IHANDLE if the next Position is not the end of the list.
131 Otherwise,NULL is returned.
135 MmGetNextLocateByProtocol (
136 IN OUT LOCATE_POSITION
*Position
,
142 PROTOCOL_INTERFACE
*Prot
;
150 Link
= Position
->Position
->ForwardLink
;
151 Position
->Position
= Link
;
154 // If not at the end, return the handle
156 if (Link
== &Position
->ProtEntry
->Protocols
) {
164 Prot
= CR (Link
, PROTOCOL_INTERFACE
, ByProtocol
, PROTOCOL_INTERFACE_SIGNATURE
);
165 Handle
= Prot
->Handle
;
166 *Interface
= Prot
->Interface
;
169 // If this handle has not been returned this request, then
172 if (Handle
->LocateRequest
!= mEfiLocateHandleRequest
) {
173 Handle
->LocateRequest
= mEfiLocateHandleRequest
;
181 Return the first Protocol Interface that matches the Protocol GUID. If
182 Registration is pasased in return a Protocol Instance that was just add
183 to the system. If Retistration is NULL return the first Protocol Interface
186 @param Protocol The protocol to search for
187 @param Registration Optional Registration Key returned from
188 RegisterProtocolNotify()
189 @param Interface Return the Protocol interface (instance).
191 @retval EFI_SUCCESS If a valid Interface is returned
192 @retval EFI_INVALID_PARAMETER Invalid parameter
193 @retval EFI_NOT_FOUND Protocol interface not found
199 IN EFI_GUID
*Protocol
,
200 IN VOID
*Registration OPTIONAL
,
205 LOCATE_POSITION Position
;
206 PROTOCOL_NOTIFY
*ProtNotify
;
209 if ((Interface
== NULL
) || (Protocol
== NULL
)) {
210 return EFI_INVALID_PARAMETER
;
214 Status
= EFI_SUCCESS
;
217 // Set initial position
219 Position
.Protocol
= Protocol
;
220 Position
.SearchKey
= Registration
;
221 Position
.Position
= &gHandleList
;
223 mEfiLocateHandleRequest
+= 1;
225 if (Registration
== NULL
) {
227 // Look up the protocol entry and set the head pointer
229 Position
.ProtEntry
= MmFindProtocolEntry (Protocol
, FALSE
);
230 if (Position
.ProtEntry
== NULL
) {
231 return EFI_NOT_FOUND
;
233 Position
.Position
= &Position
.ProtEntry
->Protocols
;
235 Handle
= MmGetNextLocateByProtocol (&Position
, Interface
);
237 Handle
= MmGetNextLocateByRegisterNotify (&Position
, Interface
);
240 if (Handle
== NULL
) {
241 Status
= EFI_NOT_FOUND
;
242 } else if (Registration
!= NULL
) {
244 // If this is a search by register notify and a handle was
245 // returned, update the register notification position
247 ProtNotify
= Registration
;
248 ProtNotify
->Position
= ProtNotify
->Position
->ForwardLink
;
255 Locates the requested handle(s) and returns them in Buffer.
257 @param SearchType The type of search to perform to locate the
259 @param Protocol The protocol to search for
260 @param SearchKey Dependant on SearchType
261 @param BufferSize On input the size of Buffer. On output the
262 size of data returned.
263 @param Buffer The buffer to return the results in
265 @retval EFI_BUFFER_TOO_SMALL Buffer too small, required buffer size is
266 returned in BufferSize.
267 @retval EFI_INVALID_PARAMETER Invalid parameter
268 @retval EFI_SUCCESS Successfully found the requested handle(s) and
269 returns them in Buffer.
275 IN EFI_LOCATE_SEARCH_TYPE SearchType
,
276 IN EFI_GUID
*Protocol OPTIONAL
,
277 IN VOID
*SearchKey OPTIONAL
,
278 IN OUT UINTN
*BufferSize
,
279 OUT EFI_HANDLE
*Buffer
283 LOCATE_POSITION Position
;
284 PROTOCOL_NOTIFY
*ProtNotify
;
285 CORE_GET_NEXT GetNext
;
288 IHANDLE
**ResultBuffer
;
291 if (BufferSize
== NULL
) {
292 return EFI_INVALID_PARAMETER
;
295 if ((*BufferSize
> 0) && (Buffer
== NULL
)) {
296 return EFI_INVALID_PARAMETER
;
302 // Set initial position
304 Position
.Protocol
= Protocol
;
305 Position
.SearchKey
= SearchKey
;
306 Position
.Position
= &gHandleList
;
309 ResultBuffer
= (IHANDLE
**) Buffer
;
310 Status
= EFI_SUCCESS
;
313 // Get the search function based on type
315 switch (SearchType
) {
317 GetNext
= MmGetNextLocateAllHandles
;
320 case ByRegisterNotify
:
321 GetNext
= MmGetNextLocateByRegisterNotify
;
323 // Must have SearchKey for locate ByRegisterNotify
325 if (SearchKey
== NULL
) {
326 Status
= EFI_INVALID_PARAMETER
;
331 GetNext
= MmGetNextLocateByProtocol
;
332 if (Protocol
== NULL
) {
333 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
;
344 Position
.Position
= &Position
.ProtEntry
->Protocols
;
348 Status
= EFI_INVALID_PARAMETER
;
352 if (EFI_ERROR (Status
)) {
357 // Enumerate out the matching handles
359 mEfiLocateHandleRequest
+= 1;
362 // Get the next handle. If no more handles, stop
364 Handle
= GetNext (&Position
, &Interface
);
365 if (NULL
== Handle
) {
370 // Increase the resulting buffer size, and if this handle
373 ResultSize
+= sizeof (Handle
);
374 if (ResultSize
<= *BufferSize
) {
375 *ResultBuffer
= Handle
;
381 // If the result is a zero length buffer, then there were no
384 if (ResultSize
== 0) {
385 Status
= EFI_NOT_FOUND
;
388 // Return the resulting buffer size. If it's larger than what
389 // was passed, then set the error code
391 if (ResultSize
> *BufferSize
) {
392 Status
= EFI_BUFFER_TOO_SMALL
;
395 *BufferSize
= ResultSize
;
397 if (SearchType
== ByRegisterNotify
&& !EFI_ERROR (Status
)) {
398 ASSERT (SearchKey
!= NULL
);
400 // If this is a search by register notify and a handle was
401 // returned, update the register notification position
403 ProtNotify
= SearchKey
;
404 ProtNotify
->Position
= ProtNotify
->Position
->ForwardLink
;
412 Function returns an array of handles that support the requested protocol
413 in a buffer allocated from pool. This is a version of MmLocateHandle()
414 that allocates a buffer for the caller.
416 @param SearchType Specifies which handle(s) are to be returned.
417 @param Protocol Provides the protocol to search by. This
418 parameter is only valid for SearchType
420 @param SearchKey Supplies the search key depending on the
422 @param NumberHandles The number of handles returned in Buffer.
423 @param Buffer A pointer to the buffer to return the requested
424 array of handles that support Protocol.
426 @retval EFI_SUCCESS The result array of handles was returned.
427 @retval EFI_NOT_FOUND No handles match the search.
428 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the
430 @retval EFI_INVALID_PARAMETER One or more parameters are not valid.
435 MmLocateHandleBuffer (
436 IN EFI_LOCATE_SEARCH_TYPE SearchType
,
437 IN EFI_GUID
*Protocol OPTIONAL
,
438 IN VOID
*SearchKey OPTIONAL
,
439 IN OUT UINTN
*NumberHandles
,
440 OUT EFI_HANDLE
**Buffer
446 if (NumberHandles
== NULL
) {
447 return EFI_INVALID_PARAMETER
;
450 if (Buffer
== NULL
) {
451 return EFI_INVALID_PARAMETER
;
457 Status
= MmLocateHandle (
465 // LocateHandleBuffer() returns incorrect status code if SearchType is
468 // Add code to correctly handle expected errors from MmLocateHandle().
470 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
471 if (Status
!= EFI_INVALID_PARAMETER
) {
472 Status
= EFI_NOT_FOUND
;
477 *Buffer
= AllocatePool (BufferSize
);
478 if (*Buffer
== NULL
) {
479 return EFI_OUT_OF_RESOURCES
;
482 Status
= MmLocateHandle (
490 *NumberHandles
= BufferSize
/ sizeof(EFI_HANDLE
);
491 if (EFI_ERROR (Status
)) {