2 Locate handle functions
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
13 // ProtocolRequest - Last LocateHandle request ID
15 UINTN mEfiLocateHandleRequest
= 0;
18 // Internal prototypes
25 PROTOCOL_ENTRY
*ProtEntry
;
31 IN OUT LOCATE_POSITION
*Position
,
36 Routine to get the next Handle, when you are searching for all handles.
38 @param Position Information about which Handle to seach for.
39 @param Interface Return the interface structure for the matching
42 @return An pointer to IHANDLE if the next Position is not the end of the list.
43 Otherwise,NULL is returned.
47 CoreGetNextLocateAllHandles (
48 IN OUT LOCATE_POSITION
*Position
,
53 Routine to get the next Handle, when you are searching for register protocol
56 @param Position Information about which Handle to seach for.
57 @param Interface Return the interface structure for the matching
60 @return An pointer to IHANDLE if the next Position is not the end of the list.
61 Otherwise,NULL is returned.
65 CoreGetNextLocateByRegisterNotify (
66 IN OUT LOCATE_POSITION
*Position
,
71 Routine to get the next Handle, when you are searching for a given protocol.
73 @param Position Information about which Handle to seach for.
74 @param Interface Return the interface structure for the matching
77 @return An pointer to IHANDLE if the next Position is not the end of the list.
78 Otherwise,NULL is returned.
82 CoreGetNextLocateByProtocol (
83 IN OUT LOCATE_POSITION
*Position
,
88 Internal function for locating the requested handle(s) and returns them in Buffer.
89 The caller should already have acquired the ProtocolLock.
91 @param SearchType The type of search to perform to locate the
93 @param Protocol The protocol to search for
94 @param SearchKey Dependant on SearchType
95 @param BufferSize On input the size of Buffer. On output the
96 size of data returned.
97 @param Buffer The buffer to return the results in
99 @retval EFI_BUFFER_TOO_SMALL Buffer too small, required buffer size is
100 returned in BufferSize.
101 @retval EFI_INVALID_PARAMETER Invalid parameter
102 @retval EFI_SUCCESS Successfully found the requested handle(s) and
103 returns them in Buffer.
107 InternalCoreLocateHandle (
108 IN EFI_LOCATE_SEARCH_TYPE SearchType
,
109 IN EFI_GUID
*Protocol OPTIONAL
,
110 IN VOID
*SearchKey OPTIONAL
,
111 IN OUT UINTN
*BufferSize
,
112 OUT EFI_HANDLE
*Buffer
116 LOCATE_POSITION Position
;
117 PROTOCOL_NOTIFY
*ProtNotify
;
118 CORE_GET_NEXT GetNext
;
121 IHANDLE
**ResultBuffer
;
124 if (BufferSize
== NULL
) {
125 return EFI_INVALID_PARAMETER
;
128 if ((*BufferSize
> 0) && (Buffer
== NULL
)) {
129 return EFI_INVALID_PARAMETER
;
135 // Set initial position
137 Position
.Protocol
= Protocol
;
138 Position
.SearchKey
= SearchKey
;
139 Position
.Position
= &gHandleList
;
142 ResultBuffer
= (IHANDLE
**)Buffer
;
143 Status
= EFI_SUCCESS
;
146 // Get the search function based on type
148 switch (SearchType
) {
150 GetNext
= CoreGetNextLocateAllHandles
;
153 case ByRegisterNotify
:
155 // Must have SearchKey for locate ByRegisterNotify
157 if (SearchKey
== NULL
) {
158 Status
= EFI_INVALID_PARAMETER
;
162 GetNext
= CoreGetNextLocateByRegisterNotify
;
166 GetNext
= CoreGetNextLocateByProtocol
;
167 if (Protocol
== NULL
) {
168 Status
= EFI_INVALID_PARAMETER
;
173 // Look up the protocol entry and set the head pointer
175 Position
.ProtEntry
= CoreFindProtocolEntry (Protocol
, FALSE
);
176 if (Position
.ProtEntry
== NULL
) {
177 Status
= EFI_NOT_FOUND
;
181 Position
.Position
= &Position
.ProtEntry
->Protocols
;
185 Status
= EFI_INVALID_PARAMETER
;
189 if (EFI_ERROR (Status
)) {
193 ASSERT (GetNext
!= NULL
);
195 // Enumerate out the matching handles
197 mEfiLocateHandleRequest
+= 1;
200 // Get the next handle. If no more handles, stop
202 Handle
= GetNext (&Position
, &Interface
);
203 if (NULL
== Handle
) {
208 // Increase the resulting buffer size, and if this handle
211 ResultSize
+= sizeof (Handle
);
212 if (ResultSize
<= *BufferSize
) {
213 *ResultBuffer
= Handle
;
219 // If the result is a zero length buffer, then there were no
222 if (ResultSize
== 0) {
223 Status
= EFI_NOT_FOUND
;
226 // Return the resulting buffer size. If it's larger than what
227 // was passed, then set the error code
229 if (ResultSize
> *BufferSize
) {
230 Status
= EFI_BUFFER_TOO_SMALL
;
233 *BufferSize
= ResultSize
;
235 if ((SearchType
== ByRegisterNotify
) && !EFI_ERROR (Status
)) {
237 // If this is a search by register notify and a handle was
238 // returned, update the register notification position
240 ASSERT (SearchKey
!= NULL
);
241 ProtNotify
= SearchKey
;
242 ProtNotify
->Position
= ProtNotify
->Position
->ForwardLink
;
250 Locates the requested handle(s) and returns them in Buffer.
252 @param SearchType The type of search to perform to locate the
254 @param Protocol The protocol to search for
255 @param SearchKey Dependant on SearchType
256 @param BufferSize On input the size of Buffer. On output the
257 size of data returned.
258 @param Buffer The buffer to return the results in
260 @retval EFI_BUFFER_TOO_SMALL Buffer too small, required buffer size is
261 returned in BufferSize.
262 @retval EFI_INVALID_PARAMETER Invalid parameter
263 @retval EFI_SUCCESS Successfully found the requested handle(s) and
264 returns them in Buffer.
270 IN EFI_LOCATE_SEARCH_TYPE SearchType
,
271 IN EFI_GUID
*Protocol OPTIONAL
,
272 IN VOID
*SearchKey OPTIONAL
,
273 IN OUT UINTN
*BufferSize
,
274 OUT EFI_HANDLE
*Buffer
280 // Lock the protocol database
282 CoreAcquireProtocolLock ();
283 Status
= InternalCoreLocateHandle (SearchType
, Protocol
, SearchKey
, BufferSize
, Buffer
);
284 CoreReleaseProtocolLock ();
289 Routine to get the next Handle, when you are searching for all handles.
291 @param Position Information about which Handle to seach for.
292 @param Interface Return the interface structure for the matching
295 @return An pointer to IHANDLE if the next Position is not the end of the list.
296 Otherwise,NULL is returned.
300 CoreGetNextLocateAllHandles (
301 IN OUT LOCATE_POSITION
*Position
,
310 Position
->Position
= Position
->Position
->ForwardLink
;
313 // If not at the end of the list, get the handle
317 if (Position
->Position
!= &gHandleList
) {
318 Handle
= CR (Position
->Position
, IHANDLE
, AllHandles
, EFI_HANDLE_SIGNATURE
);
325 Routine to get the next Handle, when you are searching for register protocol
328 @param Position Information about which Handle to seach for.
329 @param Interface Return the interface structure for the matching
332 @return An pointer to IHANDLE if the next Position is not the end of the list.
333 Otherwise,NULL is returned.
337 CoreGetNextLocateByRegisterNotify (
338 IN OUT LOCATE_POSITION
*Position
,
343 PROTOCOL_NOTIFY
*ProtNotify
;
344 PROTOCOL_INTERFACE
*Prot
;
349 ProtNotify
= Position
->SearchKey
;
352 // If this is the first request, get the next handle
354 if (ProtNotify
!= NULL
) {
355 ASSERT (ProtNotify
->Signature
== PROTOCOL_NOTIFY_SIGNATURE
);
356 Position
->SearchKey
= NULL
;
359 // If not at the end of the list, get the next handle
361 Link
= ProtNotify
->Position
->ForwardLink
;
362 if (Link
!= &ProtNotify
->Protocol
->Protocols
) {
363 Prot
= CR (Link
, PROTOCOL_INTERFACE
, ByProtocol
, PROTOCOL_INTERFACE_SIGNATURE
);
364 Handle
= Prot
->Handle
;
365 *Interface
= Prot
->Interface
;
373 Routine to get the next Handle, when you are searching for a given protocol.
375 @param Position Information about which Handle to seach for.
376 @param Interface Return the interface structure for the matching
379 @return An pointer to IHANDLE if the next Position is not the end of the list.
380 Otherwise,NULL is returned.
384 CoreGetNextLocateByProtocol (
385 IN OUT LOCATE_POSITION
*Position
,
391 PROTOCOL_INTERFACE
*Prot
;
399 Link
= Position
->Position
->ForwardLink
;
400 Position
->Position
= Link
;
403 // If not at the end, return the handle
405 if (Link
== &Position
->ProtEntry
->Protocols
) {
413 Prot
= CR (Link
, PROTOCOL_INTERFACE
, ByProtocol
, PROTOCOL_INTERFACE_SIGNATURE
);
414 Handle
= Prot
->Handle
;
415 *Interface
= Prot
->Interface
;
418 // If this handle has not been returned this request, then
421 if (Handle
->LocateRequest
!= mEfiLocateHandleRequest
) {
422 Handle
->LocateRequest
= mEfiLocateHandleRequest
;
431 Locates the handle to a device on the device path that supports the specified protocol.
433 @param Protocol Specifies the protocol to search for.
434 @param DevicePath On input, a pointer to a pointer to the device path. On output, the device
435 path pointer is modified to point to the remaining part of the device
437 @param Device A pointer to the returned device handle.
439 @retval EFI_SUCCESS The resulting handle was returned.
440 @retval EFI_NOT_FOUND No handles match the search.
441 @retval EFI_INVALID_PARAMETER Protocol is NULL.
442 @retval EFI_INVALID_PARAMETER DevicePath is NULL.
443 @retval EFI_INVALID_PARAMETER A handle matched the search and Device is NULL.
448 CoreLocateDevicePath (
449 IN EFI_GUID
*Protocol
,
450 IN OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePath
,
451 OUT EFI_HANDLE
*Device
462 EFI_HANDLE BestDevice
;
463 EFI_DEVICE_PATH_PROTOCOL
*SourcePath
;
464 EFI_DEVICE_PATH_PROTOCOL
*TmpDevicePath
;
466 if (Protocol
== NULL
) {
467 return EFI_INVALID_PARAMETER
;
470 if ((DevicePath
== NULL
) || (*DevicePath
== NULL
)) {
471 return EFI_INVALID_PARAMETER
;
476 SourcePath
= *DevicePath
;
477 TmpDevicePath
= SourcePath
;
478 while (!IsDevicePathEnd (TmpDevicePath
)) {
479 if (IsDevicePathEndInstance (TmpDevicePath
)) {
481 // If DevicePath is a multi-instance device path,
482 // the function will operate on the first instance
487 TmpDevicePath
= NextDevicePathNode (TmpDevicePath
);
490 SourceSize
= (UINTN
)TmpDevicePath
- (UINTN
)SourcePath
;
493 // Get a list of all handles that support the requested protocol
495 Status
= CoreLocateHandleBuffer (ByProtocol
, Protocol
, NULL
, &HandleCount
, &Handles
);
496 if (EFI_ERROR (Status
) || (HandleCount
== 0)) {
497 return EFI_NOT_FOUND
;
501 for (Index
= 0; Index
< HandleCount
; Index
+= 1) {
502 Handle
= Handles
[Index
];
503 Status
= CoreHandleProtocol (Handle
, &gEfiDevicePathProtocolGuid
, (VOID
**)&TmpDevicePath
);
504 if (EFI_ERROR (Status
)) {
506 // If this handle doesn't support device path, then skip it
512 // Check if DevicePath is first part of SourcePath
514 Size
= GetDevicePathSize (TmpDevicePath
) - sizeof (EFI_DEVICE_PATH_PROTOCOL
);
516 if ((Size
<= SourceSize
) && (CompareMem (SourcePath
, TmpDevicePath
, (UINTN
)Size
) == 0)) {
518 // If the size is equal to the best match, then we
519 // have a duplicate device path for 2 different device
522 ASSERT (Size
!= BestMatch
);
525 // We've got a match, see if it's the best match so far
527 if (Size
> BestMatch
) {
534 CoreFreePool (Handles
);
537 // If there wasn't any match, then no parts of the device path was found.
538 // Which is strange since there is likely a "root level" device path in the system.
540 if (BestMatch
== -1) {
541 return EFI_NOT_FOUND
;
544 if (Device
== NULL
) {
545 return EFI_INVALID_PARAMETER
;
548 *Device
= BestDevice
;
551 // Return the remaining part of the device path
553 *DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*)(((UINT8
*)SourcePath
) + BestMatch
);
558 Return the first Protocol Interface that matches the Protocol GUID. If
559 Registration is passed in, return a Protocol Instance that was just add
560 to the system. If Registration is NULL return the first Protocol Interface
563 @param Protocol The protocol to search for
564 @param Registration Optional Registration Key returned from
565 RegisterProtocolNotify()
566 @param Interface Return the Protocol interface (instance).
568 @retval EFI_SUCCESS If a valid Interface is returned
569 @retval EFI_INVALID_PARAMETER Invalid parameter
570 @retval EFI_NOT_FOUND Protocol interface not found
576 IN EFI_GUID
*Protocol
,
577 IN VOID
*Registration OPTIONAL
,
582 LOCATE_POSITION Position
;
583 PROTOCOL_NOTIFY
*ProtNotify
;
586 if ((Interface
== NULL
) || (Protocol
== NULL
)) {
587 return EFI_INVALID_PARAMETER
;
591 Status
= EFI_SUCCESS
;
594 // Set initial position
596 Position
.Protocol
= Protocol
;
597 Position
.SearchKey
= Registration
;
598 Position
.Position
= &gHandleList
;
601 // Lock the protocol database
603 Status
= CoreAcquireLockOrFail (&gProtocolDatabaseLock
);
604 if (EFI_ERROR (Status
)) {
605 return EFI_NOT_FOUND
;
608 mEfiLocateHandleRequest
+= 1;
610 if (Registration
== NULL
) {
612 // Look up the protocol entry and set the head pointer
614 Position
.ProtEntry
= CoreFindProtocolEntry (Protocol
, FALSE
);
615 if (Position
.ProtEntry
== NULL
) {
616 Status
= EFI_NOT_FOUND
;
620 Position
.Position
= &Position
.ProtEntry
->Protocols
;
622 Handle
= CoreGetNextLocateByProtocol (&Position
, Interface
);
624 Handle
= CoreGetNextLocateByRegisterNotify (&Position
, Interface
);
627 if (Handle
== NULL
) {
628 Status
= EFI_NOT_FOUND
;
629 } else if (Registration
!= NULL
) {
631 // If this is a search by register notify and a handle was
632 // returned, update the register notification position
634 ProtNotify
= Registration
;
635 ProtNotify
->Position
= ProtNotify
->Position
->ForwardLink
;
639 CoreReleaseProtocolLock ();
644 Function returns an array of handles that support the requested protocol
645 in a buffer allocated from pool. This is a version of CoreLocateHandle()
646 that allocates a buffer for the caller.
648 @param SearchType Specifies which handle(s) are to be returned.
649 @param Protocol Provides the protocol to search by. This
650 parameter is only valid for SearchType
652 @param SearchKey Supplies the search key depending on the
654 @param NumberHandles The number of handles returned in Buffer.
655 @param Buffer A pointer to the buffer to return the requested
656 array of handles that support Protocol.
658 @retval EFI_SUCCESS The result array of handles was returned.
659 @retval EFI_NOT_FOUND No handles match the search.
660 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the
662 @retval EFI_INVALID_PARAMETER One or more parameters are not valid.
667 CoreLocateHandleBuffer (
668 IN EFI_LOCATE_SEARCH_TYPE SearchType
,
669 IN EFI_GUID
*Protocol OPTIONAL
,
670 IN VOID
*SearchKey OPTIONAL
,
671 IN OUT UINTN
*NumberHandles
,
672 OUT EFI_HANDLE
**Buffer
678 if (NumberHandles
== NULL
) {
679 return EFI_INVALID_PARAMETER
;
682 if (Buffer
== NULL
) {
683 return EFI_INVALID_PARAMETER
;
691 // Lock the protocol database
693 CoreAcquireProtocolLock ();
694 Status
= InternalCoreLocateHandle (
702 // LocateHandleBuffer() returns incorrect status code if SearchType is
705 // Add code to correctly handle expected errors from CoreLocateHandle().
707 if (EFI_ERROR (Status
) && (Status
!= EFI_BUFFER_TOO_SMALL
)) {
708 if (Status
!= EFI_INVALID_PARAMETER
) {
709 Status
= EFI_NOT_FOUND
;
712 CoreReleaseProtocolLock ();
716 *Buffer
= AllocatePool (BufferSize
);
717 if (*Buffer
== NULL
) {
718 CoreReleaseProtocolLock ();
719 return EFI_OUT_OF_RESOURCES
;
722 Status
= InternalCoreLocateHandle (
730 *NumberHandles
= BufferSize
/ sizeof (EFI_HANDLE
);
731 if (EFI_ERROR (Status
)) {
735 CoreReleaseProtocolLock ();