2 Locate handle functions
4 Copyright (c) 2006 - 2008, Intel Corporation. <BR>
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this 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.
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 @retval IHANDLE An IHANDLE is returned if the next Position is
48 not the end of the list. A NULL_HANDLE is
49 returned if it's the end of the list.
53 CoreGetNextLocateAllHandles (
54 IN OUT LOCATE_POSITION
*Position
,
59 Routine to get the next Handle, when you are searching for register protocol
62 @param Position Information about which Handle to seach for.
63 @param Interface Return the interface structure for the matching
66 @retval IHANDLE An IHANDLE is returned if the next Position is
67 not the end of the list. A NULL_HANDLE is
68 returned if it's the end of the list.
72 CoreGetNextLocateByRegisterNotify (
73 IN OUT LOCATE_POSITION
*Position
,
78 Routine to get the next Handle, when you are searching for a given protocol.
80 @param Position Information about which Handle to seach for.
81 @param Interface Return the interface structure for the matching
84 @retval IHANDLE An IHANDLE is returned if the next Position is
85 not the end of the list. A NULL_HANDLE is
86 returned if it's the end of the list.
90 CoreGetNextLocateByProtocol (
91 IN OUT LOCATE_POSITION
*Position
,
97 Locates the requested handle(s) and returns them in Buffer.
99 @param SearchType The type of search to perform to locate the
101 @param Protocol The protocol to search for
102 @param SearchKey Dependant on SearchType
103 @param BufferSize On input the size of Buffer. On output the
104 size of data returned.
105 @param Buffer The buffer to return the results in
107 @retval EFI_BUFFER_TOO_SMALL Buffer too small, required buffer size is
108 returned in BufferSize.
109 @retval EFI_INVALID_PARAMETER Invalid parameter
110 @retval EFI_SUCCESS Successfully found the requested handle(s) and
111 returns them in Buffer.
117 IN EFI_LOCATE_SEARCH_TYPE SearchType
,
118 IN EFI_GUID
*Protocol OPTIONAL
,
119 IN VOID
*SearchKey OPTIONAL
,
120 IN OUT UINTN
*BufferSize
,
121 OUT EFI_HANDLE
*Buffer
125 LOCATE_POSITION Position
;
126 PROTOCOL_NOTIFY
*ProtNotify
;
127 CORE_GET_NEXT GetNext
;
130 IHANDLE
**ResultBuffer
;
133 if (BufferSize
== NULL
) {
134 Status
= EFI_INVALID_PARAMETER
;
137 if ((*BufferSize
> 0) && (Buffer
== NULL
)) {
138 return EFI_INVALID_PARAMETER
;
143 // Set initial position
146 Position
.Protocol
= Protocol
;
147 Position
.SearchKey
= SearchKey
;
148 Position
.Position
= &gHandleList
;
151 ResultBuffer
= (IHANDLE
**) Buffer
;
152 Status
= EFI_SUCCESS
;
155 // Lock the protocol database
158 CoreAcquireProtocolLock ();
161 // Get the search function based on type
163 switch (SearchType
) {
165 GetNext
= CoreGetNextLocateAllHandles
;
168 case ByRegisterNotify
:
170 // Must have SearchKey for locate ByRegisterNotify
172 if (SearchKey
== NULL
) {
173 Status
= EFI_INVALID_PARAMETER
;
176 GetNext
= CoreGetNextLocateByRegisterNotify
;
180 GetNext
= CoreGetNextLocateByProtocol
;
181 if (Protocol
== NULL
) {
182 Status
= EFI_INVALID_PARAMETER
;
186 // Look up the protocol entry and set the head pointer
188 Position
.ProtEntry
= CoreFindProtocolEntry (Protocol
, FALSE
);
189 if (Position
.ProtEntry
== NULL
) {
190 Status
= EFI_NOT_FOUND
;
193 Position
.Position
= &Position
.ProtEntry
->Protocols
;
197 Status
= EFI_INVALID_PARAMETER
;
201 if (EFI_ERROR(Status
)) {
202 CoreReleaseProtocolLock ();
207 // Enumerate out the matching handles
209 mEfiLocateHandleRequest
+= 1;
212 // Get the next handle. If no more handles, stop
214 Handle
= GetNext (&Position
, &Interface
);
215 if (NULL
== Handle
) {
220 // Increase the resulting buffer size, and if this handle
223 ResultSize
+= sizeof(Handle
);
224 if (ResultSize
<= *BufferSize
) {
225 *ResultBuffer
= Handle
;
231 // If the result is a zero length buffer, then there were no
234 if (ResultSize
== 0) {
235 Status
= EFI_NOT_FOUND
;
238 // Return the resulting buffer size. If it's larger than what
239 // was passed, then set the error code
241 if (ResultSize
> *BufferSize
) {
242 Status
= EFI_BUFFER_TOO_SMALL
;
245 *BufferSize
= ResultSize
;
247 if (SearchType
== ByRegisterNotify
&& !EFI_ERROR(Status
)) {
249 // If this is a search by register notify and a handle was
250 // returned, update the register notification position
252 ProtNotify
= SearchKey
;
253 ProtNotify
->Position
= ProtNotify
->Position
->ForwardLink
;
257 CoreReleaseProtocolLock ();
264 Routine to get the next Handle, when you are searching for all handles.
266 @param Position Information about which Handle to seach for.
267 @param Interface Return the interface structure for the matching
270 @retval IHANDLE An IHANDLE is returned if the next Position is
271 not the end of the list. A NULL_HANDLE is
272 returned if it's the end of the list.
276 CoreGetNextLocateAllHandles (
277 IN OUT LOCATE_POSITION
*Position
,
286 Position
->Position
= Position
->Position
->ForwardLink
;
289 // If not at the end of the list, get the handle
291 Handle
= NULL_HANDLE
;
293 if (Position
->Position
!= &gHandleList
) {
294 Handle
= CR (Position
->Position
, IHANDLE
, AllHandles
, EFI_HANDLE_SIGNATURE
);
303 Routine to get the next Handle, when you are searching for register protocol
306 @param Position Information about which Handle to seach for.
307 @param Interface Return the interface structure for the matching
310 @retval IHANDLE An IHANDLE is returned if the next Position is
311 not the end of the list. A NULL_HANDLE is
312 returned if it's the end of the list.
316 CoreGetNextLocateByRegisterNotify (
317 IN OUT LOCATE_POSITION
*Position
,
322 PROTOCOL_NOTIFY
*ProtNotify
;
323 PROTOCOL_INTERFACE
*Prot
;
326 Handle
= NULL_HANDLE
;
328 ProtNotify
= Position
->SearchKey
;
331 // If this is the first request, get the next handle
333 if (ProtNotify
!= NULL
) {
334 ASSERT(ProtNotify
->Signature
== PROTOCOL_NOTIFY_SIGNATURE
);
335 Position
->SearchKey
= NULL
;
338 // If not at the end of the list, get the next handle
340 Link
= ProtNotify
->Position
->ForwardLink
;
341 if (Link
!= &ProtNotify
->Protocol
->Protocols
) {
342 Prot
= CR (Link
, PROTOCOL_INTERFACE
, ByProtocol
, PROTOCOL_INTERFACE_SIGNATURE
);
343 Handle
= (IHANDLE
*) Prot
->Handle
;
344 *Interface
= Prot
->Interface
;
354 Routine to get the next Handle, when you are searching for a given protocol.
356 @param Position Information about which Handle to seach for.
357 @param Interface Return the interface structure for the matching
360 @retval IHANDLE An IHANDLE is returned if the next Position is
361 not the end of the list. A NULL_HANDLE is
362 returned if it's the end of the list.
366 CoreGetNextLocateByProtocol (
367 IN OUT LOCATE_POSITION
*Position
,
373 PROTOCOL_INTERFACE
*Prot
;
375 Handle
= NULL_HANDLE
;
381 Link
= Position
->Position
->ForwardLink
;
382 Position
->Position
= Link
;
385 // If not at the end, return the handle
387 if (Link
== &Position
->ProtEntry
->Protocols
) {
388 Handle
= NULL_HANDLE
;
395 Prot
= CR(Link
, PROTOCOL_INTERFACE
, ByProtocol
, PROTOCOL_INTERFACE_SIGNATURE
);
396 Handle
= (IHANDLE
*) Prot
->Handle
;
397 *Interface
= Prot
->Interface
;
400 // If this handle has not been returned this request, then
403 if (Handle
->LocateRequest
!= mEfiLocateHandleRequest
) {
404 Handle
->LocateRequest
= mEfiLocateHandleRequest
;
416 Locates the handle to a device on the device path that best matches the specified protocol.
418 @param Protocol The protocol to search for.
419 @param DevicePath On input, a pointer to a pointer to the device
420 path. On output, the device path pointer is
421 modified to point to the remaining part of the
423 @param Device A pointer to the returned device handle.
425 @retval EFI_SUCCESS The resulting handle was returned.
426 @retval EFI_NOT_FOUND No handles matched the search.
427 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
432 CoreLocateDevicePath (
433 IN EFI_GUID
*Protocol
,
434 IN OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePath
,
435 OUT EFI_HANDLE
*Device
446 EFI_DEVICE_PATH_PROTOCOL
*SourcePath
;
447 EFI_DEVICE_PATH_PROTOCOL
*TmpDevicePath
;
449 if (Protocol
== NULL
) {
450 return EFI_INVALID_PARAMETER
;
453 if ((DevicePath
== NULL
) || (*DevicePath
== NULL
)) {
454 return EFI_INVALID_PARAMETER
;
457 if (Device
== NULL
) {
458 return EFI_INVALID_PARAMETER
;
461 *Device
= NULL_HANDLE
;
462 SourcePath
= *DevicePath
;
463 SourceSize
= CoreDevicePathSize (SourcePath
) - sizeof(EFI_DEVICE_PATH_PROTOCOL
);
466 // The source path can only have 1 instance
468 if (CoreIsDevicePathMultiInstance (SourcePath
)) {
469 DEBUG((DEBUG_ERROR
, "LocateDevicePath: Device path has too many instances\n"));
470 return EFI_INVALID_PARAMETER
;
474 // Get a list of all handles that support the requested protocol
476 Status
= CoreLocateHandleBuffer (ByProtocol
, Protocol
, NULL
, &HandleCount
, &Handles
);
477 if (EFI_ERROR (Status
) || HandleCount
== 0) {
478 return EFI_NOT_FOUND
;
482 for(Index
= 0; Index
< HandleCount
; Index
+= 1) {
483 Handle
= Handles
[Index
];
484 Status
= CoreHandleProtocol (Handle
, &gEfiDevicePathProtocolGuid
, (VOID
**)&TmpDevicePath
);
485 if (EFI_ERROR (Status
)) {
487 // If this handle doesn't support device path, then skip it
493 // Check if DevicePath is first part of SourcePath
495 Size
= CoreDevicePathSize (TmpDevicePath
) - sizeof(EFI_DEVICE_PATH_PROTOCOL
);
496 if ((Size
<= SourceSize
) && CompareMem (SourcePath
, TmpDevicePath
, Size
) == 0) {
498 // If the size is equal to the best match, then we
499 // have a duplice device path for 2 different device
502 ASSERT (Size
!= BestMatch
);
505 // We've got a match, see if it's the best match so far
507 if (Size
> BestMatch
) {
514 CoreFreePool (Handles
);
517 // If there wasn't any match, then no parts of the device path was found.
518 // Which is strange since there is likely a "root level" device path in the system.
520 if (BestMatch
== -1) {
521 return EFI_NOT_FOUND
;
525 // Return the remaining part of the device path
527 *DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) (((UINT8
*) SourcePath
) + BestMatch
);
535 Return the first Protocol Interface that matches the Protocol GUID. If
536 Registration is pasased in return a Protocol Instance that was just add
537 to the system. If Retistration is NULL return the first Protocol Interface
540 @param Protocol The protocol to search for
541 @param Registration Optional Registration Key returned from
542 RegisterProtocolNotify()
543 @param Interface Return the Protocol interface (instance).
545 @retval EFI_SUCCESS If a valid Interface is returned
546 @retval EFI_INVALID_PARAMETER Invalid parameter
547 @retval EFI_NOT_FOUND Protocol interface not found
553 IN EFI_GUID
*Protocol
,
554 IN VOID
*Registration OPTIONAL
,
559 LOCATE_POSITION Position
;
560 PROTOCOL_NOTIFY
*ProtNotify
;
563 if (Interface
== NULL
) {
564 return EFI_INVALID_PARAMETER
;
567 if (Protocol
== NULL
) {
568 return EFI_NOT_FOUND
;
572 Status
= EFI_SUCCESS
;
575 // Set initial position
577 Position
.Protocol
= Protocol
;
578 Position
.SearchKey
= Registration
;
579 Position
.Position
= &gHandleList
;
582 // Lock the protocol database
584 CoreAcquireProtocolLock ();
586 mEfiLocateHandleRequest
+= 1;
588 if (NULL
== Registration
) {
590 // Look up the protocol entry and set the head pointer
592 Position
.ProtEntry
= CoreFindProtocolEntry (Protocol
, FALSE
);
593 if (Position
.ProtEntry
== NULL
) {
594 Status
= EFI_NOT_FOUND
;
597 Position
.Position
= &Position
.ProtEntry
->Protocols
;
599 Handle
= CoreGetNextLocateByProtocol (&Position
, Interface
);
601 Handle
= CoreGetNextLocateByRegisterNotify (&Position
, Interface
);
604 if (NULL
== Handle
) {
605 Status
= EFI_NOT_FOUND
;
606 } else if (NULL
!= Registration
) {
608 // If this is a search by register notify and a handle was
609 // returned, update the register notification position
611 ProtNotify
= Registration
;
612 ProtNotify
->Position
= ProtNotify
->Position
->ForwardLink
;
616 CoreReleaseProtocolLock ();
624 Function returns an array of handles that support the requested protocol
625 in a buffer allocated from pool. This is a version of CoreLocateHandle()
626 that allocates a buffer for the caller.
628 @param SearchType Specifies which handle(s) are to be returned.
629 @param Protocol Provides the protocol to search by. This
630 parameter is only valid for SearchType
632 @param SearchKey Supplies the search key depending on the
634 @param NumberHandles The number of handles returned in Buffer.
635 @param Buffer A pointer to the buffer to return the requested
636 array of handles that support Protocol.
638 @retval EFI_SUCCESS The result array of handles was returned.
639 @retval EFI_NOT_FOUND No handles match the search.
640 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the
642 @retval EFI_INVALID_PARAMETER Invalid parameter
647 CoreLocateHandleBuffer (
648 IN EFI_LOCATE_SEARCH_TYPE SearchType
,
649 IN EFI_GUID
*Protocol OPTIONAL
,
650 IN VOID
*SearchKey OPTIONAL
,
651 IN OUT UINTN
*NumberHandles
,
652 OUT EFI_HANDLE
**Buffer
658 if (NumberHandles
== NULL
) {
659 return EFI_INVALID_PARAMETER
;
662 if (Buffer
== NULL
) {
663 return EFI_INVALID_PARAMETER
;
669 Status
= CoreLocateHandle (
677 // LocateHandleBuffer() returns incorrect status code if SearchType is
680 // Add code to correctly handle expected errors from CoreLocateHandle().
682 if (EFI_ERROR(Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
683 if (Status
!= EFI_INVALID_PARAMETER
) {
684 Status
= EFI_NOT_FOUND
;
689 *Buffer
= CoreAllocateBootServicesPool (BufferSize
);
690 if (*Buffer
== NULL
) {
691 return EFI_OUT_OF_RESOURCES
;
694 Status
= CoreLocateHandle (
702 *NumberHandles
= BufferSize
/sizeof(EFI_HANDLE
);
703 if (EFI_ERROR(Status
)) {