3 Locate handle functions
5 Copyright (c) 2006 - 2008, Intel Corporation
6 All rights reserved. This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this 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.
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 @retval IHANDLE An IHANDLE is returned if the next Position is
49 not the end of the list. A NULL_HANDLE is
50 returned if it's the end of the list.
55 CoreGetNextLocateAllHandles (
56 IN OUT LOCATE_POSITION
*Position
,
61 Routine to get the next Handle, when you are searching for register protocol
64 @param Position Information about which Handle to seach for.
65 @param Interface Return the interface structure for the matching
68 @retval IHANDLE An IHANDLE is returned if the next Position is
69 not the end of the list. A NULL_HANDLE is
70 returned if it's the end of the list.
75 CoreGetNextLocateByRegisterNotify (
76 IN OUT LOCATE_POSITION
*Position
,
81 Routine to get the next Handle, when you are searching for a given protocol.
83 @param Position Information about which Handle to seach for.
84 @param Interface Return the interface structure for the matching
87 @retval IHANDLE An IHANDLE is returned if the next Position is
88 not the end of the list. A NULL_HANDLE is
89 returned if it's the end of the list.
94 CoreGetNextLocateByProtocol (
95 IN OUT LOCATE_POSITION
*Position
,
101 Locates the requested handle(s) and returns them in Buffer.
103 @param SearchType The type of search to perform to locate the
105 @param Protocol The protocol to search for
106 @param SearchKey Dependant on SearchType
107 @param BufferSize On input the size of Buffer. On output the
108 size of data returned.
109 @param Buffer The buffer to return the results in
111 @retval EFI_BUFFER_TOO_SMALL Buffer too small, required buffer size is
112 returned in BufferSize.
113 @retval EFI_INVALID_PARAMETER Invalid parameter
114 @retval EFI_SUCCESS Successfully found the requested handle(s) and
115 returns them in Buffer.
121 IN EFI_LOCATE_SEARCH_TYPE SearchType
,
122 IN EFI_GUID
*Protocol OPTIONAL
,
123 IN VOID
*SearchKey OPTIONAL
,
124 IN OUT UINTN
*BufferSize
,
125 OUT EFI_HANDLE
*Buffer
129 LOCATE_POSITION Position
;
130 PROTOCOL_NOTIFY
*ProtNotify
;
131 CORE_GET_NEXT GetNext
;
134 IHANDLE
**ResultBuffer
;
137 if (BufferSize
== NULL
) {
138 Status
= EFI_INVALID_PARAMETER
;
141 if ((*BufferSize
> 0) && (Buffer
== NULL
)) {
142 return EFI_INVALID_PARAMETER
;
147 // Set initial position
150 Position
.Protocol
= Protocol
;
151 Position
.SearchKey
= SearchKey
;
152 Position
.Position
= &gHandleList
;
155 ResultBuffer
= (IHANDLE
**) Buffer
;
156 Status
= EFI_SUCCESS
;
159 // Lock the protocol database
162 CoreAcquireProtocolLock ();
165 // Get the search function based on type
167 switch (SearchType
) {
169 GetNext
= CoreGetNextLocateAllHandles
;
172 case ByRegisterNotify
:
174 // Must have SearchKey for locate ByRegisterNotify
176 if (SearchKey
== NULL
) {
177 Status
= EFI_INVALID_PARAMETER
;
180 GetNext
= CoreGetNextLocateByRegisterNotify
;
184 GetNext
= CoreGetNextLocateByProtocol
;
185 if (Protocol
== NULL
) {
186 Status
= EFI_INVALID_PARAMETER
;
190 // Look up the protocol entry and set the head pointer
192 Position
.ProtEntry
= CoreFindProtocolEntry (Protocol
, FALSE
);
193 if (Position
.ProtEntry
== NULL
) {
194 Status
= EFI_NOT_FOUND
;
197 Position
.Position
= &Position
.ProtEntry
->Protocols
;
201 Status
= EFI_INVALID_PARAMETER
;
205 if (EFI_ERROR(Status
)) {
206 CoreReleaseProtocolLock ();
211 // Enumerate out the matching handles
213 mEfiLocateHandleRequest
+= 1;
216 // Get the next handle. If no more handles, stop
218 Handle
= GetNext (&Position
, &Interface
);
219 if (NULL
== Handle
) {
224 // Increase the resulting buffer size, and if this handle
227 ResultSize
+= sizeof(Handle
);
228 if (ResultSize
<= *BufferSize
) {
229 *ResultBuffer
= Handle
;
235 // If the result is a zero length buffer, then there were no
238 if (ResultSize
== 0) {
239 Status
= EFI_NOT_FOUND
;
242 // Return the resulting buffer size. If it's larger than what
243 // was passed, then set the error code
245 if (ResultSize
> *BufferSize
) {
246 Status
= EFI_BUFFER_TOO_SMALL
;
249 *BufferSize
= ResultSize
;
251 if (SearchType
== ByRegisterNotify
&& !EFI_ERROR(Status
)) {
253 // If this is a search by register notify and a handle was
254 // returned, update the register notification position
256 ProtNotify
= SearchKey
;
257 ProtNotify
->Position
= ProtNotify
->Position
->ForwardLink
;
261 CoreReleaseProtocolLock ();
268 Routine to get the next Handle, when you are searching for all handles.
270 @param Position Information about which Handle to seach for.
271 @param Interface Return the interface structure for the matching
274 @retval IHANDLE An IHANDLE is returned if the next Position is
275 not the end of the list. A NULL_HANDLE is
276 returned if it's the end of the list.
281 CoreGetNextLocateAllHandles (
282 IN OUT LOCATE_POSITION
*Position
,
291 Position
->Position
= Position
->Position
->ForwardLink
;
294 // If not at the end of the list, get the handle
296 Handle
= NULL_HANDLE
;
298 if (Position
->Position
!= &gHandleList
) {
299 Handle
= CR (Position
->Position
, IHANDLE
, AllHandles
, EFI_HANDLE_SIGNATURE
);
308 Routine to get the next Handle, when you are searching for register protocol
311 @param Position Information about which Handle to seach for.
312 @param Interface Return the interface structure for the matching
315 @retval IHANDLE An IHANDLE is returned if the next Position is
316 not the end of the list. A NULL_HANDLE is
317 returned if it's the end of the list.
322 CoreGetNextLocateByRegisterNotify (
323 IN OUT LOCATE_POSITION
*Position
,
328 PROTOCOL_NOTIFY
*ProtNotify
;
329 PROTOCOL_INTERFACE
*Prot
;
332 Handle
= NULL_HANDLE
;
334 ProtNotify
= Position
->SearchKey
;
337 // If this is the first request, get the next handle
339 if (ProtNotify
!= NULL
) {
340 ASSERT(ProtNotify
->Signature
== PROTOCOL_NOTIFY_SIGNATURE
);
341 Position
->SearchKey
= NULL
;
344 // If not at the end of the list, get the next handle
346 Link
= ProtNotify
->Position
->ForwardLink
;
347 if (Link
!= &ProtNotify
->Protocol
->Protocols
) {
348 Prot
= CR (Link
, PROTOCOL_INTERFACE
, ByProtocol
, PROTOCOL_INTERFACE_SIGNATURE
);
349 Handle
= (IHANDLE
*) Prot
->Handle
;
350 *Interface
= Prot
->Interface
;
360 Routine to get the next Handle, when you are searching for a given protocol.
362 @param Position Information about which Handle to seach for.
363 @param Interface Return the interface structure for the matching
366 @retval IHANDLE An IHANDLE is returned if the next Position is
367 not the end of the list. A NULL_HANDLE is
368 returned if it's the end of the list.
373 CoreGetNextLocateByProtocol (
374 IN OUT LOCATE_POSITION
*Position
,
380 PROTOCOL_INTERFACE
*Prot
;
382 Handle
= NULL_HANDLE
;
388 Link
= Position
->Position
->ForwardLink
;
389 Position
->Position
= Link
;
392 // If not at the end, return the handle
394 if (Link
== &Position
->ProtEntry
->Protocols
) {
395 Handle
= NULL_HANDLE
;
402 Prot
= CR(Link
, PROTOCOL_INTERFACE
, ByProtocol
, PROTOCOL_INTERFACE_SIGNATURE
);
403 Handle
= (IHANDLE
*) Prot
->Handle
;
404 *Interface
= Prot
->Interface
;
407 // If this handle has not been returned this request, then
410 if (Handle
->LocateRequest
!= mEfiLocateHandleRequest
) {
411 Handle
->LocateRequest
= mEfiLocateHandleRequest
;
423 Locates the handle to a device on the device path that best matches the specified protocol.
425 @param Protocol The protocol to search for.
426 @param DevicePath On input, a pointer to a pointer to the device
427 path. On output, the device path pointer is
428 modified to point to the remaining part of the
430 @param Device A pointer to the returned device handle.
432 @retval EFI_SUCCESS The resulting handle was returned.
433 @retval EFI_NOT_FOUND No handles matched the search.
434 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
439 CoreLocateDevicePath (
440 IN EFI_GUID
*Protocol
,
441 IN OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePath
,
442 OUT EFI_HANDLE
*Device
453 EFI_DEVICE_PATH_PROTOCOL
*SourcePath
;
454 EFI_DEVICE_PATH_PROTOCOL
*TmpDevicePath
;
456 if (Protocol
== NULL
) {
457 return EFI_INVALID_PARAMETER
;
460 if ((DevicePath
== NULL
) || (*DevicePath
== NULL
)) {
461 return EFI_INVALID_PARAMETER
;
464 if (Device
== NULL
) {
465 return EFI_INVALID_PARAMETER
;
468 *Device
= NULL_HANDLE
;
469 SourcePath
= *DevicePath
;
470 SourceSize
= CoreDevicePathSize (SourcePath
) - sizeof(EFI_DEVICE_PATH_PROTOCOL
);
473 // The source path can only have 1 instance
475 if (CoreIsDevicePathMultiInstance (SourcePath
)) {
476 DEBUG((DEBUG_ERROR
, "LocateDevicePath: Device path has too many instances\n"));
477 return EFI_INVALID_PARAMETER
;
481 // Get a list of all handles that support the requested protocol
483 Status
= CoreLocateHandleBuffer (ByProtocol
, Protocol
, NULL
, &HandleCount
, &Handles
);
484 if (EFI_ERROR (Status
) || HandleCount
== 0) {
485 return EFI_NOT_FOUND
;
489 for(Index
= 0; Index
< HandleCount
; Index
+= 1) {
490 Handle
= Handles
[Index
];
491 Status
= CoreHandleProtocol (Handle
, &gEfiDevicePathProtocolGuid
, (VOID
**)&TmpDevicePath
);
492 if (EFI_ERROR (Status
)) {
494 // If this handle doesn't support device path, then skip it
500 // Check if DevicePath is first part of SourcePath
502 Size
= CoreDevicePathSize (TmpDevicePath
) - sizeof(EFI_DEVICE_PATH_PROTOCOL
);
503 if ((Size
<= SourceSize
) && CompareMem (SourcePath
, TmpDevicePath
, Size
) == 0) {
505 // If the size is equal to the best match, then we
506 // have a duplice device path for 2 different device
509 ASSERT (Size
!= BestMatch
);
512 // We've got a match, see if it's the best match so far
514 if (Size
> BestMatch
) {
521 CoreFreePool (Handles
);
524 // If there wasn't any match, then no parts of the device path was found.
525 // Which is strange since there is likely a "root level" device path in the system.
527 if (BestMatch
== -1) {
528 return EFI_NOT_FOUND
;
532 // Return the remaining part of the device path
534 *DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) (((UINT8
*) SourcePath
) + BestMatch
);
542 Return the first Protocol Interface that matches the Protocol GUID. If
543 Registration is pasased in return a Protocol Instance that was just add
544 to the system. If Retistration is NULL return the first Protocol Interface
547 @param Protocol The protocol to search for
548 @param Registration Optional Registration Key returned from
549 RegisterProtocolNotify()
550 @param Interface Return the Protocol interface (instance).
552 @retval EFI_SUCCESS If a valid Interface is returned
553 @retval EFI_INVALID_PARAMETER Invalid parameter
554 @retval EFI_NOT_FOUND Protocol interface not found
560 IN EFI_GUID
*Protocol
,
561 IN VOID
*Registration OPTIONAL
,
566 LOCATE_POSITION Position
;
567 PROTOCOL_NOTIFY
*ProtNotify
;
570 if (Interface
== NULL
) {
571 return EFI_INVALID_PARAMETER
;
574 if (Protocol
== NULL
) {
575 return EFI_NOT_FOUND
;
579 Status
= EFI_SUCCESS
;
582 // Set initial position
584 Position
.Protocol
= Protocol
;
585 Position
.SearchKey
= Registration
;
586 Position
.Position
= &gHandleList
;
589 // Lock the protocol database
591 CoreAcquireProtocolLock ();
593 mEfiLocateHandleRequest
+= 1;
595 if (NULL
== Registration
) {
597 // Look up the protocol entry and set the head pointer
599 Position
.ProtEntry
= CoreFindProtocolEntry (Protocol
, FALSE
);
600 if (Position
.ProtEntry
== NULL
) {
601 Status
= EFI_NOT_FOUND
;
604 Position
.Position
= &Position
.ProtEntry
->Protocols
;
606 Handle
= CoreGetNextLocateByProtocol (&Position
, Interface
);
608 Handle
= CoreGetNextLocateByRegisterNotify (&Position
, Interface
);
611 if (NULL
== Handle
) {
612 Status
= EFI_NOT_FOUND
;
613 } else if (NULL
!= Registration
) {
615 // If this is a search by register notify and a handle was
616 // returned, update the register notification position
618 ProtNotify
= Registration
;
619 ProtNotify
->Position
= ProtNotify
->Position
->ForwardLink
;
623 CoreReleaseProtocolLock ();
631 Function returns an array of handles that support the requested protocol
632 in a buffer allocated from pool. This is a version of CoreLocateHandle()
633 that allocates a buffer for the caller.
635 @param SearchType Specifies which handle(s) are to be returned.
636 @param Protocol Provides the protocol to search by. This
637 parameter is only valid for SearchType
639 @param SearchKey Supplies the search key depending on the
641 @param NumberHandles The number of handles returned in Buffer.
642 @param Buffer A pointer to the buffer to return the requested
643 array of handles that support Protocol.
645 @retval EFI_SUCCESS The result array of handles was returned.
646 @retval EFI_NOT_FOUND No handles match the search.
647 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the
649 @retval EFI_INVALID_PARAMETER Invalid parameter
654 CoreLocateHandleBuffer (
655 IN EFI_LOCATE_SEARCH_TYPE SearchType
,
656 IN EFI_GUID
*Protocol OPTIONAL
,
657 IN VOID
*SearchKey OPTIONAL
,
658 IN OUT UINTN
*NumberHandles
,
659 OUT EFI_HANDLE
**Buffer
665 if (NumberHandles
== NULL
) {
666 return EFI_INVALID_PARAMETER
;
669 if (Buffer
== NULL
) {
670 return EFI_INVALID_PARAMETER
;
676 Status
= CoreLocateHandle (
684 // LocateHandleBuffer() returns incorrect status code if SearchType is
687 // Add code to correctly handle expected errors from CoreLocateHandle().
689 if (EFI_ERROR(Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
690 if (Status
!= EFI_INVALID_PARAMETER
) {
691 Status
= EFI_NOT_FOUND
;
696 *Buffer
= CoreAllocateBootServicesPool (BufferSize
);
697 if (*Buffer
== NULL
) {
698 return EFI_OUT_OF_RESOURCES
;
701 Status
= CoreLocateHandle (
709 *NumberHandles
= BufferSize
/sizeof(EFI_HANDLE
);
710 if (EFI_ERROR(Status
)) {