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 @return An pointer to IHANDLE if the next Position is not the end of the list.
48 Otherwise,NULL is returned.
52 CoreGetNextLocateAllHandles (
53 IN OUT LOCATE_POSITION
*Position
,
58 Routine to get the next Handle, when you are searching for register protocol
61 @param Position Information about which Handle to seach for.
62 @param Interface Return the interface structure for the matching
65 @return An pointer to IHANDLE if the next Position is not the end of the list.
66 Otherwise,NULL is returned.
70 CoreGetNextLocateByRegisterNotify (
71 IN OUT LOCATE_POSITION
*Position
,
76 Routine to get the next Handle, when you are searching for a given protocol.
78 @param Position Information about which Handle to seach for.
79 @param Interface Return the interface structure for the matching
82 @return An pointer to IHANDLE if the next Position is not the end of the list.
83 Otherwise,NULL is returned.
87 CoreGetNextLocateByProtocol (
88 IN OUT LOCATE_POSITION
*Position
,
94 Locates the requested handle(s) and returns them in Buffer.
96 @param SearchType The type of search to perform to locate the
98 @param Protocol The protocol to search for
99 @param SearchKey Dependant on SearchType
100 @param BufferSize On input the size of Buffer. On output the
101 size of data returned.
102 @param Buffer The buffer to return the results in
104 @retval EFI_BUFFER_TOO_SMALL Buffer too small, required buffer size is
105 returned in BufferSize.
106 @retval EFI_INVALID_PARAMETER Invalid parameter
107 @retval EFI_SUCCESS Successfully found the requested handle(s) and
108 returns them in Buffer.
114 IN EFI_LOCATE_SEARCH_TYPE SearchType
,
115 IN EFI_GUID
*Protocol OPTIONAL
,
116 IN VOID
*SearchKey OPTIONAL
,
117 IN OUT UINTN
*BufferSize
,
118 OUT EFI_HANDLE
*Buffer
122 LOCATE_POSITION Position
;
123 PROTOCOL_NOTIFY
*ProtNotify
;
124 CORE_GET_NEXT GetNext
;
127 IHANDLE
**ResultBuffer
;
130 if (BufferSize
== NULL
) {
131 Status
= EFI_INVALID_PARAMETER
;
134 if ((*BufferSize
> 0) && (Buffer
== NULL
)) {
135 return EFI_INVALID_PARAMETER
;
141 // Set initial position
143 Position
.Protocol
= Protocol
;
144 Position
.SearchKey
= SearchKey
;
145 Position
.Position
= &gHandleList
;
148 ResultBuffer
= (IHANDLE
**) Buffer
;
149 Status
= EFI_SUCCESS
;
152 // Lock the protocol database
154 CoreAcquireProtocolLock ();
157 // Get the search function based on type
159 switch (SearchType
) {
161 GetNext
= CoreGetNextLocateAllHandles
;
164 case ByRegisterNotify
:
166 // Must have SearchKey for locate ByRegisterNotify
168 if (SearchKey
== NULL
) {
169 Status
= EFI_INVALID_PARAMETER
;
172 GetNext
= CoreGetNextLocateByRegisterNotify
;
176 GetNext
= CoreGetNextLocateByProtocol
;
177 if (Protocol
== NULL
) {
178 Status
= EFI_INVALID_PARAMETER
;
182 // Look up the protocol entry and set the head pointer
184 Position
.ProtEntry
= CoreFindProtocolEntry (Protocol
, FALSE
);
185 if (Position
.ProtEntry
== NULL
) {
186 Status
= EFI_NOT_FOUND
;
189 Position
.Position
= &Position
.ProtEntry
->Protocols
;
193 Status
= EFI_INVALID_PARAMETER
;
197 if (EFI_ERROR(Status
)) {
198 CoreReleaseProtocolLock ();
203 // Enumerate out the matching handles
205 mEfiLocateHandleRequest
+= 1;
208 // Get the next handle. If no more handles, stop
210 Handle
= GetNext (&Position
, &Interface
);
211 if (NULL
== Handle
) {
216 // Increase the resulting buffer size, and if this handle
219 ResultSize
+= sizeof(Handle
);
220 if (ResultSize
<= *BufferSize
) {
221 *ResultBuffer
= Handle
;
227 // If the result is a zero length buffer, then there were no
230 if (ResultSize
== 0) {
231 Status
= EFI_NOT_FOUND
;
234 // Return the resulting buffer size. If it's larger than what
235 // was passed, then set the error code
237 if (ResultSize
> *BufferSize
) {
238 Status
= EFI_BUFFER_TOO_SMALL
;
241 *BufferSize
= ResultSize
;
243 if (SearchType
== ByRegisterNotify
&& !EFI_ERROR(Status
)) {
245 // If this is a search by register notify and a handle was
246 // returned, update the register notification position
248 ProtNotify
= SearchKey
;
249 ProtNotify
->Position
= ProtNotify
->Position
->ForwardLink
;
253 CoreReleaseProtocolLock ();
260 Routine to get the next Handle, when you are searching for all handles.
262 @param Position Information about which Handle to seach for.
263 @param Interface Return the interface structure for the matching
266 @return An pointer to IHANDLE if the next Position is not the end of the list.
267 Otherwise,NULL is returned.
271 CoreGetNextLocateAllHandles (
272 IN OUT LOCATE_POSITION
*Position
,
281 Position
->Position
= Position
->Position
->ForwardLink
;
284 // If not at the end of the list, get the handle
288 if (Position
->Position
!= &gHandleList
) {
289 Handle
= CR (Position
->Position
, IHANDLE
, AllHandles
, EFI_HANDLE_SIGNATURE
);
298 Routine to get the next Handle, when you are searching for register protocol
301 @param Position Information about which Handle to seach for.
302 @param Interface Return the interface structure for the matching
305 @return An pointer to IHANDLE if the next Position is not the end of the list.
306 Otherwise,NULL is returned.
310 CoreGetNextLocateByRegisterNotify (
311 IN OUT LOCATE_POSITION
*Position
,
316 PROTOCOL_NOTIFY
*ProtNotify
;
317 PROTOCOL_INTERFACE
*Prot
;
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
= Prot
->Handle
;
338 *Interface
= Prot
->Interface
;
347 Routine to get the next Handle, when you are searching for a given protocol.
349 @param Position Information about which Handle to seach for.
350 @param Interface Return the interface structure for the matching
353 @return An pointer to IHANDLE if the next Position is not the end of the list.
354 Otherwise,NULL is returned.
358 CoreGetNextLocateByProtocol (
359 IN OUT LOCATE_POSITION
*Position
,
365 PROTOCOL_INTERFACE
*Prot
;
373 Link
= Position
->Position
->ForwardLink
;
374 Position
->Position
= Link
;
377 // If not at the end, return the handle
379 if (Link
== &Position
->ProtEntry
->Protocols
) {
387 Prot
= CR(Link
, PROTOCOL_INTERFACE
, ByProtocol
, PROTOCOL_INTERFACE_SIGNATURE
);
388 Handle
= Prot
->Handle
;
389 *Interface
= Prot
->Interface
;
392 // If this handle has not been returned this request, then
395 if (Handle
->LocateRequest
!= mEfiLocateHandleRequest
) {
396 Handle
->LocateRequest
= mEfiLocateHandleRequest
;
406 Locates the handle to a device on the device path that best matches the specified protocol.
408 @param Protocol The protocol to search for.
409 @param DevicePath On input, a pointer to a pointer to the device
410 path. On output, the device path pointer is
411 modified to point to the remaining part of the
413 @param Device A pointer to the returned device handle.
415 @retval EFI_SUCCESS The resulting handle was returned.
416 @retval EFI_NOT_FOUND No handles matched the search.
417 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
422 CoreLocateDevicePath (
423 IN EFI_GUID
*Protocol
,
424 IN OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePath
,
425 OUT EFI_HANDLE
*Device
436 EFI_DEVICE_PATH_PROTOCOL
*SourcePath
;
437 EFI_DEVICE_PATH_PROTOCOL
*TmpDevicePath
;
439 if (Protocol
== NULL
) {
440 return EFI_INVALID_PARAMETER
;
443 if ((DevicePath
== NULL
) || (*DevicePath
== NULL
)) {
444 return EFI_INVALID_PARAMETER
;
447 if (Device
== NULL
) {
448 return EFI_INVALID_PARAMETER
;
452 SourcePath
= *DevicePath
;
453 SourceSize
= GetDevicePathSize (SourcePath
) - sizeof(EFI_DEVICE_PATH_PROTOCOL
);
456 // The source path can only have 1 instance
458 if (IsDevicePathMultiInstance (SourcePath
)) {
459 DEBUG((DEBUG_ERROR
, "LocateDevicePath: Device path has too many instances\n"));
460 return EFI_INVALID_PARAMETER
;
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
);
486 if ((Size
<= SourceSize
) && CompareMem (SourcePath
, TmpDevicePath
, Size
) == 0) {
488 // If the size is equal to the best match, then we
489 // have a duplice device path for 2 different device
492 ASSERT (Size
!= BestMatch
);
495 // We've got a match, see if it's the best match so far
497 if (Size
> BestMatch
) {
504 CoreFreePool (Handles
);
507 // If there wasn't any match, then no parts of the device path was found.
508 // Which is strange since there is likely a "root level" device path in the system.
510 if (BestMatch
== -1) {
511 return EFI_NOT_FOUND
;
515 // Return the remaining part of the device path
517 *DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) (((UINT8
*) SourcePath
) + BestMatch
);
523 Return the first Protocol Interface that matches the Protocol GUID. If
524 Registration is pasased in return a Protocol Instance that was just add
525 to the system. If Retistration is NULL return the first Protocol Interface
528 @param Protocol The protocol to search for
529 @param Registration Optional Registration Key returned from
530 RegisterProtocolNotify()
531 @param Interface Return the Protocol interface (instance).
533 @retval EFI_SUCCESS If a valid Interface is returned
534 @retval EFI_INVALID_PARAMETER Invalid parameter
535 @retval EFI_NOT_FOUND Protocol interface not found
541 IN EFI_GUID
*Protocol
,
542 IN VOID
*Registration OPTIONAL
,
547 LOCATE_POSITION Position
;
548 PROTOCOL_NOTIFY
*ProtNotify
;
551 if (Interface
== NULL
) {
552 return EFI_INVALID_PARAMETER
;
555 if (Protocol
== NULL
) {
556 return EFI_NOT_FOUND
;
560 Status
= EFI_SUCCESS
;
563 // Set initial position
565 Position
.Protocol
= Protocol
;
566 Position
.SearchKey
= Registration
;
567 Position
.Position
= &gHandleList
;
570 // Lock the protocol database
572 CoreAcquireProtocolLock ();
574 mEfiLocateHandleRequest
+= 1;
576 if (Registration
== NULL
) {
578 // Look up the protocol entry and set the head pointer
580 Position
.ProtEntry
= CoreFindProtocolEntry (Protocol
, FALSE
);
581 if (Position
.ProtEntry
== NULL
) {
582 Status
= EFI_NOT_FOUND
;
585 Position
.Position
= &Position
.ProtEntry
->Protocols
;
587 Handle
= CoreGetNextLocateByProtocol (&Position
, Interface
);
589 Handle
= CoreGetNextLocateByRegisterNotify (&Position
, Interface
);
592 if (Handle
== NULL
) {
593 Status
= EFI_NOT_FOUND
;
594 } else if (Registration
!= NULL
) {
596 // If this is a search by register notify and a handle was
597 // returned, update the register notification position
599 ProtNotify
= Registration
;
600 ProtNotify
->Position
= ProtNotify
->Position
->ForwardLink
;
604 CoreReleaseProtocolLock ();
610 Function returns an array of handles that support the requested protocol
611 in a buffer allocated from pool. This is a version of CoreLocateHandle()
612 that allocates a buffer for the caller.
614 @param SearchType Specifies which handle(s) are to be returned.
615 @param Protocol Provides the protocol to search by. This
616 parameter is only valid for SearchType
618 @param SearchKey Supplies the search key depending on the
620 @param NumberHandles The number of handles returned in Buffer.
621 @param Buffer A pointer to the buffer to return the requested
622 array of handles that support Protocol.
624 @retval EFI_SUCCESS The result array of handles was returned.
625 @retval EFI_NOT_FOUND No handles match the search.
626 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the
628 @retval EFI_INVALID_PARAMETER One or more paramters are not valid.
633 CoreLocateHandleBuffer (
634 IN EFI_LOCATE_SEARCH_TYPE SearchType
,
635 IN EFI_GUID
*Protocol OPTIONAL
,
636 IN VOID
*SearchKey OPTIONAL
,
637 IN OUT UINTN
*NumberHandles
,
638 OUT EFI_HANDLE
**Buffer
644 if (NumberHandles
== NULL
) {
645 return EFI_INVALID_PARAMETER
;
648 if (Buffer
== NULL
) {
649 return EFI_INVALID_PARAMETER
;
655 Status
= CoreLocateHandle (
663 // LocateHandleBuffer() returns incorrect status code if SearchType is
666 // Add code to correctly handle expected errors from CoreLocateHandle().
668 if (EFI_ERROR(Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
669 if (Status
!= EFI_INVALID_PARAMETER
) {
670 Status
= EFI_NOT_FOUND
;
675 *Buffer
= AllocatePool (BufferSize
);
676 if (*Buffer
== NULL
) {
677 return EFI_OUT_OF_RESOURCES
;
680 Status
= CoreLocateHandle (
688 *NumberHandles
= BufferSize
/ sizeof(EFI_HANDLE
);
689 if (EFI_ERROR(Status
)) {