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
,
43 CoreGetNextLocateAllHandles (
44 IN OUT LOCATE_POSITION
*Position
,
50 CoreGetNextLocateByRegisterNotify (
51 IN OUT LOCATE_POSITION
*Position
,
57 CoreGetNextLocateByProtocol (
58 IN OUT LOCATE_POSITION
*Position
,
72 IN EFI_LOCATE_SEARCH_TYPE SearchType
,
73 IN EFI_GUID
*Protocol OPTIONAL
,
74 IN VOID
*SearchKey OPTIONAL
,
75 IN OUT UINTN
*BufferSize
,
76 OUT EFI_HANDLE
*Buffer
82 Locates the requested handle(s) and returns them in Buffer.
86 SearchType - The type of search to perform to locate the handles
88 Protocol - The protocol to search for
90 SearchKey - Dependant on SearchType
92 BufferSize - On input the size of Buffer. On output the
93 size of data returned.
95 Buffer - The buffer to return the results in
100 EFI_BUFFER_TOO_SMALL - Buffer too small, required buffer size is returned in BufferSize.
102 EFI_INVALID_PARAMETER - Invalid parameter
104 EFI_SUCCESS - Successfully found the requested handle(s) and returns them in Buffer.
109 LOCATE_POSITION Position
;
110 PROTOCOL_NOTIFY
*ProtNotify
;
111 CORE_GET_NEXT GetNext
;
114 IHANDLE
**ResultBuffer
;
117 if (BufferSize
== NULL
) {
118 Status
= EFI_INVALID_PARAMETER
;
121 if ((*BufferSize
> 0) && (Buffer
== NULL
)) {
122 return EFI_INVALID_PARAMETER
;
127 // Set initial position
130 Position
.Protocol
= Protocol
;
131 Position
.SearchKey
= SearchKey
;
132 Position
.Position
= &gHandleList
;
135 ResultBuffer
= (IHANDLE
**) Buffer
;
136 Status
= EFI_SUCCESS
;
139 // Lock the protocol database
142 CoreAcquireProtocolLock ();
145 // Get the search function based on type
147 switch (SearchType
) {
149 GetNext
= CoreGetNextLocateAllHandles
;
152 case ByRegisterNotify
:
154 // Must have SearchKey for locate ByRegisterNotify
156 if (SearchKey
== NULL
) {
157 Status
= EFI_INVALID_PARAMETER
;
160 GetNext
= CoreGetNextLocateByRegisterNotify
;
164 GetNext
= CoreGetNextLocateByProtocol
;
165 if (Protocol
== NULL
) {
166 Status
= EFI_INVALID_PARAMETER
;
170 // Look up the protocol entry and set the head pointer
172 Position
.ProtEntry
= CoreFindProtocolEntry (Protocol
, FALSE
);
173 if (Position
.ProtEntry
== NULL
) {
174 Status
= EFI_NOT_FOUND
;
177 Position
.Position
= &Position
.ProtEntry
->Protocols
;
181 Status
= EFI_INVALID_PARAMETER
;
185 if (EFI_ERROR(Status
)) {
186 CoreReleaseProtocolLock ();
191 // Enumerate out the matching handles
193 mEfiLocateHandleRequest
+= 1;
196 // Get the next handle. If no more handles, stop
198 Handle
= GetNext (&Position
, &Interface
);
199 if (NULL
== Handle
) {
204 // Increase the resulting buffer size, and if this handle
207 ResultSize
+= sizeof(Handle
);
208 if (ResultSize
<= *BufferSize
) {
209 *ResultBuffer
= Handle
;
215 // If the result is a zero length buffer, then there were no
218 if (ResultSize
== 0) {
219 Status
= EFI_NOT_FOUND
;
222 // Return the resulting buffer size. If it's larger than what
223 // was passed, then set the error code
225 if (ResultSize
> *BufferSize
) {
226 Status
= EFI_BUFFER_TOO_SMALL
;
229 *BufferSize
= ResultSize
;
231 if (SearchType
== ByRegisterNotify
&& !EFI_ERROR(Status
)) {
233 // If this is a search by register notify and a handle was
234 // returned, update the register notification position
236 ProtNotify
= SearchKey
;
237 ProtNotify
->Position
= ProtNotify
->Position
->ForwardLink
;
241 CoreReleaseProtocolLock ();
248 CoreGetNextLocateAllHandles (
249 IN OUT LOCATE_POSITION
*Position
,
256 Routine to get the next Handle, when you are searching for all handles.
260 Position - Information about which Handle to seach for.
262 Interface - Return the interface structure for the matching protocol.
265 IHANDLE - An IHANDLE is returned if the next Position is not the end of the
266 list. A NULL_HANDLE is returned if it's the end of the list.
275 Position
->Position
= Position
->Position
->ForwardLink
;
278 // If not at the end of the list, get the handle
280 Handle
= NULL_HANDLE
;
282 if (Position
->Position
!= &gHandleList
) {
283 Handle
= CR (Position
->Position
, IHANDLE
, AllHandles
, EFI_HANDLE_SIGNATURE
);
292 CoreGetNextLocateByRegisterNotify (
293 IN OUT LOCATE_POSITION
*Position
,
300 Routine to get the next Handle, when you are searching for register protocol
305 Position - Information about which Handle to seach for.
307 Interface - Return the interface structure for the matching protocol.
310 IHANDLE - An IHANDLE is returned if the next Position is not the end of the
311 list. A NULL_HANDLE is returned if it's the end of the list.
316 PROTOCOL_NOTIFY
*ProtNotify
;
317 PROTOCOL_INTERFACE
*Prot
;
320 Handle
= NULL_HANDLE
;
322 ProtNotify
= Position
->SearchKey
;
325 // If this is the first request, get the next handle
327 if (ProtNotify
!= NULL
) {
328 ASSERT(ProtNotify
->Signature
== PROTOCOL_NOTIFY_SIGNATURE
);
329 Position
->SearchKey
= NULL
;
332 // If not at the end of the list, get the next handle
334 Link
= ProtNotify
->Position
->ForwardLink
;
335 if (Link
!= &ProtNotify
->Protocol
->Protocols
) {
336 Prot
= CR (Link
, PROTOCOL_INTERFACE
, ByProtocol
, PROTOCOL_INTERFACE_SIGNATURE
);
337 Handle
= (IHANDLE
*) Prot
->Handle
;
338 *Interface
= Prot
->Interface
;
348 CoreGetNextLocateByProtocol (
349 IN OUT LOCATE_POSITION
*Position
,
356 Routine to get the next Handle, when you are searching for a given protocol.
360 Position - Information about which Handle to seach for.
362 Interface - Return the interface structure for the matching protocol.
365 IHANDLE - An IHANDLE is returned if the next Position is not the end of the
366 list. A NULL_HANDLE is returned if it's the end of the list.
372 PROTOCOL_INTERFACE
*Prot
;
374 Handle
= NULL_HANDLE
;
380 Link
= Position
->Position
->ForwardLink
;
381 Position
->Position
= Link
;
384 // If not at the end, return the handle
386 if (Link
== &Position
->ProtEntry
->Protocols
) {
387 Handle
= NULL_HANDLE
;
394 Prot
= CR(Link
, PROTOCOL_INTERFACE
, ByProtocol
, PROTOCOL_INTERFACE_SIGNATURE
);
395 Handle
= (IHANDLE
*) Prot
->Handle
;
396 *Interface
= Prot
->Interface
;
399 // If this handle has not been returned this request, then
402 if (Handle
->LocateRequest
!= mEfiLocateHandleRequest
) {
403 Handle
->LocateRequest
= mEfiLocateHandleRequest
;
415 CoreLocateDevicePath (
416 IN EFI_GUID
*Protocol
,
417 IN OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePath
,
418 OUT EFI_HANDLE
*Device
424 Locates the handle to a device on the device path that best matches the specified protocol.
428 Protocol - The protocol to search for.
429 DevicePath - On input, a pointer to a pointer to the device path. On output, the device
430 path pointer is modified to point to the remaining part of the devicepath.
431 Device - A pointer to the returned device handle.
435 EFI_SUCCESS - The resulting handle was returned.
436 EFI_NOT_FOUND - No handles matched the search.
437 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
449 EFI_DEVICE_PATH_PROTOCOL
*SourcePath
;
450 EFI_DEVICE_PATH_PROTOCOL
*TmpDevicePath
;
452 if (Protocol
== NULL
) {
453 return EFI_INVALID_PARAMETER
;
456 if ((DevicePath
== NULL
) || (*DevicePath
== NULL
)) {
457 return EFI_INVALID_PARAMETER
;
460 if (Device
== NULL
) {
461 return EFI_INVALID_PARAMETER
;
464 *Device
= NULL_HANDLE
;
465 SourcePath
= *DevicePath
;
466 SourceSize
= CoreDevicePathSize (SourcePath
) - sizeof(EFI_DEVICE_PATH_PROTOCOL
);
469 // The source path can only have 1 instance
471 if (CoreIsDevicePathMultiInstance (SourcePath
)) {
472 DEBUG((EFI_D_ERROR
, "LocateDevicePath: Device path has too many instances\n"));
473 return EFI_INVALID_PARAMETER
;
477 // Get a list of all handles that support the requested protocol
479 Status
= CoreLocateHandleBuffer (ByProtocol
, Protocol
, NULL
, &HandleCount
, &Handles
);
480 if (EFI_ERROR (Status
) || HandleCount
== 0) {
481 return EFI_NOT_FOUND
;
485 for(Index
= 0; Index
< HandleCount
; Index
+= 1) {
486 Handle
= Handles
[Index
];
487 Status
= CoreHandleProtocol (Handle
, &gEfiDevicePathProtocolGuid
, (VOID
**)&TmpDevicePath
);
488 if (EFI_ERROR (Status
)) {
490 // If this handle doesn't support device path, then skip it
496 // Check if DevicePath is first part of SourcePath
498 Size
= CoreDevicePathSize (TmpDevicePath
) - sizeof(EFI_DEVICE_PATH_PROTOCOL
);
499 if ((Size
<= SourceSize
) && CompareMem (SourcePath
, TmpDevicePath
, Size
) == 0) {
501 // If the size is equal to the best match, then we
502 // have a duplice device path for 2 different device
505 ASSERT (Size
!= BestMatch
);
508 // We've got a match, see if it's the best match so far
510 if (Size
> BestMatch
) {
517 CoreFreePool (Handles
);
520 // If there wasn't any match, then no parts of the device path was found.
521 // Which is strange since there is likely a "root level" device path in the system.
523 if (BestMatch
== -1) {
524 return EFI_NOT_FOUND
;
528 // Return the remaining part of the device path
530 *DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) (((UINT8
*) SourcePath
) + BestMatch
);
539 IN EFI_GUID
*Protocol
,
540 IN VOID
*Registration OPTIONAL
,
547 Return the first Protocol Interface that matches the Protocol GUID. If
548 Registration is pasased in return a Protocol Instance that was just add
549 to the system. If Retistration is NULL return the first Protocol Interface
554 Protocol - The protocol to search for
556 Registration - Optional Registration Key returned from RegisterProtocolNotify()
558 Interface - Return the Protocol interface (instance).
562 EFI_SUCCESS - If a valid Interface is returned
564 EFI_INVALID_PARAMETER - Invalid parameter
566 EFI_NOT_FOUND - Protocol interface not found
571 LOCATE_POSITION Position
;
572 PROTOCOL_NOTIFY
*ProtNotify
;
575 if (Interface
== NULL
) {
576 return EFI_INVALID_PARAMETER
;
579 if (Protocol
== NULL
) {
580 return EFI_NOT_FOUND
;
584 Status
= EFI_SUCCESS
;
587 // Set initial position
589 Position
.Protocol
= Protocol
;
590 Position
.SearchKey
= Registration
;
591 Position
.Position
= &gHandleList
;
594 // Lock the protocol database
596 CoreAcquireProtocolLock ();
598 mEfiLocateHandleRequest
+= 1;
600 if (NULL
== Registration
) {
602 // Look up the protocol entry and set the head pointer
604 Position
.ProtEntry
= CoreFindProtocolEntry (Protocol
, FALSE
);
605 if (Position
.ProtEntry
== NULL
) {
606 Status
= EFI_NOT_FOUND
;
609 Position
.Position
= &Position
.ProtEntry
->Protocols
;
611 Handle
= CoreGetNextLocateByProtocol (&Position
, Interface
);
613 Handle
= CoreGetNextLocateByRegisterNotify (&Position
, Interface
);
616 if (NULL
== Handle
) {
617 Status
= EFI_NOT_FOUND
;
618 } else if (NULL
!= Registration
) {
620 // If this is a search by register notify and a handle was
621 // returned, update the register notification position
623 ProtNotify
= Registration
;
624 ProtNotify
->Position
= ProtNotify
->Position
->ForwardLink
;
628 CoreReleaseProtocolLock ();
636 CoreLocateHandleBuffer (
637 IN EFI_LOCATE_SEARCH_TYPE SearchType
,
638 IN EFI_GUID
*Protocol OPTIONAL
,
639 IN VOID
*SearchKey OPTIONAL
,
640 IN OUT UINTN
*NumberHandles
,
641 OUT EFI_HANDLE
**Buffer
647 Function returns an array of handles that support the requested protocol
648 in a buffer allocated from pool. This is a version of CoreLocateHandle()
649 that allocates a buffer for the caller.
653 SearchType - Specifies which handle(s) are to be returned.
654 Protocol - Provides the protocol to search by.
655 This parameter is only valid for SearchType ByProtocol.
656 SearchKey - Supplies the search key depending on the SearchType.
657 NumberHandles - The number of handles returned in Buffer.
658 Buffer - A pointer to the buffer to return the requested array of
659 handles that support Protocol.
663 EFI_SUCCESS - The result array of handles was returned.
664 EFI_NOT_FOUND - No handles match the search.
665 EFI_OUT_OF_RESOURCES - There is not enough pool memory to store the matching results.
666 EFI_INVALID_PARAMETER - Invalid parameter
673 if (NumberHandles
== NULL
) {
674 return EFI_INVALID_PARAMETER
;
677 if (Buffer
== NULL
) {
678 return EFI_INVALID_PARAMETER
;
684 Status
= CoreLocateHandle (
692 // LocateHandleBuffer() returns incorrect status code if SearchType is
695 // Add code to correctly handle expected errors from CoreLocateHandle().
697 if (EFI_ERROR(Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
698 if (Status
!= EFI_INVALID_PARAMETER
) {
699 Status
= EFI_NOT_FOUND
;
704 *Buffer
= CoreAllocateBootServicesPool (BufferSize
);
705 if (*Buffer
== NULL
) {
706 return EFI_OUT_OF_RESOURCES
;
709 Status
= CoreLocateHandle (
717 *NumberHandles
= BufferSize
/sizeof(EFI_HANDLE
);
718 if (EFI_ERROR(Status
)) {