To allow easier observability into the newly added cdev alias functionality, extend devlookup to be able to resolve them.
Signed-off-by: Ahmad Fatoum <a.fat...@pengutronix.de> --- commands/Kconfig | 2 +- commands/devlookup.c | 50 +++++++++++++++++++++++++++++++++++++------- include/stringlist.h | 6 ++++++ 3 files changed, 50 insertions(+), 8 deletions(-) diff --git a/commands/Kconfig b/commands/Kconfig index ca3f13d7e0cc..7eff747ffdb6 100644 --- a/commands/Kconfig +++ b/commands/Kconfig @@ -92,7 +92,7 @@ config CMD_DEVLOOKUP help Look up device behind device file and its parameters - devlookup [-v VAR] /dev/DEVICE [parameter] + devlookup [-v VAR] [-ka] /dev/DEVICE [parameter] Detects the device behind a device file and outputs it, unless a second argument is given. In that case the device diff --git a/commands/devlookup.c b/commands/devlookup.c index 0d4c6e808b60..5877d5f1b82c 100644 --- a/commands/devlookup.c +++ b/commands/devlookup.c @@ -9,17 +9,25 @@ #include <linux/ctype.h> #include <environment.h> #include <block.h> +#include <stringlist.h> + +static int devlookup_process(struct cdev *cdev, void *sl) +{ + string_list_add(sl, cdev->name); + return 1; +} static int do_devlookup(int argc, char *argv[]) { const char *variable = NULL, *devicefile, *paramname; - struct cdev *cdev; + struct cdev *cdev = NULL; int opt, ret; - bool kernelopt = false; + bool alias = false, kernelopt = false; const char *val; - char *buf = NULL; + char *aliasbuf = NULL, *buf = NULL; + struct string_list sl; - while ((opt = getopt(argc, argv, "v:k")) > 0) { + while ((opt = getopt(argc, argv, "v:ka")) > 0) { switch(opt) { case 'v': variable = optarg; @@ -27,6 +35,9 @@ static int do_devlookup(int argc, char *argv[]) case 'k': kernelopt = true; break; + case 'a': + alias = true; + break; } } @@ -39,12 +50,33 @@ static int do_devlookup(int argc, char *argv[]) devicefile = argv[0]; paramname = argv[1]; + string_list_init(&sl); + + ret = cdev_alias_resolve_for_each(devicefile, devlookup_process, &sl); + if (ret < 0) + goto out; + else if (ret > 1) { + aliasbuf = string_list_join(&sl, " "); + if (string_list_count(&sl) > 1 && (kernelopt || paramname)) { + printf("Option not supported for multi cdev alias\n"); + return COMMAND_ERROR; + } + + if (alias) { + ret = cmd_export_val(variable, aliasbuf); + goto out; + } + + devicefile = aliasbuf; + } + devicefile = devpath_to_name(devicefile); cdev = cdev_open_by_name(devicefile, O_RDONLY); if (!cdev) { printf("devlookup: cdev %s not found\n", devicefile); - return -ENOENT; + ret = -ENOENT; + goto out; } if (!cdev->dev) { @@ -62,8 +94,11 @@ static int do_devlookup(int argc, char *argv[]) ret = cmd_export_val(variable, val); out: + string_list_free(&sl); + free(aliasbuf); free(buf); - cdev_close(cdev); + if (cdev) + cdev_close(cdev); return ret; } @@ -76,12 +111,13 @@ BAREBOX_CMD_HELP_TEXT("") BAREBOX_CMD_HELP_TEXT("Options:") BAREBOX_CMD_HELP_OPT ("-v", "write output to VARIABLE instead of printing it") BAREBOX_CMD_HELP_OPT ("-k", "output kernel rootarg line") +BAREBOX_CMD_HELP_OPT ("-a", "output resolution of cdev alias") BAREBOX_CMD_HELP_END BAREBOX_CMD_START(devlookup) .cmd = do_devlookup, BAREBOX_CMD_DESC("look up device behind device file and its parameters") - BAREBOX_CMD_OPTS("[-v VAR] [-k] /dev/DEVICE [parameter]") + BAREBOX_CMD_OPTS("[-v VAR] [-ka] /dev/DEVICE [parameter]") BAREBOX_CMD_GROUP(CMD_GRP_SCRIPT) BAREBOX_CMD_HELP(cmd_devlookup_help) BAREBOX_CMD_END diff --git a/include/stringlist.h b/include/stringlist.h index dcfd33c6e064..b964fabd2320 100644 --- a/include/stringlist.h +++ b/include/stringlist.h @@ -3,6 +3,7 @@ #define __STRINGLIST_H #include <linux/list.h> +#include <linux/string.h> #include <malloc.h> struct string_list { @@ -24,6 +25,11 @@ static inline void string_list_init(struct string_list *sl) sl->str = NULL; } +static inline size_t string_list_count(struct string_list *sl) +{ + return list_count_nodes(&sl->list); +} + static inline void string_list_free(struct string_list *sl) { struct string_list *entry, *safe; -- 2.39.5