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
,
89 Locates the requested handle(s) and returns them in Buffer.
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.
109 IN EFI_LOCATE_SEARCH_TYPE SearchType
,
110 IN EFI_GUID
*Protocol OPTIONAL
,
111 IN VOID
*SearchKey OPTIONAL
,
112 IN OUT UINTN
*BufferSize
,
113 OUT EFI_HANDLE
*Buffer
117 LOCATE_POSITION Position
;
118 PROTOCOL_NOTIFY
*ProtNotify
;
119 CORE_GET_NEXT GetNext
;
122 IHANDLE
**ResultBuffer
;
125 if (BufferSize
== NULL
) {
126 return EFI_INVALID_PARAMETER
;
129 if ((*BufferSize
> 0) && (Buffer
== NULL
)) {
130 return EFI_INVALID_PARAMETER
;
136 // Set initial position
138 Position
.Protocol
= Protocol
;
139 Position
.SearchKey
= SearchKey
;
140 Position
.Position
= &gHandleList
;
143 ResultBuffer
= (IHANDLE
**) Buffer
;
144 Status
= EFI_SUCCESS
;
147 // Lock the protocol database
149 CoreAcquireProtocolLock ();
152 // Get the search function based on type
154 switch (SearchType
) {
156 GetNext
= CoreGetNextLocateAllHandles
;
159 case ByRegisterNotify
:
161 // Must have SearchKey for locate ByRegisterNotify
163 if (SearchKey
== NULL
) {
164 Status
= EFI_INVALID_PARAMETER
;
167 GetNext
= CoreGetNextLocateByRegisterNotify
;
171 GetNext
= CoreGetNextLocateByProtocol
;
172 if (Protocol
== NULL
) {
173 Status
= EFI_INVALID_PARAMETER
;
177 // Look up the protocol entry and set the head pointer
179 Position
.ProtEntry
= CoreFindProtocolEntry (Protocol
, FALSE
);
180 if (Position
.ProtEntry
== NULL
) {
181 Status
= EFI_NOT_FOUND
;
184 Position
.Position
= &Position
.ProtEntry
->Protocols
;
188 Status
= EFI_INVALID_PARAMETER
;
192 if (EFI_ERROR(Status
)) {
193 CoreReleaseProtocolLock ();
197 ASSERT (GetNext
!= NULL
);
199 // Enumerate out the matching handles
201 mEfiLocateHandleRequest
+= 1;
204 // Get the next handle. If no more handles, stop
206 Handle
= GetNext (&Position
, &Interface
);
207 if (NULL
== Handle
) {
212 // Increase the resulting buffer size, and if this handle
215 ResultSize
+= sizeof(Handle
);
216 if (ResultSize
<= *BufferSize
) {
217 *ResultBuffer
= Handle
;
223 // If the result is a zero length buffer, then there were no
226 if (ResultSize
== 0) {
227 Status
= EFI_NOT_FOUND
;
230 // Return the resulting buffer size. If it's larger than what
231 // was passed, then set the error code
233 if (ResultSize
> *BufferSize
) {
234 Status
= EFI_BUFFER_TOO_SMALL
;
237 *BufferSize
= ResultSize
;
239 if (SearchType
== ByRegisterNotify
&& !EFI_ERROR(Status
)) {
241 // If this is a search by register notify and a handle was
242 // returned, update the register notification position
244 ASSERT (SearchKey
!= NULL
);
245 ProtNotify
= SearchKey
;
246 ProtNotify
->Position
= ProtNotify
->Position
->ForwardLink
;
250 CoreReleaseProtocolLock ();
257 Routine to get the next Handle, when you are searching for all handles.
259 @param Position Information about which Handle to seach for.
260 @param Interface Return the interface structure for the matching
263 @return An pointer to IHANDLE if the next Position is not the end of the list.
264 Otherwise,NULL is returned.
268 CoreGetNextLocateAllHandles (
269 IN OUT LOCATE_POSITION
*Position
,
278 Position
->Position
= Position
->Position
->ForwardLink
;
281 // If not at the end of the list, get the handle
285 if (Position
->Position
!= &gHandleList
) {
286 Handle
= CR (Position
->Position
, IHANDLE
, AllHandles
, EFI_HANDLE_SIGNATURE
);
295 Routine to get the next Handle, when you are searching for register protocol
298 @param Position Information about which Handle to seach for.
299 @param Interface Return the interface structure for the matching
302 @return An pointer to IHANDLE if the next Position is not the end of the list.
303 Otherwise,NULL is returned.
307 CoreGetNextLocateByRegisterNotify (
308 IN OUT LOCATE_POSITION
*Position
,
313 PROTOCOL_NOTIFY
*ProtNotify
;
314 PROTOCOL_INTERFACE
*Prot
;
319 ProtNotify
= Position
->SearchKey
;
322 // If this is the first request, get the next handle
324 if (ProtNotify
!= NULL
) {
325 ASSERT(ProtNotify
->Signature
== PROTOCOL_NOTIFY_SIGNATURE
);
326 Position
->SearchKey
= NULL
;
329 // If not at the end of the list, get the next handle
331 Link
= ProtNotify
->Position
->ForwardLink
;
332 if (Link
!= &ProtNotify
->Protocol
->Protocols
) {
333 Prot
= CR (Link
, PROTOCOL_INTERFACE
, ByProtocol
, PROTOCOL_INTERFACE_SIGNATURE
);
334 Handle
= Prot
->Handle
;
335 *Interface
= Prot
->Interface
;
344 Routine to get the next Handle, when you are searching for a given protocol.
346 @param Position Information about which Handle to seach for.
347 @param Interface Return the interface structure for the matching
350 @return An pointer to IHANDLE if the next Position is not the end of the list.
351 Otherwise,NULL is returned.
355 CoreGetNextLocateByProtocol (
356 IN OUT LOCATE_POSITION
*Position
,
362 PROTOCOL_INTERFACE
*Prot
;
370 Link
= Position
->Position
->ForwardLink
;
371 Position
->Position
= Link
;
374 // If not at the end, return the handle
376 if (Link
== &Position
->ProtEntry
->Protocols
) {
384 Prot
= CR(Link
, PROTOCOL_INTERFACE
, ByProtocol
, PROTOCOL_INTERFACE_SIGNATURE
);
385 Handle
= Prot
->Handle
;
386 *Interface
= Prot
->Interface
;
389 // If this handle has not been returned this request, then
392 if (Handle
->LocateRequest
!= mEfiLocateHandleRequest
) {
393 Handle
->LocateRequest
= mEfiLocateHandleRequest
;
403 Locates the handle to a device on the device path that supports the specified protocol.
405 @param Protocol Specifies the protocol to search for.
406 @param DevicePath On input, a pointer to a pointer to the device path. On output, the device
407 path pointer is modified to point to the remaining part of the device
409 @param Device A pointer to the returned device handle.
411 @retval EFI_SUCCESS The resulting handle was returned.
412 @retval EFI_NOT_FOUND No handles match the search.
413 @retval EFI_INVALID_PARAMETER Protocol is NULL.
414 @retval EFI_INVALID_PARAMETER DevicePath is NULL.
415 @retval EFI_INVALID_PARAMETER A handle matched the search and Device is NULL.
420 CoreLocateDevicePath (
421 IN EFI_GUID
*Protocol
,
422 IN OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePath
,
423 OUT EFI_HANDLE
*Device
434 EFI_HANDLE BestDevice
;
435 EFI_DEVICE_PATH_PROTOCOL
*SourcePath
;
436 EFI_DEVICE_PATH_PROTOCOL
*TmpDevicePath
;
438 if (Protocol
== NULL
) {
439 return EFI_INVALID_PARAMETER
;
442 if ((DevicePath
== NULL
) || (*DevicePath
== NULL
)) {
443 return EFI_INVALID_PARAMETER
;
448 SourcePath
= *DevicePath
;
449 TmpDevicePath
= SourcePath
;
450 while (!IsDevicePathEnd (TmpDevicePath
)) {
451 if (IsDevicePathEndInstance (TmpDevicePath
)) {
453 // If DevicePath is a multi-instance device path,
454 // the function will operate on the first instance
458 TmpDevicePath
= NextDevicePathNode (TmpDevicePath
);
461 SourceSize
= (UINTN
) TmpDevicePath
- (UINTN
) SourcePath
;
464 // Get a list of all handles that support the requested protocol
466 Status
= CoreLocateHandleBuffer (ByProtocol
, Protocol
, NULL
, &HandleCount
, &Handles
);
467 if (EFI_ERROR (Status
) || HandleCount
== 0) {
468 return EFI_NOT_FOUND
;
472 for(Index
= 0; Index
< HandleCount
; Index
+= 1) {
473 Handle
= Handles
[Index
];
474 Status
= CoreHandleProtocol (Handle
, &gEfiDevicePathProtocolGuid
, (VOID
**)&TmpDevicePath
);
475 if (EFI_ERROR (Status
)) {
477 // If this handle doesn't support device path, then skip it
483 // Check if DevicePath is first part of SourcePath
485 Size
= GetDevicePathSize (TmpDevicePath
) - sizeof(EFI_DEVICE_PATH_PROTOCOL
);
487 if ((Size
<= SourceSize
) && CompareMem (SourcePath
, TmpDevicePath
, (UINTN
) Size
) == 0) {
489 // If the size is equal to the best match, then we
490 // have a duplicate device path for 2 different device
493 ASSERT (Size
!= BestMatch
);
496 // We've got a match, see if it's the best match so far
498 if (Size
> BestMatch
) {
505 CoreFreePool (Handles
);
508 // If there wasn't any match, then no parts of the device path was found.
509 // Which is strange since there is likely a "root level" device path in the system.
511 if (BestMatch
== -1) {
512 return EFI_NOT_FOUND
;
515 if (Device
== NULL
) {
516 return EFI_INVALID_PARAMETER
;
518 *Device
= BestDevice
;
521 // Return the remaining part of the device path
523 *DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) (((UINT8
*) SourcePath
) + BestMatch
);
529 Return the first Protocol Interface that matches the Protocol GUID. If
530 Registration is passed in, return a Protocol Instance that was just add
531 to the system. If Registration is NULL return the first Protocol Interface
534 @param Protocol The protocol to search for
535 @param Registration Optional Registration Key returned from
536 RegisterProtocolNotify()
537 @param Interface Return the Protocol interface (instance).
539 @retval EFI_SUCCESS If a valid Interface is returned
540 @retval EFI_INVALID_PARAMETER Invalid parameter
541 @retval EFI_NOT_FOUND Protocol interface not found
547 IN EFI_GUID
*Protocol
,
548 IN VOID
*Registration OPTIONAL
,
553 LOCATE_POSITION Position
;
554 PROTOCOL_NOTIFY
*ProtNotify
;
557 if ((Interface
== NULL
) || (Protocol
== NULL
)) {
558 return EFI_INVALID_PARAMETER
;
562 Status
= EFI_SUCCESS
;
565 // Set initial position
567 Position
.Protocol
= Protocol
;
568 Position
.SearchKey
= Registration
;
569 Position
.Position
= &gHandleList
;
572 // Lock the protocol database
574 Status
= CoreAcquireLockOrFail (&gProtocolDatabaseLock
);
575 if (EFI_ERROR (Status
)) {
576 return EFI_NOT_FOUND
;
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 parameters 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
)) {