2 Locate handle functions
4 Copyright (c) 2006 - 2009, 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.
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 @return An pointer to IHANDLE if the next Position is not the end of the list.
49 Otherwise,NULL is returned.
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 @return An pointer to IHANDLE if the next Position is not the end of the list.
67 Otherwise,NULL is returned.
71 CoreGetNextLocateByRegisterNotify (
72 IN OUT LOCATE_POSITION
*Position
,
77 Routine to get the next Handle, when you are searching for a given 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 CoreGetNextLocateByProtocol (
89 IN OUT LOCATE_POSITION
*Position
,
95 Locates the requested handle(s) and returns them in Buffer.
97 @param SearchType The type of search to perform to locate the
99 @param Protocol The protocol to search for
100 @param SearchKey Dependant on SearchType
101 @param BufferSize On input the size of Buffer. On output the
102 size of data returned.
103 @param Buffer The buffer to return the results in
105 @retval EFI_BUFFER_TOO_SMALL Buffer too small, required buffer size is
106 returned in BufferSize.
107 @retval EFI_INVALID_PARAMETER Invalid parameter
108 @retval EFI_SUCCESS Successfully found the requested handle(s) and
109 returns them in Buffer.
115 IN EFI_LOCATE_SEARCH_TYPE SearchType
,
116 IN EFI_GUID
*Protocol OPTIONAL
,
117 IN VOID
*SearchKey OPTIONAL
,
118 IN OUT UINTN
*BufferSize
,
119 OUT EFI_HANDLE
*Buffer
123 LOCATE_POSITION Position
;
124 PROTOCOL_NOTIFY
*ProtNotify
;
125 CORE_GET_NEXT GetNext
;
128 IHANDLE
**ResultBuffer
;
131 if (BufferSize
== NULL
) {
132 return EFI_INVALID_PARAMETER
;
135 if ((*BufferSize
> 0) && (Buffer
== NULL
)) {
136 return EFI_INVALID_PARAMETER
;
142 // Set initial position
144 Position
.Protocol
= Protocol
;
145 Position
.SearchKey
= SearchKey
;
146 Position
.Position
= &gHandleList
;
149 ResultBuffer
= (IHANDLE
**) Buffer
;
150 Status
= EFI_SUCCESS
;
153 // Lock the protocol database
155 CoreAcquireProtocolLock ();
158 // Get the search function based on type
160 switch (SearchType
) {
162 GetNext
= CoreGetNextLocateAllHandles
;
165 case ByRegisterNotify
:
167 // Must have SearchKey for locate ByRegisterNotify
169 if (SearchKey
== NULL
) {
170 Status
= EFI_INVALID_PARAMETER
;
173 GetNext
= CoreGetNextLocateByRegisterNotify
;
177 GetNext
= CoreGetNextLocateByProtocol
;
178 if (Protocol
== NULL
) {
179 Status
= EFI_INVALID_PARAMETER
;
183 // Look up the protocol entry and set the head pointer
185 Position
.ProtEntry
= CoreFindProtocolEntry (Protocol
, FALSE
);
186 if (Position
.ProtEntry
== NULL
) {
187 Status
= EFI_NOT_FOUND
;
190 Position
.Position
= &Position
.ProtEntry
->Protocols
;
194 Status
= EFI_INVALID_PARAMETER
;
198 if (EFI_ERROR(Status
)) {
199 CoreReleaseProtocolLock ();
204 // Enumerate out the matching handles
206 mEfiLocateHandleRequest
+= 1;
209 // Get the next handle. If no more handles, stop
211 Handle
= GetNext (&Position
, &Interface
);
212 if (NULL
== Handle
) {
217 // Increase the resulting buffer size, and if this handle
220 ResultSize
+= sizeof(Handle
);
221 if (ResultSize
<= *BufferSize
) {
222 *ResultBuffer
= Handle
;
228 // If the result is a zero length buffer, then there were no
231 if (ResultSize
== 0) {
232 Status
= EFI_NOT_FOUND
;
235 // Return the resulting buffer size. If it's larger than what
236 // was passed, then set the error code
238 if (ResultSize
> *BufferSize
) {
239 Status
= EFI_BUFFER_TOO_SMALL
;
242 *BufferSize
= ResultSize
;
244 if (SearchType
== ByRegisterNotify
&& !EFI_ERROR(Status
)) {
246 // If this is a search by register notify and a handle was
247 // returned, update the register notification position
249 ProtNotify
= SearchKey
;
250 ProtNotify
->Position
= ProtNotify
->Position
->ForwardLink
;
254 CoreReleaseProtocolLock ();
261 Routine to get the next Handle, when you are searching for all handles.
263 @param Position Information about which Handle to seach for.
264 @param Interface Return the interface structure for the matching
267 @return An pointer to IHANDLE if the next Position is not the end of the list.
268 Otherwise,NULL is returned.
272 CoreGetNextLocateAllHandles (
273 IN OUT LOCATE_POSITION
*Position
,
282 Position
->Position
= Position
->Position
->ForwardLink
;
285 // If not at the end of the list, get the handle
289 if (Position
->Position
!= &gHandleList
) {
290 Handle
= CR (Position
->Position
, IHANDLE
, AllHandles
, EFI_HANDLE_SIGNATURE
);
299 Routine to get the next Handle, when you are searching for register protocol
302 @param Position Information about which Handle to seach for.
303 @param Interface Return the interface structure for the matching
306 @return An pointer to IHANDLE if the next Position is not the end of the list.
307 Otherwise,NULL is returned.
311 CoreGetNextLocateByRegisterNotify (
312 IN OUT LOCATE_POSITION
*Position
,
317 PROTOCOL_NOTIFY
*ProtNotify
;
318 PROTOCOL_INTERFACE
*Prot
;
323 ProtNotify
= Position
->SearchKey
;
326 // If this is the first request, get the next handle
328 if (ProtNotify
!= NULL
) {
329 ASSERT(ProtNotify
->Signature
== PROTOCOL_NOTIFY_SIGNATURE
);
330 Position
->SearchKey
= NULL
;
333 // If not at the end of the list, get the next handle
335 Link
= ProtNotify
->Position
->ForwardLink
;
336 if (Link
!= &ProtNotify
->Protocol
->Protocols
) {
337 Prot
= CR (Link
, PROTOCOL_INTERFACE
, ByProtocol
, PROTOCOL_INTERFACE_SIGNATURE
);
338 Handle
= Prot
->Handle
;
339 *Interface
= Prot
->Interface
;
348 Routine to get the next Handle, when you are searching for a given protocol.
350 @param Position Information about which Handle to seach for.
351 @param Interface Return the interface structure for the matching
354 @return An pointer to IHANDLE if the next Position is not the end of the list.
355 Otherwise,NULL is returned.
359 CoreGetNextLocateByProtocol (
360 IN OUT LOCATE_POSITION
*Position
,
366 PROTOCOL_INTERFACE
*Prot
;
374 Link
= Position
->Position
->ForwardLink
;
375 Position
->Position
= Link
;
378 // If not at the end, return the handle
380 if (Link
== &Position
->ProtEntry
->Protocols
) {
388 Prot
= CR(Link
, PROTOCOL_INTERFACE
, ByProtocol
, PROTOCOL_INTERFACE_SIGNATURE
);
389 Handle
= Prot
->Handle
;
390 *Interface
= Prot
->Interface
;
393 // If this handle has not been returned this request, then
396 if (Handle
->LocateRequest
!= mEfiLocateHandleRequest
) {
397 Handle
->LocateRequest
= mEfiLocateHandleRequest
;
407 Locates the handle to a device on the device path that best matches the specified protocol.
409 @param Protocol The protocol to search for.
410 @param DevicePath On input, a pointer to a pointer to the device
411 path. On output, the device path pointer is
412 modified to point to the remaining part of the
414 @param Device A pointer to the returned device handle.
416 @retval EFI_SUCCESS The resulting handle was returned.
417 @retval EFI_NOT_FOUND No handles matched the search.
418 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
423 CoreLocateDevicePath (
424 IN EFI_GUID
*Protocol
,
425 IN OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePath
,
426 OUT EFI_HANDLE
*Device
437 EFI_DEVICE_PATH_PROTOCOL
*SourcePath
;
438 EFI_DEVICE_PATH_PROTOCOL
*TmpDevicePath
;
440 if (Protocol
== NULL
) {
441 return EFI_INVALID_PARAMETER
;
444 if ((DevicePath
== NULL
) || (*DevicePath
== NULL
)) {
445 return EFI_INVALID_PARAMETER
;
448 if (Device
== NULL
) {
449 return EFI_INVALID_PARAMETER
;
453 SourcePath
= *DevicePath
;
454 TmpDevicePath
= SourcePath
;
455 while (!IsDevicePathEnd (TmpDevicePath
)) {
456 if (IsDevicePathEndInstance (TmpDevicePath
)) {
458 // If DevicePath is a multi-instance device path,
459 // the function will operate on the first instance
463 TmpDevicePath
= NextDevicePathNode (TmpDevicePath
);
466 SourceSize
= (UINTN
) TmpDevicePath
- (UINTN
) SourcePath
;
469 // Get a list of all handles that support the requested protocol
471 Status
= CoreLocateHandleBuffer (ByProtocol
, Protocol
, NULL
, &HandleCount
, &Handles
);
472 if (EFI_ERROR (Status
) || HandleCount
== 0) {
473 return EFI_NOT_FOUND
;
477 for(Index
= 0; Index
< HandleCount
; Index
+= 1) {
478 Handle
= Handles
[Index
];
479 Status
= CoreHandleProtocol (Handle
, &gEfiDevicePathProtocolGuid
, (VOID
**)&TmpDevicePath
);
480 if (EFI_ERROR (Status
)) {
482 // If this handle doesn't support device path, then skip it
488 // Check if DevicePath is first part of SourcePath
490 Size
= GetDevicePathSize (TmpDevicePath
) - sizeof(EFI_DEVICE_PATH_PROTOCOL
);
491 if ((Size
<= SourceSize
) && CompareMem (SourcePath
, TmpDevicePath
, Size
) == 0) {
493 // If the size is equal to the best match, then we
494 // have a duplicate device path for 2 different device
497 ASSERT (Size
!= BestMatch
);
500 // We've got a match, see if it's the best match so far
502 if (Size
> BestMatch
) {
509 CoreFreePool (Handles
);
512 // If there wasn't any match, then no parts of the device path was found.
513 // Which is strange since there is likely a "root level" device path in the system.
515 if (BestMatch
== -1) {
516 return EFI_NOT_FOUND
;
520 // Return the remaining part of the device path
522 *DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) (((UINT8
*) SourcePath
) + BestMatch
);
528 Return the first Protocol Interface that matches the Protocol GUID. If
529 Registration is passed in, return a Protocol Instance that was just add
530 to the system. If Registration is NULL return the first Protocol Interface
533 @param Protocol The protocol to search for
534 @param Registration Optional Registration Key returned from
535 RegisterProtocolNotify()
536 @param Interface Return the Protocol interface (instance).
538 @retval EFI_SUCCESS If a valid Interface is returned
539 @retval EFI_INVALID_PARAMETER Invalid parameter
540 @retval EFI_NOT_FOUND Protocol interface not found
546 IN EFI_GUID
*Protocol
,
547 IN VOID
*Registration OPTIONAL
,
552 LOCATE_POSITION Position
;
553 PROTOCOL_NOTIFY
*ProtNotify
;
556 if (Interface
== NULL
) {
557 return EFI_INVALID_PARAMETER
;
560 if (Protocol
== NULL
) {
561 return EFI_NOT_FOUND
;
565 Status
= EFI_SUCCESS
;
568 // Set initial position
570 Position
.Protocol
= Protocol
;
571 Position
.SearchKey
= Registration
;
572 Position
.Position
= &gHandleList
;
575 // Lock the protocol database
577 CoreAcquireProtocolLock ();
579 mEfiLocateHandleRequest
+= 1;
581 if (Registration
== NULL
) {
583 // Look up the protocol entry and set the head pointer
585 Position
.ProtEntry
= CoreFindProtocolEntry (Protocol
, FALSE
);
586 if (Position
.ProtEntry
== NULL
) {
587 Status
= EFI_NOT_FOUND
;
590 Position
.Position
= &Position
.ProtEntry
->Protocols
;
592 Handle
= CoreGetNextLocateByProtocol (&Position
, Interface
);
594 Handle
= CoreGetNextLocateByRegisterNotify (&Position
, Interface
);
597 if (Handle
== NULL
) {
598 Status
= EFI_NOT_FOUND
;
599 } else if (Registration
!= NULL
) {
601 // If this is a search by register notify and a handle was
602 // returned, update the register notification position
604 ProtNotify
= Registration
;
605 ProtNotify
->Position
= ProtNotify
->Position
->ForwardLink
;
609 CoreReleaseProtocolLock ();
615 Function returns an array of handles that support the requested protocol
616 in a buffer allocated from pool. This is a version of CoreLocateHandle()
617 that allocates a buffer for the caller.
619 @param SearchType Specifies which handle(s) are to be returned.
620 @param Protocol Provides the protocol to search by. This
621 parameter is only valid for SearchType
623 @param SearchKey Supplies the search key depending on the
625 @param NumberHandles The number of handles returned in Buffer.
626 @param Buffer A pointer to the buffer to return the requested
627 array of handles that support Protocol.
629 @retval EFI_SUCCESS The result array of handles was returned.
630 @retval EFI_NOT_FOUND No handles match the search.
631 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the
633 @retval EFI_INVALID_PARAMETER One or more paramters are not valid.
638 CoreLocateHandleBuffer (
639 IN EFI_LOCATE_SEARCH_TYPE SearchType
,
640 IN EFI_GUID
*Protocol OPTIONAL
,
641 IN VOID
*SearchKey OPTIONAL
,
642 IN OUT UINTN
*NumberHandles
,
643 OUT EFI_HANDLE
**Buffer
649 if (NumberHandles
== NULL
) {
650 return EFI_INVALID_PARAMETER
;
653 if (Buffer
== NULL
) {
654 return EFI_INVALID_PARAMETER
;
660 Status
= CoreLocateHandle (
668 // LocateHandleBuffer() returns incorrect status code if SearchType is
671 // Add code to correctly handle expected errors from CoreLocateHandle().
673 if (EFI_ERROR(Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
674 if (Status
!= EFI_INVALID_PARAMETER
) {
675 Status
= EFI_NOT_FOUND
;
680 *Buffer
= AllocatePool (BufferSize
);
681 if (*Buffer
== NULL
) {
682 return EFI_OUT_OF_RESOURCES
;
685 Status
= CoreLocateHandle (
693 *NumberHandles
= BufferSize
/ sizeof(EFI_HANDLE
);
694 if (EFI_ERROR(Status
)) {