[RFC 1/1] cmd: add command to dump EFI block devices

Heinrich Schuchardt heinrich.schuchardt at canonical.com
Tue Oct 4 14:33:50 CEST 2022


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 at 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 at 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
+);
-- 
2.37.2



More information about the U-Boot mailing list