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 search 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
);
71 Routine to get the next Handle, when you are searching for register protocol
74 @param Position Information about which Handle to search 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 SmmGetNextLocateByRegisterNotify (
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
;
119 Routine to get the next Handle, when you are searching for a given protocol.
121 @param Position Information about which Handle to search for.
122 @param Interface Return the interface structure for the matching
125 @return An pointer to IHANDLE if the next Position is not the end of the list.
126 Otherwise,NULL is returned.
130 SmmGetNextLocateByProtocol (
131 IN OUT LOCATE_POSITION
*Position
,
137 PROTOCOL_INTERFACE
*Prot
;
145 Link
= Position
->Position
->ForwardLink
;
146 Position
->Position
= Link
;
149 // If not at the end, return the handle
151 if (Link
== &Position
->ProtEntry
->Protocols
) {
159 Prot
= CR (Link
, PROTOCOL_INTERFACE
, ByProtocol
, PROTOCOL_INTERFACE_SIGNATURE
);
160 Handle
= Prot
->Handle
;
161 *Interface
= Prot
->Interface
;
164 // If this handle has not been returned this request, then
167 if (Handle
->LocateRequest
!= mEfiLocateHandleRequest
) {
168 Handle
->LocateRequest
= mEfiLocateHandleRequest
;
177 Return the first Protocol Interface that matches the Protocol GUID. If
178 Registration is pasased in return a Protocol Instance that was just add
179 to the system. If Registration is NULL return the first Protocol Interface
182 @param Protocol The protocol to search for
183 @param Registration Optional Registration Key returned from
184 RegisterProtocolNotify()
185 @param Interface Return the Protocol interface (instance).
187 @retval EFI_SUCCESS If a valid Interface is returned
188 @retval EFI_INVALID_PARAMETER Invalid parameter
189 @retval EFI_NOT_FOUND Protocol interface not found
195 IN EFI_GUID
*Protocol
,
196 IN VOID
*Registration OPTIONAL
,
201 LOCATE_POSITION Position
;
202 PROTOCOL_NOTIFY
*ProtNotify
;
205 if ((Interface
== NULL
) || (Protocol
== NULL
)) {
206 return EFI_INVALID_PARAMETER
;
210 Status
= EFI_SUCCESS
;
213 // Set initial position
215 Position
.Protocol
= Protocol
;
216 Position
.SearchKey
= Registration
;
217 Position
.Position
= &gHandleList
;
219 mEfiLocateHandleRequest
+= 1;
221 if (Registration
== NULL
) {
223 // Look up the protocol entry and set the head pointer
225 Position
.ProtEntry
= SmmFindProtocolEntry (Protocol
, FALSE
);
226 if (Position
.ProtEntry
== NULL
) {
227 return EFI_NOT_FOUND
;
230 Position
.Position
= &Position
.ProtEntry
->Protocols
;
232 Handle
= SmmGetNextLocateByProtocol (&Position
, Interface
);
234 Handle
= SmmGetNextLocateByRegisterNotify (&Position
, Interface
);
237 if (Handle
== NULL
) {
238 Status
= EFI_NOT_FOUND
;
239 } else if (Registration
!= NULL
) {
241 // If this is a search by register notify and a handle was
242 // returned, update the register notification position
244 ProtNotify
= Registration
;
245 ProtNotify
->Position
= ProtNotify
->Position
->ForwardLink
;
252 Locates the requested handle(s) and returns them in Buffer.
254 @param SearchType The type of search to perform to locate the
256 @param Protocol The protocol to search for
257 @param SearchKey Dependant on SearchType
258 @param BufferSize On input the size of Buffer. On output the
259 size of data returned.
260 @param Buffer The buffer to return the results in
262 @retval EFI_BUFFER_TOO_SMALL Buffer too small, required buffer size is
263 returned in BufferSize.
264 @retval EFI_INVALID_PARAMETER Invalid parameter
265 @retval EFI_SUCCESS Successfully found the requested handle(s) and
266 returns them in Buffer.
272 IN EFI_LOCATE_SEARCH_TYPE SearchType
,
273 IN EFI_GUID
*Protocol OPTIONAL
,
274 IN VOID
*SearchKey OPTIONAL
,
275 IN OUT UINTN
*BufferSize
,
276 OUT EFI_HANDLE
*Buffer
280 LOCATE_POSITION Position
;
281 PROTOCOL_NOTIFY
*ProtNotify
;
282 CORE_GET_NEXT GetNext
;
285 IHANDLE
**ResultBuffer
;
288 if (BufferSize
== NULL
) {
289 return EFI_INVALID_PARAMETER
;
292 if ((*BufferSize
> 0) && (Buffer
== NULL
)) {
293 return EFI_INVALID_PARAMETER
;
299 // Set initial position
301 Position
.Protocol
= Protocol
;
302 Position
.SearchKey
= SearchKey
;
303 Position
.Position
= &gHandleList
;
306 ResultBuffer
= (IHANDLE
**)Buffer
;
307 Status
= EFI_SUCCESS
;
310 // Get the search function based on type
312 switch (SearchType
) {
314 GetNext
= SmmGetNextLocateAllHandles
;
317 case ByRegisterNotify
:
318 GetNext
= SmmGetNextLocateByRegisterNotify
;
320 // Must have SearchKey for locate ByRegisterNotify
322 if (SearchKey
== NULL
) {
323 Status
= EFI_INVALID_PARAMETER
;
329 GetNext
= SmmGetNextLocateByProtocol
;
330 if (Protocol
== NULL
) {
331 Status
= EFI_INVALID_PARAMETER
;
336 // Look up the protocol entry and set the head pointer
338 Position
.ProtEntry
= SmmFindProtocolEntry (Protocol
, FALSE
);
339 if (Position
.ProtEntry
== NULL
) {
340 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 SmmLocateHandle()
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 SmmLocateHandleBuffer (
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
= SmmLocateHandle (
465 // LocateHandleBuffer() returns incorrect status code if SearchType is
468 // Add code to correctly handle expected errors from SmmLocateHandle().
470 if (EFI_ERROR (Status
) && (Status
!= EFI_BUFFER_TOO_SMALL
)) {
471 if (Status
!= EFI_INVALID_PARAMETER
) {
472 Status
= EFI_NOT_FOUND
;
478 *Buffer
= AllocatePool (BufferSize
);
479 if (*Buffer
== NULL
) {
480 return EFI_OUT_OF_RESOURCES
;
483 Status
= SmmLocateHandle (
491 *NumberHandles
= BufferSize
/ sizeof (EFI_HANDLE
);
492 if (EFI_ERROR (Status
)) {