summaryrefslogtreecommitdiff
path: root/EDK/Foundation/Library/Dxe/EfiDriverLib/Handle.c
diff options
context:
space:
mode:
Diffstat (limited to 'EDK/Foundation/Library/Dxe/EfiDriverLib/Handle.c')
-rw-r--r--EDK/Foundation/Library/Dxe/EfiDriverLib/Handle.c176
1 files changed, 176 insertions, 0 deletions
diff --git a/EDK/Foundation/Library/Dxe/EfiDriverLib/Handle.c b/EDK/Foundation/Library/Dxe/EfiDriverLib/Handle.c
new file mode 100644
index 0000000..b440a10
--- /dev/null
+++ b/EDK/Foundation/Library/Dxe/EfiDriverLib/Handle.c
@@ -0,0 +1,176 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Handle.c
+
+Abstract:
+
+ Support for Handle lib fucntions.
+
+--*/
+
+#include "Tiano.h"
+#include "EfiDriverLib.h"
+
+EFI_STATUS
+EfiLibLocateHandleProtocolByProtocols (
+ IN OUT EFI_HANDLE * Handle, OPTIONAL
+ OUT VOID **Interface, OPTIONAL
+ ...
+ )
+/*++
+Routine Description:
+
+ Function locates Protocol and/or Handle on which all Protocols specified
+ as a variable list are installed.
+ It supports continued search. The caller must assure that no handles are added
+ or removed while performing continued search, by e.g., rising the TPL and not
+ calling any handle routines. Otherwise the behavior is undefined.
+
+Arguments:
+
+ Handle - The address of handle to receive the handle on which protocols
+ indicated by the variable list are installed.
+ If points to NULL, all handles are searched. If pointing to a
+ handle returned from previous call, searches starting from next handle.
+ If NULL, the parameter is ignored.
+
+ Interface - The address of a pointer to a protocol interface that will receive
+ the interface indicated by first variable argument.
+ If NULL, the parameter is ignored.
+
+ ... - A variable argument list containing protocol GUIDs. Must end with NULL.
+
+Returns:
+
+ EFI_SUCCESS - All the protocols where found on same handle.
+ EFI_NOT_FOUND - A Handle with all the protocols installed was not found.
+ Other values as may be returned from LocateHandleBuffer() or HandleProtocol().
+
+--*/
+{
+ VA_LIST args;
+ EFI_STATUS Status;
+ EFI_GUID *Protocol;
+ EFI_GUID *ProtocolFirst;
+ EFI_HANDLE *HandleBuffer;
+ UINTN NumberOfHandles;
+ UINTN Idx;
+ VOID *AnInterface;
+
+ AnInterface = NULL;
+ VA_START (args, Interface);
+ ProtocolFirst = VA_ARG (args, EFI_GUID *);
+
+ //
+ // Get list of all handles that support the first protocol.
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ ProtocolFirst,
+ NULL,
+ &NumberOfHandles,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Check if this is a countinuation of handle searching.
+ //
+ Idx = 0;
+ if ((Handle != NULL) && (*Handle != NULL)) {
+ //
+ // Leave the Idx just beyond the matching handle.
+ //
+ for (; Idx < NumberOfHandles;) {
+ if (*Handle == HandleBuffer[Idx++]) {
+ break;
+ }
+ }
+ }
+
+ //
+ // Iterate handles testing for presence of remaining protocols.
+ //
+ for (; Idx < NumberOfHandles; Idx++) {
+
+ //
+ // Start with the second protocol, the first one is sure on this handle.
+ //
+ VA_START (args, Interface);
+ VA_ARG (args, EFI_GUID *);
+
+ //
+ // Iterate protocols from the variable list.
+ //
+ while (TRUE) {
+
+ Protocol = VA_ARG (args, EFI_GUID *);
+
+ if (Protocol == NULL) {
+
+ //
+ // If here, the list was iterated successfully
+ // finding each protocol on a single handle.
+ //
+
+ Status = EFI_SUCCESS;
+
+ //
+ // OPTIONAL parameter returning the Handle.
+ //
+ if (Handle != NULL) {
+ *Handle = HandleBuffer[Idx];
+ }
+
+ //
+ // OPTIONAL parameter returning the first rotocol's Interface.
+ //
+ if (Interface != NULL) {
+ Status = gBS->HandleProtocol (
+ HandleBuffer[Idx],
+ ProtocolFirst,
+ Interface
+ );
+ }
+
+ goto lbl_out;
+ }
+
+ Status = gBS->HandleProtocol (
+ HandleBuffer[Idx],
+ Protocol,
+ &AnInterface
+ );
+ if (EFI_ERROR (Status)) {
+
+ //
+ // This handle does not have the iterated protocol.
+ //
+ break;
+ }
+ }
+
+ }
+
+ //
+ // If here, no handle that bears all the protocols was found.
+ //
+ Status = EFI_NOT_FOUND;
+
+lbl_out:
+ gBS->FreePool (HandleBuffer);
+ return Status;
+}