2 Locate handle functions
4 Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials are licensed and made available
6 under the terms and conditions of the BSD License which accompanies this
7 distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "PiSmmCore.h"
18 // ProtocolRequest - Last LocateHandle request ID
20 UINTN mEfiLocateHandleRequest
= 0;
23 // Internal prototypes
30 PROTOCOL_ENTRY
*ProtEntry
;
36 IN OUT LOCATE_POSITION
*Position
,
41 Routine to get the next Handle, when you are searching for all handles.
43 @param Position Information about which Handle to seach for.
44 @param Interface Return the interface structure for the matching
47 @return An pointer to IHANDLE if the next Position is not the end of the list.
48 Otherwise,NULL is returned.
52 SmmGetNextLocateAllHandles (
53 IN OUT LOCATE_POSITION
*Position
,
62 Position
->Position
= Position
->Position
->ForwardLink
;
65 // If not at the end of the list, get the handle
69 if (Position
->Position
!= &gHandleList
) {
70 Handle
= CR (Position
->Position
, IHANDLE
, AllHandles
, EFI_HANDLE_SIGNATURE
);
76 Routine to get the next Handle, when you are searching for register protocol
79 @param Position Information about which Handle to seach for.
80 @param Interface Return the interface structure for the matching
83 @return An pointer to IHANDLE if the next Position is not the end of the list.
84 Otherwise,NULL is returned.
88 SmmGetNextLocateByRegisterNotify (
89 IN OUT LOCATE_POSITION
*Position
,
94 PROTOCOL_NOTIFY
*ProtNotify
;
95 PROTOCOL_INTERFACE
*Prot
;
100 ProtNotify
= Position
->SearchKey
;
103 // If this is the first request, get the next handle
105 if (ProtNotify
!= NULL
) {
106 ASSERT(ProtNotify
->Signature
== PROTOCOL_NOTIFY_SIGNATURE
);
107 Position
->SearchKey
= NULL
;
110 // If not at the end of the list, get the next handle
112 Link
= ProtNotify
->Position
->ForwardLink
;
113 if (Link
!= &ProtNotify
->Protocol
->Protocols
) {
114 Prot
= CR (Link
, PROTOCOL_INTERFACE
, ByProtocol
, PROTOCOL_INTERFACE_SIGNATURE
);
115 Handle
= Prot
->Handle
;
116 *Interface
= Prot
->Interface
;
123 Routine to get the next Handle, when you are searching for a given protocol.
125 @param Position Information about which Handle to seach for.
126 @param Interface Return the interface structure for the matching
129 @return An pointer to IHANDLE if the next Position is not the end of the list.
130 Otherwise,NULL is returned.
134 SmmGetNextLocateByProtocol (
135 IN OUT LOCATE_POSITION
*Position
,
141 PROTOCOL_INTERFACE
*Prot
;
149 Link
= Position
->Position
->ForwardLink
;
150 Position
->Position
= Link
;
153 // If not at the end, return the handle
155 if (Link
== &Position
->ProtEntry
->Protocols
) {
163 Prot
= CR(Link
, PROTOCOL_INTERFACE
, ByProtocol
, PROTOCOL_INTERFACE_SIGNATURE
);
164 Handle
= Prot
->Handle
;
165 *Interface
= Prot
->Interface
;
168 // If this handle has not been returned this request, then
171 if (Handle
->LocateRequest
!= mEfiLocateHandleRequest
) {
172 Handle
->LocateRequest
= mEfiLocateHandleRequest
;
180 Return the first Protocol Interface that matches the Protocol GUID. If
181 Registration is pasased in return a Protocol Instance that was just add
182 to the system. If Retistration is NULL return the first Protocol Interface
185 @param Protocol The protocol to search for
186 @param Registration Optional Registration Key returned from
187 RegisterProtocolNotify()
188 @param Interface Return the Protocol interface (instance).
190 @retval EFI_SUCCESS If a valid Interface is returned
191 @retval EFI_INVALID_PARAMETER Invalid parameter
192 @retval EFI_NOT_FOUND Protocol interface not found
198 IN EFI_GUID
*Protocol
,
199 IN VOID
*Registration OPTIONAL
,
204 LOCATE_POSITION Position
;
205 PROTOCOL_NOTIFY
*ProtNotify
;
208 if (Interface
== NULL
) {
209 return EFI_INVALID_PARAMETER
;
212 if (Protocol
== NULL
) {
213 return EFI_NOT_FOUND
;
217 Status
= EFI_SUCCESS
;
220 // Set initial position
222 Position
.Protocol
= Protocol
;
223 Position
.SearchKey
= Registration
;
224 Position
.Position
= &gHandleList
;
226 mEfiLocateHandleRequest
+= 1;
228 if (Registration
== NULL
) {
230 // Look up the protocol entry and set the head pointer
232 Position
.ProtEntry
= SmmFindProtocolEntry (Protocol
, FALSE
);
233 if (Position
.ProtEntry
== NULL
) {
234 return EFI_NOT_FOUND
;
236 Position
.Position
= &Position
.ProtEntry
->Protocols
;
238 Handle
= SmmGetNextLocateByProtocol (&Position
, Interface
);
240 Handle
= SmmGetNextLocateByRegisterNotify (&Position
, Interface
);
243 if (Handle
== NULL
) {
244 Status
= EFI_NOT_FOUND
;
245 } else if (Registration
!= NULL
) {
247 // If this is a search by register notify and a handle was
248 // returned, update the register notification position
250 ProtNotify
= Registration
;
251 ProtNotify
->Position
= ProtNotify
->Position
->ForwardLink
;
258 Locates the requested handle(s) and returns them in Buffer.
260 @param SearchType The type of search to perform to locate the
262 @param Protocol The protocol to search for
263 @param SearchKey Dependant on SearchType
264 @param BufferSize On input the size of Buffer. On output the
265 size of data returned.
266 @param Buffer The buffer to return the results in
268 @retval EFI_BUFFER_TOO_SMALL Buffer too small, required buffer size is
269 returned in BufferSize.
270 @retval EFI_INVALID_PARAMETER Invalid parameter
271 @retval EFI_SUCCESS Successfully found the requested handle(s) and
272 returns them in Buffer.
278 IN EFI_LOCATE_SEARCH_TYPE SearchType
,
279 IN EFI_GUID
*Protocol OPTIONAL
,
280 IN VOID
*SearchKey OPTIONAL
,
281 IN OUT UINTN
*BufferSize
,
282 OUT EFI_HANDLE
*Buffer
286 LOCATE_POSITION Position
;
287 PROTOCOL_NOTIFY
*ProtNotify
;
288 CORE_GET_NEXT GetNext
;
291 IHANDLE
**ResultBuffer
;
294 if (BufferSize
== NULL
) {
295 return EFI_INVALID_PARAMETER
;
298 if ((*BufferSize
> 0) && (Buffer
== NULL
)) {
299 return EFI_INVALID_PARAMETER
;
305 // Set initial position
307 Position
.Protocol
= Protocol
;
308 Position
.SearchKey
= SearchKey
;
309 Position
.Position
= &gHandleList
;
312 ResultBuffer
= (IHANDLE
**) Buffer
;
313 Status
= EFI_SUCCESS
;
316 // Get the search function based on type
318 switch (SearchType
) {
320 GetNext
= SmmGetNextLocateAllHandles
;
323 case ByRegisterNotify
:
324 GetNext
= SmmGetNextLocateByRegisterNotify
;
326 // Must have SearchKey for locate ByRegisterNotify
328 if (SearchKey
== NULL
) {
329 Status
= EFI_INVALID_PARAMETER
;
334 GetNext
= SmmGetNextLocateByProtocol
;
335 if (Protocol
== NULL
) {
336 Status
= EFI_INVALID_PARAMETER
;
340 // Look up the protocol entry and set the head pointer
342 Position
.ProtEntry
= SmmFindProtocolEntry (Protocol
, FALSE
);
343 if (Position
.ProtEntry
== NULL
) {
344 Status
= EFI_NOT_FOUND
;
347 Position
.Position
= &Position
.ProtEntry
->Protocols
;
351 Status
= EFI_INVALID_PARAMETER
;
355 if (EFI_ERROR(Status
)) {
360 // Enumerate out the matching handles
362 mEfiLocateHandleRequest
+= 1;
365 // Get the next handle. If no more handles, stop
367 Handle
= GetNext (&Position
, &Interface
);
368 if (NULL
== Handle
) {
373 // Increase the resulting buffer size, and if this handle
376 ResultSize
+= sizeof(Handle
);
377 if (ResultSize
<= *BufferSize
) {
378 *ResultBuffer
= Handle
;
384 // If the result is a zero length buffer, then there were no
387 if (ResultSize
== 0) {
388 Status
= EFI_NOT_FOUND
;
391 // Return the resulting buffer size. If it's larger than what
392 // was passed, then set the error code
394 if (ResultSize
> *BufferSize
) {
395 Status
= EFI_BUFFER_TOO_SMALL
;
398 *BufferSize
= ResultSize
;
400 if (SearchType
== ByRegisterNotify
&& !EFI_ERROR(Status
)) {
401 ASSERT (SearchKey
!= NULL
);
403 // If this is a search by register notify and a handle was
404 // returned, update the register notification position
406 ProtNotify
= SearchKey
;
407 ProtNotify
->Position
= ProtNotify
->Position
->ForwardLink
;
415 Function returns an array of handles that support the requested protocol
416 in a buffer allocated from pool. This is a version of SmmLocateHandle()
417 that allocates a buffer for the caller.
419 @param SearchType Specifies which handle(s) are to be returned.
420 @param Protocol Provides the protocol to search by. This
421 parameter is only valid for SearchType
423 @param SearchKey Supplies the search key depending on the
425 @param NumberHandles The number of handles returned in Buffer.
426 @param Buffer A pointer to the buffer to return the requested
427 array of handles that support Protocol.
429 @retval EFI_SUCCESS The result array of handles was returned.
430 @retval EFI_NOT_FOUND No handles match the search.
431 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the
433 @retval EFI_INVALID_PARAMETER One or more paramters are not valid.
438 SmmLocateHandleBuffer (
439 IN EFI_LOCATE_SEARCH_TYPE SearchType
,
440 IN EFI_GUID
*Protocol OPTIONAL
,
441 IN VOID
*SearchKey OPTIONAL
,
442 IN OUT UINTN
*NumberHandles
,
443 OUT EFI_HANDLE
**Buffer
449 if (NumberHandles
== NULL
) {
450 return EFI_INVALID_PARAMETER
;
453 if (Buffer
== NULL
) {
454 return EFI_INVALID_PARAMETER
;
460 Status
= SmmLocateHandle (
468 // LocateHandleBuffer() returns incorrect status code if SearchType is
471 // Add code to correctly handle expected errors from SmmLocateHandle().
473 if (EFI_ERROR(Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
474 if (Status
!= EFI_INVALID_PARAMETER
) {
475 Status
= EFI_NOT_FOUND
;
480 *Buffer
= AllocatePool (BufferSize
);
481 if (*Buffer
== NULL
) {
482 return EFI_OUT_OF_RESOURCES
;
485 Status
= SmmLocateHandle (
493 *NumberHandles
= BufferSize
/ sizeof(EFI_HANDLE
);
494 if (EFI_ERROR(Status
)) {