3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 Locate handle functions
27 // ProtocolRequest - Last LocateHandle request ID
29 UINTN mEfiLocateHandleRequest
= 0;
32 // Internal prototypes
39 PROTOCOL_ENTRY
*ProtEntry
;
45 IN OUT LOCATE_POSITION
*Position
,
51 CoreGetNextLocateAllHandles (
52 IN OUT LOCATE_POSITION
*Position
,
58 CoreGetNextLocateByRegisterNotify (
59 IN OUT LOCATE_POSITION
*Position
,
65 CoreGetNextLocateByProtocol (
66 IN OUT LOCATE_POSITION
*Position
,
80 IN EFI_LOCATE_SEARCH_TYPE SearchType
,
81 IN EFI_GUID
*Protocol OPTIONAL
,
82 IN VOID
*SearchKey OPTIONAL
,
83 IN OUT UINTN
*BufferSize
,
84 OUT EFI_HANDLE
*Buffer
90 Locates the requested handle(s) and returns them in Buffer.
94 SearchType - The type of search to perform to locate the handles
96 Protocol - The protocol to search for
98 SearchKey - Dependant on SearchType
100 BufferSize - On input the size of Buffer. On output the
101 size of data returned.
103 Buffer - The buffer to return the results in
108 EFI_BUFFER_TOO_SMALL - Buffer too small, required buffer size is returned in BufferSize.
110 EFI_INVALID_PARAMETER - Invalid parameter
112 EFI_SUCCESS - Successfully found the requested handle(s) and returns them in Buffer.
117 LOCATE_POSITION Position
;
118 PROTOCOL_NOTIFY
*ProtNotify
;
119 CORE_GET_NEXT GetNext
;
122 IHANDLE
**ResultBuffer
;
125 if (BufferSize
== NULL
) {
126 Status
= EFI_INVALID_PARAMETER
;
129 if ((*BufferSize
> 0) && (Buffer
== NULL
)) {
130 return EFI_INVALID_PARAMETER
;
135 // 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
150 CoreAcquireProtocolLock ();
153 // Get the search function based on type
155 switch (SearchType
) {
157 GetNext
= CoreGetNextLocateAllHandles
;
160 case ByRegisterNotify
:
162 // Must have SearchKey for locate ByRegisterNotify
164 if (SearchKey
== NULL
) {
165 Status
= EFI_INVALID_PARAMETER
;
168 GetNext
= CoreGetNextLocateByRegisterNotify
;
172 GetNext
= CoreGetNextLocateByProtocol
;
173 if (Protocol
== NULL
) {
174 Status
= EFI_INVALID_PARAMETER
;
178 // Look up the protocol entry and set the head pointer
180 Position
.ProtEntry
= CoreFindProtocolEntry (Protocol
, FALSE
);
181 if (Position
.ProtEntry
== NULL
) {
182 Status
= EFI_NOT_FOUND
;
185 Position
.Position
= &Position
.ProtEntry
->Protocols
;
189 Status
= EFI_INVALID_PARAMETER
;
193 if (EFI_ERROR(Status
)) {
194 CoreReleaseProtocolLock ();
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 ProtNotify
= SearchKey
;
245 ProtNotify
->Position
= ProtNotify
->Position
->ForwardLink
;
249 CoreReleaseProtocolLock ();
256 CoreGetNextLocateAllHandles (
257 IN OUT LOCATE_POSITION
*Position
,
264 Routine to get the next Handle, when you are searching for all handles.
268 Position - Information about which Handle to seach for.
270 Interface - Return the interface structure for the matching protocol.
273 IHANDLE - An IHANDLE is returned if the next Position is not the end of the
274 list. A NULL_HANDLE is returned if it's the end of the list.
283 Position
->Position
= Position
->Position
->ForwardLink
;
286 // If not at the end of the list, get the handle
288 Handle
= NULL_HANDLE
;
290 if (Position
->Position
!= &gHandleList
) {
291 Handle
= CR (Position
->Position
, IHANDLE
, AllHandles
, EFI_HANDLE_SIGNATURE
);
300 CoreGetNextLocateByRegisterNotify (
301 IN OUT LOCATE_POSITION
*Position
,
308 Routine to get the next Handle, when you are searching for register protocol
313 Position - Information about which Handle to seach for.
315 Interface - Return the interface structure for the matching protocol.
318 IHANDLE - An IHANDLE is returned if the next Position is not the end of the
319 list. A NULL_HANDLE is returned if it's the end of the list.
324 PROTOCOL_NOTIFY
*ProtNotify
;
325 PROTOCOL_INTERFACE
*Prot
;
328 Handle
= NULL_HANDLE
;
330 ProtNotify
= Position
->SearchKey
;
333 // If this is the first request, get the next handle
335 if (ProtNotify
!= NULL
) {
336 ASSERT(ProtNotify
->Signature
== PROTOCOL_NOTIFY_SIGNATURE
);
337 Position
->SearchKey
= NULL
;
340 // If not at the end of the list, get the next handle
342 Link
= ProtNotify
->Position
->ForwardLink
;
343 if (Link
!= &ProtNotify
->Protocol
->Protocols
) {
344 Prot
= CR (Link
, PROTOCOL_INTERFACE
, ByProtocol
, PROTOCOL_INTERFACE_SIGNATURE
);
345 Handle
= (IHANDLE
*) Prot
->Handle
;
346 *Interface
= Prot
->Interface
;
356 CoreGetNextLocateByProtocol (
357 IN OUT LOCATE_POSITION
*Position
,
364 Routine to get the next Handle, when you are searching for a given protocol.
368 Position - Information about which Handle to seach for.
370 Interface - Return the interface structure for the matching protocol.
373 IHANDLE - An IHANDLE is returned if the next Position is not the end of the
374 list. A NULL_HANDLE is returned if it's the end of the list.
380 PROTOCOL_INTERFACE
*Prot
;
382 Handle
= NULL_HANDLE
;
388 Link
= Position
->Position
->ForwardLink
;
389 Position
->Position
= Link
;
392 // If not at the end, return the handle
394 if (Link
== &Position
->ProtEntry
->Protocols
) {
395 Handle
= NULL_HANDLE
;
402 Prot
= CR(Link
, PROTOCOL_INTERFACE
, ByProtocol
, PROTOCOL_INTERFACE_SIGNATURE
);
403 Handle
= (IHANDLE
*) Prot
->Handle
;
404 *Interface
= Prot
->Interface
;
407 // If this handle has not been returned this request, then
410 if (Handle
->LocateRequest
!= mEfiLocateHandleRequest
) {
411 Handle
->LocateRequest
= mEfiLocateHandleRequest
;
423 CoreLocateDevicePath (
424 IN EFI_GUID
*Protocol
,
425 IN OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePath
,
426 OUT EFI_HANDLE
*Device
432 Locates the handle to a device on the device path that best matches the specified protocol.
436 Protocol - The protocol to search for.
437 DevicePath - On input, a pointer to a pointer to the device path. On output, the device
438 path pointer is modified to point to the remaining part of the devicepath.
439 Device - A pointer to the returned device handle.
443 EFI_SUCCESS - The resulting handle was returned.
444 EFI_NOT_FOUND - No handles matched the search.
445 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.
457 EFI_DEVICE_PATH_PROTOCOL
*SourcePath
;
458 EFI_DEVICE_PATH_PROTOCOL
*TmpDevicePath
;
460 if (Protocol
== NULL
) {
461 return EFI_INVALID_PARAMETER
;
464 if ((DevicePath
== NULL
) || (*DevicePath
== NULL
)) {
465 return EFI_INVALID_PARAMETER
;
468 if (Device
== NULL
) {
469 return EFI_INVALID_PARAMETER
;
472 *Device
= NULL_HANDLE
;
473 SourcePath
= *DevicePath
;
474 SourceSize
= CoreDevicePathSize (SourcePath
) - sizeof(EFI_DEVICE_PATH_PROTOCOL
);
477 // The source path can only have 1 instance
479 if (CoreIsDevicePathMultiInstance (SourcePath
)) {
480 DEBUG((EFI_D_ERROR
, "LocateDevicePath: Device path has too many instances\n"));
481 return EFI_INVALID_PARAMETER
;
485 // Get a list of all handles that support the requested protocol
487 Status
= CoreLocateHandleBuffer (ByProtocol
, Protocol
, NULL
, &HandleCount
, &Handles
);
488 if (EFI_ERROR (Status
) || HandleCount
== 0) {
489 return EFI_NOT_FOUND
;
493 for(Index
= 0; Index
< HandleCount
; Index
+= 1) {
494 Handle
= Handles
[Index
];
495 Status
= CoreHandleProtocol (Handle
, &gEfiDevicePathProtocolGuid
, (VOID
**)&TmpDevicePath
);
496 if (EFI_ERROR (Status
)) {
498 // If this handle doesn't support device path, then skip it
504 // Check if DevicePath is first part of SourcePath
506 Size
= CoreDevicePathSize (TmpDevicePath
) - sizeof(EFI_DEVICE_PATH_PROTOCOL
);
507 if ((Size
<= SourceSize
) && CompareMem (SourcePath
, TmpDevicePath
, Size
) == 0) {
509 // If the size is equal to the best match, then we
510 // have a duplice device path for 2 different device
513 ASSERT (Size
!= BestMatch
);
516 // We've got a match, see if it's the best match so far
518 if (Size
> BestMatch
) {
525 CoreFreePool (Handles
);
528 // If there wasn't any match, then no parts of the device path was found.
529 // Which is strange since there is likely a "root level" device path in the system.
531 if (BestMatch
== -1) {
532 return EFI_NOT_FOUND
;
536 // Return the remaining part of the device path
538 *DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) (((UINT8
*) SourcePath
) + BestMatch
);
547 IN EFI_GUID
*Protocol
,
548 IN VOID
*Registration OPTIONAL
,
555 Return the first Protocol Interface that matches the Protocol GUID. If
556 Registration is pasased in return a Protocol Instance that was just add
557 to the system. If Retistration is NULL return the first Protocol Interface
562 Protocol - The protocol to search for
564 Registration - Optional Registration Key returned from RegisterProtocolNotify()
566 Interface - Return the Protocol interface (instance).
570 EFI_SUCCESS - If a valid Interface is returned
572 EFI_INVALID_PARAMETER - Invalid parameter
574 EFI_NOT_FOUND - Protocol interface not found
579 LOCATE_POSITION Position
;
580 PROTOCOL_NOTIFY
*ProtNotify
;
583 if (Interface
== NULL
) {
584 return EFI_INVALID_PARAMETER
;
587 if (Protocol
== NULL
) {
588 return EFI_NOT_FOUND
;
592 Status
= EFI_SUCCESS
;
595 // Set initial position
597 Position
.Protocol
= Protocol
;
598 Position
.SearchKey
= Registration
;
599 Position
.Position
= &gHandleList
;
602 // Lock the protocol database
604 CoreAcquireProtocolLock ();
606 mEfiLocateHandleRequest
+= 1;
608 if (NULL
== Registration
) {
610 // Look up the protocol entry and set the head pointer
612 Position
.ProtEntry
= CoreFindProtocolEntry (Protocol
, FALSE
);
613 if (Position
.ProtEntry
== NULL
) {
614 Status
= EFI_NOT_FOUND
;
617 Position
.Position
= &Position
.ProtEntry
->Protocols
;
619 Handle
= CoreGetNextLocateByProtocol (&Position
, Interface
);
621 Handle
= CoreGetNextLocateByRegisterNotify (&Position
, Interface
);
624 if (NULL
== Handle
) {
625 Status
= EFI_NOT_FOUND
;
626 } else if (NULL
!= Registration
) {
628 // If this is a search by register notify and a handle was
629 // returned, update the register notification position
631 ProtNotify
= Registration
;
632 ProtNotify
->Position
= ProtNotify
->Position
->ForwardLink
;
636 CoreReleaseProtocolLock ();
644 CoreLocateHandleBuffer (
645 IN EFI_LOCATE_SEARCH_TYPE SearchType
,
646 IN EFI_GUID
*Protocol OPTIONAL
,
647 IN VOID
*SearchKey OPTIONAL
,
648 IN OUT UINTN
*NumberHandles
,
649 OUT EFI_HANDLE
**Buffer
655 Function returns an array of handles that support the requested protocol
656 in a buffer allocated from pool. This is a version of CoreLocateHandle()
657 that allocates a buffer for the caller.
661 SearchType - Specifies which handle(s) are to be returned.
662 Protocol - Provides the protocol to search by.
663 This parameter is only valid for SearchType ByProtocol.
664 SearchKey - Supplies the search key depending on the SearchType.
665 NumberHandles - The number of handles returned in Buffer.
666 Buffer - A pointer to the buffer to return the requested array of
667 handles that support Protocol.
671 EFI_SUCCESS - The result array of handles was returned.
672 EFI_NOT_FOUND - No handles match the search.
673 EFI_OUT_OF_RESOURCES - There is not enough pool memory to store the matching results.
674 EFI_INVALID_PARAMETER - Invalid parameter
681 if (NumberHandles
== NULL
) {
682 return EFI_INVALID_PARAMETER
;
685 if (Buffer
== NULL
) {
686 return EFI_INVALID_PARAMETER
;
692 Status
= CoreLocateHandle (
700 // LocateHandleBuffer() returns incorrect status code if SearchType is
703 // Add code to correctly handle expected errors from CoreLocateHandle().
705 if (EFI_ERROR(Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
706 if (Status
!= EFI_INVALID_PARAMETER
) {
707 Status
= EFI_NOT_FOUND
;
712 *Buffer
= CoreAllocateBootServicesPool (BufferSize
);
713 if (*Buffer
== NULL
) {
714 return EFI_OUT_OF_RESOURCES
;
717 Status
= CoreLocateHandle (
725 *NumberHandles
= BufferSize
/sizeof(EFI_HANDLE
);
726 if (EFI_ERROR(Status
)) {