[v4,4/9] cmd: efitool: add drivers command

Message ID 20190115025522.12060-5-takahiro.akashi@linaro.org
State New
Headers show
Series
  • cmd: add efitool for efi environment
Related show

Commit Message

AKASHI Takahiro Jan. 15, 2019, 2:55 a.m.
"drivers" command prints all the uefi drivers on the system.

=> efi drivers
D
r
v                Driver Name          Image Path

Comments

Heinrich Schuchardt Jan. 15, 2019, 3:39 a.m. | #1
On 1/15/19 3:55 AM, AKASHI Takahiro wrote:
> "drivers" command prints all the uefi drivers on the system.
> 
> => efi drivers
> D
> r
> v                Driver Name          Image Path
> ================ ==================== ==========
>         7ef31d30 EFI block driver     <built-in>
> 
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> ---
>  cmd/efitool.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 83 insertions(+), 1 deletion(-)
> 
> diff --git a/cmd/efitool.c b/cmd/efitool.c
> index 6b2df1beedb5..4d46721fbf91 100644
> --- a/cmd/efitool.c
> +++ b/cmd/efitool.c
> @@ -8,6 +8,7 @@
>  #include <charset.h>
>  #include <common.h>
>  #include <command.h>
> +#include <efi_driver.h>
>  #include <efi_loader.h>
>  #include <environment.h>
>  #include <errno.h>
> @@ -16,6 +17,7 @@
>  #include <malloc.h>
>  #include <search.h>
>  #include <linux/ctype.h>
> +#include <linux/kernel.h>
>  #include <asm/global_data.h>
>  
>  #define BS systab.boottime
> @@ -358,6 +360,82 @@ static int do_efi_show_devices(int argc, char * const argv[])
>  	return CMD_RET_SUCCESS;
>  }
>  
> +static int efi_get_driver_handle_info(efi_handle_t handle, u16 **name,
> +				      u16 **devname, u16 **filename)
> +{
> +	struct efi_handler *handler;
> +	struct efi_driver_binding_extended_protocol *bp;

We can have drivers supplied by U-Boot and drivers supplied by an EFI
binary that we recently installed via the bootefi command.

A driver installed via the bootefi command will not have allocated
memory for the extra fields. So the rest of the code accessing the name
field will produce an illegal memory access.

Best regards

Heinrich

> +	efi_status_t ret;
> +
> +	ret = efi_search_protocol(handle, &efi_guid_driver_binding_protocol,
> +				  &handler);
> +	if (ret != EFI_SUCCESS)
> +		return -1;
> +	bp = handler->protocol_interface;
> +
> +	*name = malloc((strlen(bp->name) + 1) * sizeof(u16));
> +	if (*name)
> +		ascii2unicode(*name, bp->name);
> +
> +	/*
> +	 * TODO:
> +	 * handle image->device_handle,
> +	 * use append_device_path()
> +	 */
> +	*devname = NULL;
> +	*filename = NULL;
> +
> +	return 0;
> +}
> +
> +static int do_efi_show_drivers(int argc, char * const argv[])
> +{
> +	efi_handle_t *handles = NULL, *handle;
> +	efi_uintn_t size = 0;
> +	u16 *drvname, *devname, *filename;
> +	efi_status_t ret;
> +	int i;
> +
> +	ret = BS->locate_handle(BY_PROTOCOL, &efi_guid_driver_binding_protocol,
> +				NULL, &size, NULL);
> +	if (ret == EFI_BUFFER_TOO_SMALL) {
> +		handles = calloc(1, size);
> +		if (!handles)
> +			return CMD_RET_FAILURE;
> +
> +		ret = BS->locate_handle(BY_PROTOCOL,
> +					&efi_guid_driver_binding_protocol,
> +					NULL, &size, handles);
> +	}
> +	if (ret != EFI_SUCCESS) {
> +		free(handles);
> +		return CMD_RET_FAILURE;
> +	}
> +
> +	printf("D\n");
> +	printf("r\n");
> +	printf("v                Driver Name          Image Path\n");
> +	printf("================ ==================== ==========\n");
> +	handle = handles;
> +	for (i = 0; i < size / sizeof(*handle); i++) {
> +		if (!efi_get_driver_handle_info(*handle, &drvname, &devname,
> +						&filename)) {
> +			if (filename)
> +				printf("%16p %-20ls %ls/%ls\n",
> +				       *handle, drvname, devname, filename);
> +			else
> +				printf("%16p %-20ls <built-in>\n",
> +				       *handle, drvname);
> +			free(drvname);
> +			free(devname);
> +			free(filename);
> +		}
> +		handle++;
> +	}
> +
> +	return CMD_RET_SUCCESS;
> +}
> +
>  static int do_efi_boot_add(int argc, char * const argv[])
>  {
>  	int id;
> @@ -767,6 +845,8 @@ static int do_efitool(cmd_tbl_t *cmdtp, int flag,
>  		return do_efi_set_var(argc, argv);
>  	else if (!strcmp(command, "devices"))
>  		return do_efi_show_devices(argc, argv);
> +	else if (!strcmp(command, "drivers"))
> +		return do_efi_show_drivers(argc, argv);
>  	else
>  		return CMD_RET_USAGE;
>  }
> @@ -793,7 +873,9 @@ static char efitool_help_text[] =
>  	"  - set/delete uefi variable's value\n"
>  	"    <value> may be \"=\"...\"\", \"=0x...\", \"=H...\", (set) or \"=\" (delete)\n"
>  	"efitool devices\n"
> -	"  - show uefi devices\n";
> +	"  - show uefi devices\n"
> +	"efitool drivers\n"
> +	"  - show uefi drivers\n";
>  #endif
>  
>  U_BOOT_CMD(
>

Patch

================ ==================== ==========
        7ef31d30 EFI block driver     <built-in>

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 cmd/efitool.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 83 insertions(+), 1 deletion(-)

diff --git a/cmd/efitool.c b/cmd/efitool.c
index 6b2df1beedb5..4d46721fbf91 100644
--- a/cmd/efitool.c
+++ b/cmd/efitool.c
@@ -8,6 +8,7 @@ 
 #include <charset.h>
 #include <common.h>
 #include <command.h>
+#include <efi_driver.h>
 #include <efi_loader.h>
 #include <environment.h>
 #include <errno.h>
@@ -16,6 +17,7 @@ 
 #include <malloc.h>
 #include <search.h>
 #include <linux/ctype.h>
+#include <linux/kernel.h>
 #include <asm/global_data.h>
 
 #define BS systab.boottime
@@ -358,6 +360,82 @@  static int do_efi_show_devices(int argc, char * const argv[])
 	return CMD_RET_SUCCESS;
 }
 
+static int efi_get_driver_handle_info(efi_handle_t handle, u16 **name,
+				      u16 **devname, u16 **filename)
+{
+	struct efi_handler *handler;
+	struct efi_driver_binding_extended_protocol *bp;
+	efi_status_t ret;
+
+	ret = efi_search_protocol(handle, &efi_guid_driver_binding_protocol,
+				  &handler);
+	if (ret != EFI_SUCCESS)
+		return -1;
+	bp = handler->protocol_interface;
+
+	*name = malloc((strlen(bp->name) + 1) * sizeof(u16));
+	if (*name)
+		ascii2unicode(*name, bp->name);
+
+	/*
+	 * TODO:
+	 * handle image->device_handle,
+	 * use append_device_path()
+	 */
+	*devname = NULL;
+	*filename = NULL;
+
+	return 0;
+}
+
+static int do_efi_show_drivers(int argc, char * const argv[])
+{
+	efi_handle_t *handles = NULL, *handle;
+	efi_uintn_t size = 0;
+	u16 *drvname, *devname, *filename;
+	efi_status_t ret;
+	int i;
+
+	ret = BS->locate_handle(BY_PROTOCOL, &efi_guid_driver_binding_protocol,
+				NULL, &size, NULL);
+	if (ret == EFI_BUFFER_TOO_SMALL) {
+		handles = calloc(1, size);
+		if (!handles)
+			return CMD_RET_FAILURE;
+
+		ret = BS->locate_handle(BY_PROTOCOL,
+					&efi_guid_driver_binding_protocol,
+					NULL, &size, handles);
+	}
+	if (ret != EFI_SUCCESS) {
+		free(handles);
+		return CMD_RET_FAILURE;
+	}
+
+	printf("D\n");
+	printf("r\n");
+	printf("v                Driver Name          Image Path\n");
+	printf("================ ==================== ==========\n");
+	handle = handles;
+	for (i = 0; i < size / sizeof(*handle); i++) {
+		if (!efi_get_driver_handle_info(*handle, &drvname, &devname,
+						&filename)) {
+			if (filename)
+				printf("%16p %-20ls %ls/%ls\n",
+				       *handle, drvname, devname, filename);
+			else
+				printf("%16p %-20ls <built-in>\n",
+				       *handle, drvname);
+			free(drvname);
+			free(devname);
+			free(filename);
+		}
+		handle++;
+	}
+
+	return CMD_RET_SUCCESS;
+}
+
 static int do_efi_boot_add(int argc, char * const argv[])
 {
 	int id;
@@ -767,6 +845,8 @@  static int do_efitool(cmd_tbl_t *cmdtp, int flag,
 		return do_efi_set_var(argc, argv);
 	else if (!strcmp(command, "devices"))
 		return do_efi_show_devices(argc, argv);
+	else if (!strcmp(command, "drivers"))
+		return do_efi_show_drivers(argc, argv);
 	else
 		return CMD_RET_USAGE;
 }
@@ -793,7 +873,9 @@  static char efitool_help_text[] =
 	"  - set/delete uefi variable's value\n"
 	"    <value> may be \"=\"...\"\", \"=0x...\", \"=H...\", (set) or \"=\" (delete)\n"
 	"efitool devices\n"
-	"  - show uefi devices\n";
+	"  - show uefi devices\n"
+	"efitool drivers\n"
+	"  - show uefi drivers\n";
 #endif
 
 U_BOOT_CMD(