diff options
Diffstat (limited to 'cmd/bootdev.c')
| -rw-r--r-- | cmd/bootdev.c | 120 | 
1 files changed, 120 insertions, 0 deletions
| diff --git a/cmd/bootdev.c b/cmd/bootdev.c new file mode 100644 index 00000000000..ecd797c0503 --- /dev/null +++ b/cmd/bootdev.c @@ -0,0 +1,120 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * 'bootdev' command + * + * Copyright 2021 Google LLC + * Written by Simon Glass <sjg@chromium.org> + */ + +#include <common.h> +#include <bootdev.h> +#include <bootflow.h> +#include <bootstd.h> +#include <command.h> +#include <dm.h> +#include <dm/device-internal.h> +#include <dm/uclass-internal.h> + +static int bootdev_check_state(struct bootstd_priv **stdp) +{ +	struct bootstd_priv *std; +	int ret; + +	ret = bootstd_get_priv(&std); +	if (ret) +		return ret; +	if (!std->cur_bootdev) { +		printf("Please use 'bootdev select' first\n"); +		return -ENOENT; +	} +	*stdp = std; + +	return 0; +} + +static int do_bootdev_list(struct cmd_tbl *cmdtp, int flag, int argc, +			   char *const argv[]) +{ +	bool probe; + +	probe = argc >= 2 && !strcmp(argv[1], "-p"); +	bootdev_list(probe); + +	return 0; +} + +static int do_bootdev_select(struct cmd_tbl *cmdtp, int flag, int argc, +			     char *const argv[]) +{ +	struct bootstd_priv *std; +	struct udevice *dev; +	int ret; + +	ret = bootstd_get_priv(&std); +	if (ret) +		return CMD_RET_FAILURE; +	if (argc < 2) { +		std->cur_bootdev = NULL; +		return 0; +	} +	if (bootdev_find_by_any(argv[1], &dev)) +		return CMD_RET_FAILURE; + +	std->cur_bootdev = dev; + +	return 0; +} + +static int do_bootdev_info(struct cmd_tbl *cmdtp, int flag, int argc, +			   char *const argv[]) +{ +	struct bootstd_priv *priv; +	struct bootflow *bflow; +	int ret, i, num_valid; +	struct udevice *dev; +	bool probe; + +	probe = argc >= 2 && !strcmp(argv[1], "-p"); + +	ret = bootdev_check_state(&priv); +	if (ret) +		return CMD_RET_FAILURE; + +	dev = priv->cur_bootdev; + +	/* Count the number of bootflows, including how many are valid*/ +	num_valid = 0; +	for (ret = bootdev_first_bootflow(dev, &bflow), i = 0; +	     !ret; +	     ret = bootdev_next_bootflow(&bflow), i++) +		num_valid += bflow->state == BOOTFLOWST_READY; + +	/* +	 * Prove the device, if requested, otherwise assume that there is no +	 * error +	 */ +	ret = 0; +	if (probe) +		ret = device_probe(dev); + +	printf("Name:      %s\n", dev->name); +	printf("Sequence:  %d\n", dev_seq(dev)); +	printf("Status:    %s\n", ret ? simple_itoa(ret) : device_active(dev) ? +		"Probed" : "OK"); +	printf("Uclass:    %s\n", dev_get_uclass_name(dev_get_parent(dev))); +	printf("Bootflows: %d (%d valid)\n", i, num_valid); + +	return 0; +} + +#ifdef CONFIG_SYS_LONGHELP +static char bootdev_help_text[] = +	"list [-p]      - list all available bootdevs (-p to probe)\n" +	"bootdev select <bd>    - select a bootdev by name | label | seq\n" +	"bootdev info [-p]      - show information about a bootdev (-p to probe)"; +#endif + +U_BOOT_CMD_WITH_SUBCMDS(bootdev, "Boot devices", bootdev_help_text, +	U_BOOT_SUBCMD_MKENT(list, 2, 1, do_bootdev_list), +	U_BOOT_SUBCMD_MKENT(select, 2, 1, do_bootdev_select), +	U_BOOT_SUBCMD_MKENT(info, 2, 1, do_bootdev_info)); | 
