From 736fcf60d1db389941b4f15f94c31fe0403552a8 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 31 Jul 2014 00:09:58 +0100 Subject: [PATCH] [efi] Add ability to dump all openers of a given protocol on a handle Signed-off-by: Michael Brown --- src/include/ipxe/efi/efi.h | 27 +++++++++++- src/interface/efi/efi_debug.c | 83 +++++++++++++++++++++++++++++++++-- 2 files changed, 106 insertions(+), 4 deletions(-) diff --git a/src/include/ipxe/efi/efi.h b/src/include/ipxe/efi/efi.h index b5537dd6..51b501c1 100644 --- a/src/include/ipxe/efi/efi.h +++ b/src/include/ipxe/efi/efi.h @@ -153,22 +153,47 @@ extern const char * efi_devpath_text ( EFI_DEVICE_PATH_PROTOCOL *path ); extern const char * efi_handle_devpath_text ( EFI_HANDLE handle ); extern const char * efi_handle_name ( EFI_HANDLE handle ); +extern void dbg_efi_openers ( EFI_HANDLE handle, EFI_GUID *protocol ); extern void dbg_efi_protocols ( EFI_HANDLE handle ); +#define DBG_EFI_OPENERS_IF( level, handle, protocol ) do { \ + if ( DBG_ ## level ) { \ + dbg_efi_openers ( handle, protocol ); \ + } \ + } while ( 0 ) + #define DBG_EFI_PROTOCOLS_IF( level, handle ) do { \ if ( DBG_ ## level ) { \ dbg_efi_protocols ( handle ); \ } \ } while ( 0 ) +#define DBGC_EFI_OPENERS_IF( level, id, ... ) do { \ + DBG_AC_IF ( level, id ); \ + DBG_EFI_OPENERS_IF ( level, __VA_ARGS__ ); \ + DBG_DC_IF ( level ); \ + } while ( 0 ) + #define DBGC_EFI_PROTOCOLS_IF( level, id, ... ) do { \ DBG_AC_IF ( level, id ); \ DBG_EFI_PROTOCOLS_IF ( level, __VA_ARGS__ ); \ DBG_DC_IF ( level ); \ } while ( 0 ) +#define DBGC_EFI_OPENERS( ... ) \ + DBGC_EFI_OPENERS_IF ( LOG, ##__VA_ARGS__ ) #define DBGC_EFI_PROTOCOLS( ... ) \ - DBGC_EFI_PROTOCOLS_IF( LOG, ##__VA_ARGS__ ) + DBGC_EFI_PROTOCOLS_IF ( LOG, ##__VA_ARGS__ ) + +#define DBGC2_EFI_OPENERS( ... ) \ + DBGC_EFI_OPENERS_IF ( EXTRA, ##__VA_ARGS__ ) +#define DBGC2_EFI_PROTOCOLS( ... ) \ + DBGC_EFI_PROTOCOLS_IF ( EXTRA, ##__VA_ARGS__ ) + +#define DBGCP_EFI_OPENERS( ... ) \ + DBGC_EFI_OPENERS_IF ( PROFILE, ##__VA_ARGS__ ) +#define DBGCP_EFI_PROTOCOLS( ... ) \ + DBGC_EFI_PROTOCOLS_IF ( PROFILE, ##__VA_ARGS__ ) extern EFI_STATUS efi_init ( EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *systab ); diff --git a/src/interface/efi/efi_debug.c b/src/interface/efi/efi_debug.c index b3cb9cb5..21bb5fc6 100644 --- a/src/interface/efi/efi_debug.c +++ b/src/interface/efi/efi_debug.c @@ -183,6 +183,77 @@ const char * efi_guid_ntoa ( EFI_GUID *guid ) { return uuid_ntoa ( &u.uuid ); } +/** + * Name protocol open attributes + * + * @v attributes Protocol open attributes + * @ret name Protocol open attributes name + * + * Returns a (static) string with characters for each set bit + * corresponding to BY_(H)ANDLE_PROTOCOL, (G)ET_PROTOCOL, + * (T)EST_PROTOCOL, BY_(C)HILD_CONTROLLER, BY_(D)RIVER, and + * E(X)CLUSIVE. + */ +static const char * efi_open_attributes_name ( unsigned int attributes ) { + static char attribute_chars[] = "HGTCDX"; + static char name[ sizeof ( attribute_chars ) ]; + char *tmp = name; + unsigned int i; + + for ( i = 0 ; i < ( sizeof ( attribute_chars ) - 1 ) ; i++ ) { + if ( attributes & ( 1 << i ) ) + *(tmp++) = attribute_chars[i]; + } + *tmp = '\0'; + + return name; +} + +/** + * Print list of openers of a given protocol on a given handle + * + * @v handle EFI handle + * @v protocol Protocol GUID + */ +void dbg_efi_openers ( EFI_HANDLE handle, EFI_GUID *protocol ) { + EFI_BOOT_SERVICES *bs = efi_systab->BootServices; + EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *openers; + EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *opener; + UINTN count; + unsigned int i; + EFI_STATUS efirc; + int rc; + + /* Retrieve list of openers */ + if ( ( efirc = bs->OpenProtocolInformation ( handle, protocol, &openers, + &count ) ) != 0 ) { + rc = -EEFI ( efirc ); + printf ( "EFI could not retrieve openers for %s on %p: %s\n", + efi_guid_ntoa ( protocol ), handle, strerror ( rc ) ); + return; + } + + /* Dump list of openers */ + for ( i = 0 ; i < count ; i++ ) { + opener = &openers[i]; + printf ( "HANDLE %p %s %s opened %dx (%s)", + handle, efi_handle_name ( handle ), + efi_guid_ntoa ( protocol ), opener->OpenCount, + efi_open_attributes_name ( opener->Attributes ) ); + printf ( " by %p %s", opener->AgentHandle, + efi_handle_name ( opener->AgentHandle ) ); + if ( opener->ControllerHandle == handle ) { + printf ( "\n" ); + } else { + printf ( " for %p %s\n", opener->ControllerHandle, + efi_handle_name ( opener->ControllerHandle ) ); + } + } + + /* Free list */ + bs->FreePool ( openers ); +} + /** * Print list of protocol handlers attached to a handle * @@ -190,7 +261,8 @@ const char * efi_guid_ntoa ( EFI_GUID *guid ) { */ void dbg_efi_protocols ( EFI_HANDLE handle ) { EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - EFI_GUID **protocols; + EFI_GUID **protocols; + EFI_GUID *protocol; UINTN count; unsigned int i; EFI_STATUS efirc; @@ -206,8 +278,13 @@ void dbg_efi_protocols ( EFI_HANDLE handle ) { } /* Dump list of protocols */ - for ( i = 0 ; i < count ; i++ ) - printf ( "%s\n", efi_guid_ntoa ( protocols[i] ) ); + for ( i = 0 ; i < count ; i++ ) { + protocol = protocols[i]; + printf ( "HANDLE %p %s %s supported\n", + handle, efi_handle_name ( handle ), + efi_guid_ntoa ( protocol ) ); + dbg_efi_openers ( handle, protocol ); + } /* Free list */ bs->FreePool ( protocols );