2 Locate handle functions
4 Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
12 // ProtocolRequest - Last LocateHandle request ID
14 UINTN mEfiLocateHandleRequest
= 0;
17 // Internal prototypes
24 PROTOCOL_ENTRY
*ProtEntry
;
30 IN OUT LOCATE_POSITION
*Position
,
35 Routine to get the next Handle, when you are searching for all handles.
37 @param Position Information about which Handle to seach for.
38 @param Interface Return the interface structure for the matching
41 @return An pointer to IHANDLE if the next Position is not the end of the list.
42 Otherwise,NULL is returned.
46 SmmGetNextLocateAllHandles (
47 IN OUT LOCATE_POSITION
*Position
,
56 Position
->Position
= Position
->Position
->ForwardLink
;
59 // If not at the end of the list, get the handle
63 if (Position
->Position
!= &gHandleList
) {
64 Handle
= CR (Position
->Position
, IHANDLE
, AllHandles
, EFI_HANDLE_SIGNATURE
);
70 Routine to get the next Handle, when you are searching for register protocol
73 @param Position Information about which Handle to seach for.
74 @param Interface Return the interface structure for the matching
77 @return An pointer to IHANDLE if the next Position is not the end of the list.
78 Otherwise,NULL is returned.
82 SmmGetNextLocateByRegisterNotify (
83 IN OUT LOCATE_POSITION
*Position
,
88 PROTOCOL_NOTIFY
*ProtNotify
;
89 PROTOCOL_INTERFACE
*Prot
;
94 ProtNotify
= Position
->SearchKey
;
97 // If this is the first request, get the next handle
99 if (ProtNotify
!= NULL
) {
100 ASSERT(ProtNotify
->Signature
== PROTOCOL_NOTIFY_SIGNATURE
);
101 Position
->SearchKey
= NULL
;
104 // If not at the end of the list, get the next handle
106 Link
= ProtNotify
->Position
->ForwardLink
;
107 if (Link
!= &ProtNotify
->Protocol
->Protocols
) {
108 Prot
= CR (Link
, PROTOCOL_INTERFACE
, ByProtocol
, PROTOCOL_INTERFACE_SIGNATURE
);
109 Handle
= Prot
->Handle
;
110 *Interface
= Prot
->Interface
;
117 Routine to get the next Handle, when you are searching for a given protocol.
119 @param Position Information about which Handle to seach for.
120 @param Interface Return the interface structure for the matching
123 @return An pointer to IHANDLE if the next Position is not the end of the list.
124 Otherwise,NULL is returned.
128 SmmGetNextLocateByProtocol (
129 IN OUT LOCATE_POSITION
*Position
,
135 PROTOCOL_INTERFACE
*Prot
;
143 Link
= Position
->Position
->ForwardLink
;
144 Position
->Position
= Link
;
147 // If not at the end, return the handle
149 if (Link
== &Position
->ProtEntry
->Protocols
) {
157 Prot
= CR(Link
, PROTOCOL_INTERFACE
, ByProtocol
, PROTOCOL_INTERFACE_SIGNATURE
);
158 Handle
= Prot
->Handle
;
159 *Interface
= Prot
->Interface
;
162 // If this handle has not been returned this request, then
165 if (Handle
->LocateRequest
!= mEfiLocateHandleRequest
) {
166 Handle
->LocateRequest
= mEfiLocateHandleRequest
;
174 Return the first Protocol Interface that matches the Protocol GUID. If
175 Registration is pasased in return a Protocol Instance that was just add
176 to the system. If Retistration is NULL return the first Protocol Interface
179 @param Protocol The protocol to search for
180 @param Registration Optional Registration Key returned from
181 RegisterProtocolNotify()
182 @param Interface Return the Protocol interface (instance).
184 @retval EFI_SUCCESS If a valid Interface is returned
185 @retval EFI_INVALID_PARAMETER Invalid parameter
186 @retval EFI_NOT_FOUND Protocol interface not found
192 IN EFI_GUID
*Protocol
,
193 IN VOID
*Registration OPTIONAL
,
198 LOCATE_POSITION Position
;
199 PROTOCOL_NOTIFY
*ProtNotify
;
202 if ((Interface
== NULL
) || (Protocol
== NULL
)) {
203 return EFI_INVALID_PARAMETER
;
207 Status
= EFI_SUCCESS
;
210 // Set initial position
212 Position
.Protocol
= Protocol
;
213 Position
.SearchKey
= Registration
;
214 Position
.Position
= &gHandleList
;
216 mEfiLocateHandleRequest
+= 1;
218 if (Registration
== NULL
) {
220 // Look up the protocol entry and set the head pointer
222 Position
.ProtEntry
= SmmFindProtocolEntry (Protocol
, FALSE
);
223 if (Position
.ProtEntry
== NULL
) {
224 return EFI_NOT_FOUND
;
226 Position
.Position
= &Position
.ProtEntry
->Protocols
;
228 Handle
= SmmGetNextLocateByProtocol (&Position
, Interface
);
230 Handle
= SmmGetNextLocateByRegisterNotify (&Position
, Interface
);
233 if (Handle
== NULL
) {
234 Status
= EFI_NOT_FOUND
;
235 } else if (Registration
!= NULL
) {
237 // If this is a search by register notify and a handle was
238 // returned, update the register notification position
240 ProtNotify
= Registration
;
241 ProtNotify
->Position
= ProtNotify
->Position
->ForwardLink
;
248 Locates the requested handle(s) and returns them in Buffer.
250 @param SearchType The type of search to perform to locate the
252 @param Protocol The protocol to search for
253 @param SearchKey Dependant on SearchType
254 @param BufferSize On input the size of Buffer. On output the
255 size of data returned.
256 @param Buffer The buffer to return the results in
258 @retval EFI_BUFFER_TOO_SMALL Buffer too small, required buffer size is
259 returned in BufferSize.
260 @retval EFI_INVALID_PARAMETER Invalid parameter
261 @retval EFI_SUCCESS Successfully found the requested handle(s) and
262 returns them in Buffer.
268 IN EFI_LOCATE_SEARCH_TYPE SearchType
,
269 IN EFI_GUID
*Protocol OPTIONAL
,
270 IN VOID
*SearchKey OPTIONAL
,
271 IN OUT UINTN
*BufferSize
,
272 OUT EFI_HANDLE
*Buffer
276 LOCATE_POSITION Position
;
277 PROTOCOL_NOTIFY
*ProtNotify
;
278 CORE_GET_NEXT GetNext
;
281 IHANDLE
**ResultBuffer
;
284 if (BufferSize
== NULL
) {
285 return EFI_INVALID_PARAMETER
;
288 if ((*BufferSize
> 0) && (Buffer
== NULL
)) {
289 return EFI_INVALID_PARAMETER
;
295 // Set initial position
297 Position
.Protocol
= Protocol
;
298 Position
.SearchKey
= SearchKey
;
299 Position
.Position
= &gHandleList
;
302 ResultBuffer
= (IHANDLE
**) Buffer
;
303 Status
= EFI_SUCCESS
;
306 // Get the search function based on type
308 switch (SearchType
) {
310 GetNext
= SmmGetNextLocateAllHandles
;
313 case ByRegisterNotify
:
314 GetNext
= SmmGetNextLocateByRegisterNotify
;
316 // Must have SearchKey for locate ByRegisterNotify
318 if (SearchKey
== NULL
) {
319 Status
= EFI_INVALID_PARAMETER
;
324 GetNext
= SmmGetNextLocateByProtocol
;
325 if (Protocol
== NULL
) {
326 Status
= EFI_INVALID_PARAMETER
;
330 // Look up the protocol entry and set the head pointer
332 Position
.ProtEntry
= SmmFindProtocolEntry (Protocol
, FALSE
);
333 if (Position
.ProtEntry
== NULL
) {
334 Status
= EFI_NOT_FOUND
;
337 Position
.Position
= &Position
.ProtEntry
->Protocols
;
341 Status
= EFI_INVALID_PARAMETER
;
345 if (EFI_ERROR(Status
)) {
350 // Enumerate out the matching handles
352 mEfiLocateHandleRequest
+= 1;
355 // Get the next handle. If no more handles, stop
357 Handle
= GetNext (&Position
, &Interface
);
358 if (NULL
== Handle
) {
363 // Increase the resulting buffer size, and if this handle
366 ResultSize
+= sizeof(Handle
);
367 if (ResultSize
<= *BufferSize
) {
368 *ResultBuffer
= Handle
;
374 // If the result is a zero length buffer, then there were no
377 if (ResultSize
== 0) {
378 Status
= EFI_NOT_FOUND
;
381 // Return the resulting buffer size. If it's larger than what
382 // was passed, then set the error code
384 if (ResultSize
> *BufferSize
) {
385 Status
= EFI_BUFFER_TOO_SMALL
;
388 *BufferSize
= ResultSize
;
390 if (SearchType
== ByRegisterNotify
&& !EFI_ERROR(Status
)) {
391 ASSERT (SearchKey
!= NULL
);
393 // If this is a search by register notify and a handle was
394 // returned, update the register notification position
396 ProtNotify
= SearchKey
;
397 ProtNotify
->Position
= ProtNotify
->Position
->ForwardLink
;
405 Function returns an array of handles that support the requested protocol
406 in a buffer allocated from pool. This is a version of SmmLocateHandle()
407 that allocates a buffer for the caller.
409 @param SearchType Specifies which handle(s) are to be returned.
410 @param Protocol Provides the protocol to search by. This
411 parameter is only valid for SearchType
413 @param SearchKey Supplies the search key depending on the
415 @param NumberHandles The number of handles returned in Buffer.
416 @param Buffer A pointer to the buffer to return the requested
417 array of handles that support Protocol.
419 @retval EFI_SUCCESS The result array of handles was returned.
420 @retval EFI_NOT_FOUND No handles match the search.
421 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the
423 @retval EFI_INVALID_PARAMETER One or more parameters are not valid.
428 SmmLocateHandleBuffer (
429 IN EFI_LOCATE_SEARCH_TYPE SearchType
,
430 IN EFI_GUID
*Protocol OPTIONAL
,
431 IN VOID
*SearchKey OPTIONAL
,
432 IN OUT UINTN
*NumberHandles
,
433 OUT EFI_HANDLE
**Buffer
439 if (NumberHandles
== NULL
) {
440 return EFI_INVALID_PARAMETER
;
443 if (Buffer
== NULL
) {
444 return EFI_INVALID_PARAMETER
;
450 Status
= SmmLocateHandle (
458 // LocateHandleBuffer() returns incorrect status code if SearchType is
461 // Add code to correctly handle expected errors from SmmLocateHandle().
463 if (EFI_ERROR(Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
464 if (Status
!= EFI_INVALID_PARAMETER
) {
465 Status
= EFI_NOT_FOUND
;
470 *Buffer
= AllocatePool (BufferSize
);
471 if (*Buffer
== NULL
) {
472 return EFI_OUT_OF_RESOURCES
;
475 Status
= SmmLocateHandle (
483 *NumberHandles
= BufferSize
/ sizeof(EFI_HANDLE
);
484 if (EFI_ERROR(Status
)) {