
Provide a command to dump
* all block devices * the protocol interfaces installed on these * the open protocol information
Signed-off-by: Heinrich Schuchardt heinrich.schuchardt@canonical.com --- When working on the EFI DM integration this command will us help to better understand the setup.
We might want to add some of the output to efidebug in future. --- cmd/Kconfig | 7 ++ cmd/Makefile | 1 + cmd/blkdump.c | 176 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 184 insertions(+) create mode 100644 cmd/blkdump.c
diff --git a/cmd/Kconfig b/cmd/Kconfig index bfa12ce12a..8c34a139fc 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -1850,6 +1850,13 @@ endif
menu "Misc commands"
+config CMD_BLKDUMP + bool "Enable 'blkdump' command" + depends on EFI_LOADER + default y + help + Dump open protocol information for block devices + config CMD_BMP bool "Enable 'bmp' command" depends on LCD || DM_VIDEO || VIDEO diff --git a/cmd/Makefile b/cmd/Makefile index cf6ce1bd6f..6ec219b3bc 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_CMD_AB_SELECT) += ab_select.o obj-$(CONFIG_CMD_ADC) += adc.o obj-$(CONFIG_CMD_ARMFLASH) += armflash.o obj-$(CONFIG_BLK) += blk_common.o +obj-$(CONFIG_CMD_BLKDUMP) += blkdump.o obj-$(CONFIG_CMD_BOOTDEV) += bootdev.o obj-$(CONFIG_CMD_BOOTFLOW) += bootflow.o obj-$(CONFIG_CMD_BOOTMETH) += bootmeth.o diff --git a/cmd/blkdump.c b/cmd/blkdump.c new file mode 100644 index 0000000000..936d92468b --- /dev/null +++ b/cmd/blkdump.c @@ -0,0 +1,176 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * The 'sbi' command displays information about the SBI implementation. + * + * Copyright (c) 2020, Heinrich Schuchardt xypron.glpk@gmx.de + */ + +#include <common.h> +#include <command.h> +#include <dm/device.h> +#include <efi_loader.h> + +/** + * print_handle() - print handle + * + * @handle: handle + */ +void print_handle(efi_handle_t handle) +{ + struct efi_handler *handler; + struct efi_device_path *dp; + efi_uintn_t ret; + + printf("%p", handle); + + if (handle->dev) + printf(" (%s)", handle->dev->name); + + ret = efi_search_protocol(handle, &efi_guid_device_path, &handler); + if (ret != EFI_SUCCESS) + goto out; + dp = handler->protocol_interface; + printf(" - %pD", dp); + +out: + printf("\n"); +} + +/** + * print_attributes() - print attributes + * + * @val: value + */ +void print_attributes(u32 val) +{ + const char *attr_text[] = { + "EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL", + "EFI_OPEN_PROTOCOL_GET_PROTOCOL", + "EFI_OPEN_PROTOCOL_TEST_PROTOCOL", + "EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER", + "EFI_OPEN_PROTOCOL_BY_DRIVER", + "EFI_OPEN_PROTOCOL_EXCLUSIVE", + NULL, + }; + u32 mask = 1; + int first = 0; + + for (const char **pos = attr_text; *pos; ++pos, mask <<= 1) { + if (mask & val) { + if (first) { + printf(" | "); + ++first; + } + printf(*pos); + } + } + printf("\n"); +} + +/** + * print_open_protocol_information() print open protocol information + * + * @handle: handle + * @prot: protocol GUID + */ +void print_open_protocol_information(efi_handle_t handle, efi_guid_t *prot) +{ + efi_status_t ret; + struct efi_open_protocol_info_entry *buffer; + efi_uintn_t count; + + ret = EFI_CALL(systab.boottime->open_protocol_information( + handle, prot, &buffer, &count)); + if (ret == EFI_NOT_FOUND) { + printf("Handle doesn't support specified protocol\n"); + return; + } + if (ret != EFI_SUCCESS) { + printf("Failed to get open protocol information\n"); + return; + } + + for (efi_uintn_t i = 0; i < count; ++i) { + struct efi_open_protocol_info_entry *info = &buffer[i]; + + printf(" AgentHandle - "); + print_handle(info->agent_handle); + printf(" ControllerHandle - "); + print_handle(info->controller_handle); + printf(" Attributes - "); + print_attributes(info->attributes); + printf(" OpenCount - %d\n", info->open_count); + } + + if (buffer) + efi_free_pool(buffer); +} + +/** + * print_handle() - print protocols installed on handle + * + * @handle: handle + */ +void print_protocols(efi_handle_t handle) +{ + efi_guid_t **buffer = NULL; + efi_uintn_t count; + efi_status_t ret; + + ret = EFI_CALL(systab.boottime->protocols_per_handle( + handle, &buffer, &count)); + if (ret != EFI_SUCCESS) { + printf("Can't get protocols\n\n"); + return; + } + for (efi_uintn_t i = 0; i < count; ++i) { + efi_guid_t *prot = buffer[i]; + + printf(" protocol: %pUl - %pUs\n", prot, prot); + print_open_protocol_information(handle, prot); + } + if (buffer) + efi_free_pool(buffer); +} + +static int do_blkdump(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + efi_handle_t *handles = NULL; + efi_uintn_t no_handles; + efi_status_t ret; + + /* Initialize UEFI drivers */ + ret = efi_init_obj_list(); + if (ret != EFI_SUCCESS) { + printf("Cannot initialize UEFI sub-system"); + return CMD_RET_FAILURE; + } + + ret = EFI_CALL(efi_locate_handle_buffer(BY_PROTOCOL, + &efi_block_io_guid, NULL, + &no_handles, &handles)); + if (ret != EFI_SUCCESS) { + printf("Could not locate handles\n"); + return CMD_RET_FAILURE; + } + for (efi_uintn_t i = 0; i < no_handles; ++i) { + efi_handle_t h = handles[i]; + + print_handle(h); + print_protocols(h); + printf("\n"); + } + + if (handles) + efi_free_pool(handles); + + + return CMD_RET_SUCCESS; +} + +U_BOOT_CMD_COMPLETE( + blkdump, 1, 0, do_blkdump, + "display EFI block devices", + NULL, NULL +);