From 3d01254140fc9e5e900d739cb97bd9fba6aa2b68 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 17 Jan 2023 10:47:12 -0700 Subject: dm: core: Support sorting devices with dm tree Add a -s flag to sort the top-level devices in order of uclass ID. Signed-off-by: Simon Glass --- cmd/dm.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'cmd') diff --git a/cmd/dm.c b/cmd/dm.c index 218be85795d..979cd36061e 100644 --- a/cmd/dm.c +++ b/cmd/dm.c @@ -59,7 +59,11 @@ static int do_dm_dump_static_driver_info(struct cmd_tbl *cmdtp, int flag, static int do_dm_dump_tree(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { - dm_dump_tree(); + bool sort; + + sort = argc > 1 && !strcmp(argv[1], "-s"); + + dm_dump_tree(sort); return 0; } @@ -87,7 +91,7 @@ static char dm_help_text[] = "dm drivers Dump list of drivers with uclass and instances\n" DM_MEM_HELP "dm static Dump list of drivers with static platform data\n" - "dm tree Dump tree of driver model devices ('*' = activated)\n" + "dm tree [-s] Dump tree of driver model devices (-s=sort)\n" "dm uclass Dump list of instances for each uclass" ; #endif @@ -98,5 +102,5 @@ U_BOOT_CMD_WITH_SUBCMDS(dm, "Driver model low level access", dm_help_text, U_BOOT_SUBCMD_MKENT(drivers, 1, 1, do_dm_dump_drivers), DM_MEM U_BOOT_SUBCMD_MKENT(static, 1, 1, do_dm_dump_static_driver_info), - U_BOOT_SUBCMD_MKENT(tree, 1, 1, do_dm_dump_tree), + U_BOOT_SUBCMD_MKENT(tree, 2, 1, do_dm_dump_tree), U_BOOT_SUBCMD_MKENT(uclass, 1, 1, do_dm_dump_uclass)); -- cgit v1.3.1 From f1779f2cc3b91ccf2ebb1ec7fcd703c3a3d20cef Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 17 Jan 2023 10:47:20 -0700 Subject: vbe: Avoid a build failure when bloblist is not enabled This needs to be able to work (at least partially) without the bloblist active. Add a condition for this. Signed-off-by: Simon Glass --- cmd/vbe.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'cmd') diff --git a/cmd/vbe.c b/cmd/vbe.c index befaf07c64d..600690394eb 100644 --- a/cmd/vbe.c +++ b/cmd/vbe.c @@ -79,10 +79,13 @@ static int do_vbe_info(struct cmd_tbl *cmdtp, int flag, int argc, static int do_vbe_state(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { - struct vbe_handoff *handoff; + struct vbe_handoff *handoff = NULL; int i; - handoff = bloblist_find(BLOBLISTT_VBE, sizeof(struct vbe_handoff)); + if (IS_ENABLED(CONFIG_BLOBLIST)) { + handoff = bloblist_find(BLOBLISTT_VBE, + sizeof(struct vbe_handoff)); + } if (!handoff) { printf("No VBE state\n"); return CMD_RET_FAILURE; -- cgit v1.3.1 From bd90b092882099afa3786829036c82d6a4241fc8 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 17 Jan 2023 10:47:33 -0700 Subject: bootstd: Add the concept of a bootdev hunter Some bootdevs must be enumerated before they appear. For example, USB bootdevs are not visible until USB is enumerated. With standard boot this needs to happen automatically, since we only want to enumerate a bus if it is needed. Add a way to define bootdev 'hunters' which can be used to hunt for bootdevs of a given type. Track which ones have been used and add a command to list them. Include a clang work-around which seems to be needed. Signed-off-by: Simon Glass --- boot/bootdev-uclass.c | 31 +++++++++++++++++++++++++++ cmd/bootdev.c | 35 ++++++++++++++++++++++++++++--- include/bootdev.h | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++ include/bootstd.h | 3 +++ test/boot/bootdev.c | 52 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 176 insertions(+), 3 deletions(-) (limited to 'cmd') diff --git a/boot/bootdev-uclass.c b/boot/bootdev-uclass.c index 0ef3daf24cb..62eb0b617cd 100644 --- a/boot/bootdev-uclass.c +++ b/boot/bootdev-uclass.c @@ -636,6 +636,37 @@ int bootdev_setup_iter_order(struct bootflow_iter *iter, struct udevice **devp) return 0; } +void bootdev_list_hunters(struct bootstd_priv *std) +{ + struct bootdev_hunter *orig, *start; + int n_ent, i; + + orig = ll_entry_start(struct bootdev_hunter, bootdev_hunter); + n_ent = ll_entry_count(struct bootdev_hunter, bootdev_hunter); + + /* + * workaround for strange bug in clang-12 which sees all the below data + * as zeroes. Any access of start seems to fix it, such as + * + * printf("%p", start); + * + * Use memcpy() to force the correct behaviour. + */ + memcpy(&start, &orig, sizeof(orig)); + printf("%4s %4s %-15s %s\n", "Prio", "Used", "Uclass", "Hunter"); + printf("%4s %4s %-15s %s\n", "----", "----", "---------------", "---------------"); + for (i = 0; i < n_ent; i++) { + struct bootdev_hunter *info = start + i; + + printf("%4d %4s %-15s %s\n", info->prio, + std->hunters_used & BIT(i) ? "*" : "", + uclass_get_name(info->uclass), + info->drv ? info->drv->name : "(none)"); + } + + printf("(total hunters: %d)\n", n_ent); +} + static int bootdev_post_bind(struct udevice *dev) { struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev); diff --git a/cmd/bootdev.c b/cmd/bootdev.c index ecd797c0503..80bfe2812e4 100644 --- a/cmd/bootdev.c +++ b/cmd/bootdev.c @@ -107,14 +107,43 @@ static int do_bootdev_info(struct cmd_tbl *cmdtp, int flag, int argc, return 0; } +static int do_bootdev_hunt(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + struct bootstd_priv *priv; + const char *spec = NULL; + bool list = false; + int ret = 0; + + if (argc >= 2) { + if (!strcmp(argv[1], "-l")) + list = true; + else + spec = argv[1]; + } + + ret = bootstd_get_priv(&priv); + if (ret) + return ret; + if (list) { + bootdev_list_hunters(priv); + } else { + /* TODO: implement hunting */ + } + + return 0; +} + #ifdef CONFIG_SYS_LONGHELP static char bootdev_help_text[] = - "list [-p] - list all available bootdevs (-p to probe)\n" - "bootdev select - select a bootdev by name | label | seq\n" - "bootdev info [-p] - show information about a bootdev (-p to probe)"; + "list [-p] - list all available bootdevs (-p to probe)\n" + "bootdev hunt [-l|] - use hunt drivers to find bootdevs\n" + "bootdev select - 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(hunt, 2, 1, do_bootdev_hunt), U_BOOT_SUBCMD_MKENT(select, 2, 1, do_bootdev_select), U_BOOT_SUBCMD_MKENT(info, 2, 1, do_bootdev_info)); diff --git a/include/bootdev.h b/include/bootdev.h index 1e91d4130e7..cafb5285a28 100644 --- a/include/bootdev.h +++ b/include/bootdev.h @@ -11,6 +11,7 @@ struct bootflow; struct bootflow_iter; +struct bootstd_priv; struct udevice; /** @@ -33,6 +34,53 @@ enum bootdev_prio_t { BOOTDEVP_COUNT, }; +struct bootdev_hunter; + +/** + * bootdev_hunter_func - function to probe for bootdevs of a given type + * + * This should hunt around for bootdevs of the given type, binding them as it + * finds them. This may involve bus enumeration, etc. + * + * @info: Info structure describing this hunter + * @show: true to show information from the hunter + * Returns: 0 if OK, -ve on error + */ +typedef int (*bootdev_hunter_func)(struct bootdev_hunter *info, bool show); + +/** + * struct bootdev_hunter - information about how to hunt for bootdevs + * + * @prio: Scanning priority of this hunter + * @uclass: Uclass ID for the media associated with this bootdev + * @drv: bootdev driver for the things found by this hunter + * @hunt: Function to call to hunt for bootdevs of this type (NULL if none) + * + * Some bootdevs are not visible until other devices are enumerated. For + * example, USB bootdevs only appear when the USB bus is enumerated. + * + * On the other hand, we don't always want to enumerate all the buses just to + * find the first valid bootdev. Ideally we want to work through them in + * priority order, so that the fastest bootdevs are discovered first. + * + * This struct holds information about the bootdev so we can determine the probe + * order and how to hunt for bootdevs of this type + */ +struct bootdev_hunter { + enum bootdev_prio_t prio; + enum uclass_id uclass; + struct driver *drv; + bootdev_hunter_func hunt; +}; + +/* declare a new bootdev hunter */ +#define BOOTDEV_HUNTER(__name) \ + ll_entry_declare(struct bootdev_hunter, __name, bootdev_hunter) + +/* access a bootdev hunter by name */ +#define BOOTDEV_HUNTER_GET(__name) \ + ll_entry_get(struct bootdev_hunter, __name, bootdev_hunter) + /** * struct bootdev_uc_plat - uclass information about a bootdev * @@ -205,6 +253,16 @@ int bootdev_find_by_any(const char *name, struct udevice **devp); */ int bootdev_setup_iter_order(struct bootflow_iter *iter, struct udevice **devp); +/** + * bootdev_list_hunters() - List the available bootdev hunters + * + * These provide a way to find new bootdevs by enumerating buses, etc. This + * function lists the available hunters + * + * @std: Pointer to bootstd private info + */ +void bootdev_list_hunters(struct bootstd_priv *std); + #if CONFIG_IS_ENABLED(BOOTSTD) /** * bootdev_setup_for_dev() - Bind a new bootdev device (deprecated) diff --git a/include/bootstd.h b/include/bootstd.h index bd305094fdc..dddb3e15384 100644 --- a/include/bootstd.h +++ b/include/bootstd.h @@ -33,6 +33,8 @@ struct udevice; * @bootmeth_order: List of bootmeth devices to use, in order, NULL-terminated * @vbe_bootmeth: Currently selected VBE bootmeth, NULL if none * @theme: Node containing the theme information + * @hunters_used: Bitmask of used hunters, indexed by their position in the + * linker list. The bit is set if the hunter has been used already */ struct bootstd_priv { const char **prefixes; @@ -45,6 +47,7 @@ struct bootstd_priv { struct udevice **bootmeth_order; struct udevice *vbe_bootmeth; ofnode theme; + uint hunters_used; }; /** diff --git a/test/boot/bootdev.c b/test/boot/bootdev.c index 1c2a79fb108..a8ca12a3c8f 100644 --- a/test/boot/bootdev.c +++ b/test/boot/bootdev.c @@ -221,3 +221,55 @@ static int bootdev_test_prio(struct unit_test_state *uts) return 0; } BOOTSTD_TEST(bootdev_test_prio, UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +/* Check listing hunters */ +static int bootdev_test_hunter(struct unit_test_state *uts) +{ + struct bootstd_priv *std; + + /* get access to the used hunters */ + ut_assertok(bootstd_get_priv(&std)); + + console_record_reset_enable(); + bootdev_list_hunters(std); + ut_assert_nextline("Prio Used Uclass Hunter"); + ut_assert_nextlinen("----"); + ut_assert_nextline("(total hunters: 0)"); + ut_assert_console_end(); + + return 0; +} +BOOTSTD_TEST(bootdev_test_hunter, UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +/* Check 'bootdev hunt' command */ +static int bootdev_test_cmd_hunt(struct unit_test_state *uts) +{ + struct bootstd_priv *std; + + /* get access to the used hunters */ + ut_assertok(bootstd_get_priv(&std)); + + console_record_reset_enable(); + ut_assertok(run_command("bootdev hunt -l", 0)); + ut_assert_nextline("Prio Used Uclass Hunter"); + ut_assert_nextlinen("----"); + ut_assert_nextline("(total hunters: 0)"); + ut_assert_console_end(); + + /* Scan all hunters */ + ut_assertok(run_command("bootdev hunt", 0)); + ut_assert_console_end(); + + /* List available hunters */ + ut_assertok(run_command("bootdev hunt -l", 0)); + ut_assert_nextlinen("Prio"); + ut_assert_nextlinen("----"); + ut_assert_nextline("(total hunters: 0)"); + ut_assert_console_end(); + + ut_asserteq(0, std->hunters_used); + + return 0; +} +BOOTSTD_TEST(bootdev_test_cmd_hunt, UT_TESTF_DM | UT_TESTF_SCAN_FDT | + UT_TESTF_ETH_BOOTDEV); -- cgit v1.3.1 From c7b63d500df707bd9c9041e0dae3a25f56098978 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 17 Jan 2023 10:47:34 -0700 Subject: bootstd: Support running bootdev hunters Add a way to run a bootdev hunter to find bootdevs of a certain type. Add this to the 'bootdev hunt' command. Test for this are added in a later patch, since a useful test needs some hunters to work with. Signed-off-by: Simon Glass --- boot/bootdev-uclass.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++ cmd/bootdev.c | 7 +++++- include/bootdev.h | 14 ++++++++++++ test/boot/bootdev.c | 3 +++ 4 files changed, 84 insertions(+), 1 deletion(-) (limited to 'cmd') diff --git a/boot/bootdev-uclass.c b/boot/bootdev-uclass.c index 62eb0b617cd..081b94ce332 100644 --- a/boot/bootdev-uclass.c +++ b/boot/bootdev-uclass.c @@ -636,6 +636,67 @@ int bootdev_setup_iter_order(struct bootflow_iter *iter, struct udevice **devp) return 0; } +static int bootdev_hunt_drv(struct bootdev_hunter *info, uint seq, bool show) +{ + const char *name = uclass_get_name(info->uclass); + struct bootstd_priv *std; + int ret; + + ret = bootstd_get_priv(&std); + if (ret) + return log_msg_ret("std", ret); + + if (!(std->hunters_used & BIT(seq))) { + if (show) + printf("Hunting with: %s\n", + uclass_get_name(info->uclass)); + log_debug("Hunting with: %s\n", name); + if (info->hunt) { + ret = info->hunt(info, show); + if (ret) + return ret; + } + std->hunters_used |= BIT(seq); + } + + return 0; +} + +int bootdev_hunt(const char *spec, bool show) +{ + struct bootdev_hunter *start; + const char *end; + int n_ent, i; + int result; + size_t len; + + start = ll_entry_start(struct bootdev_hunter, bootdev_hunter); + n_ent = ll_entry_count(struct bootdev_hunter, bootdev_hunter); + result = 0; + + len = SIZE_MAX; + if (spec) { + trailing_strtoln_end(spec, NULL, &end); + len = end - spec; + } + + for (i = 0; i < n_ent; i++) { + struct bootdev_hunter *info = start + i; + const char *name = uclass_get_name(info->uclass); + int ret; + + log_debug("looking at %.*s for %s\n", + (int)max(strlen(name), len), spec, name); + if (spec && strncmp(spec, name, max(strlen(name), len))) + continue; + ret = bootdev_hunt_drv(info, i, show); + if (ret) + result = ret; + } + + return result; +} + void bootdev_list_hunters(struct bootstd_priv *std) { struct bootdev_hunter *orig, *start; diff --git a/cmd/bootdev.c b/cmd/bootdev.c index 80bfe2812e4..28866faac76 100644 --- a/cmd/bootdev.c +++ b/cmd/bootdev.c @@ -128,7 +128,12 @@ static int do_bootdev_hunt(struct cmd_tbl *cmdtp, int flag, int argc, if (list) { bootdev_list_hunters(priv); } else { - /* TODO: implement hunting */ + ret = bootdev_hunt(spec, true); + if (ret) { + printf("Failed (err=%dE)\n", ret); + + return CMD_RET_FAILURE; + } } return 0; diff --git a/include/bootdev.h b/include/bootdev.h index cafb5285a28..deef7890489 100644 --- a/include/bootdev.h +++ b/include/bootdev.h @@ -263,6 +263,20 @@ int bootdev_setup_iter_order(struct bootflow_iter *iter, struct udevice **devp); */ void bootdev_list_hunters(struct bootstd_priv *std); +/** + * bootdev_hunt() - Hunt for bootdevs matching a particular spec + * + * This runs the selected hunter (or all if @spec is NULL) to try to find new + * bootdevs. + * + * @spec: Spec to match, e.g. "mmc0", or NULL for any. If provided, this must + * match a uclass name so that the hunter can be determined. Any trailing number + * is ignored + * @show: true to show each hunter before using it + * Returns: 0 if OK, -ve on error + */ +int bootdev_hunt(const char *spec, bool show); + #if CONFIG_IS_ENABLED(BOOTSTD) /** * bootdev_setup_for_dev() - Bind a new bootdev device (deprecated) diff --git a/test/boot/bootdev.c b/test/boot/bootdev.c index a8ca12a3c8f..45a00c34c0c 100644 --- a/test/boot/bootdev.c +++ b/test/boot/bootdev.c @@ -237,6 +237,9 @@ static int bootdev_test_hunter(struct unit_test_state *uts) ut_assert_nextline("(total hunters: 0)"); ut_assert_console_end(); + ut_assertok(bootdev_hunt("mmc1", false)); + ut_assert_console_end(); + return 0; } BOOTSTD_TEST(bootdev_test_hunter, UT_TESTF_DM | UT_TESTF_SCAN_FDT); -- cgit v1.3.1 From c8c3fd24cc0dd9512237dc13528e90eb46e704a7 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 17 Jan 2023 10:47:39 -0700 Subject: net: Add a function to run dhcp At present this must be done by executing the command. Also it involves fiddling with the environment to determine the correct autoload behaviour. Ideally it should be possible to run network operations without even having the command line present (CONFIG_CMDLINE). For now, add a function to handle DHCP, so it can be called from a bootdev more easily. Signed-off-by: Simon Glass Reviewed-by: Ramon Fried --- cmd/net.c | 35 +++++++++++++++++++++++++++++++++++ include/net.h | 15 +++++++++++++++ 2 files changed, 50 insertions(+) (limited to 'cmd') diff --git a/cmd/net.c b/cmd/net.c index dd50930a362..4227321871c 100644 --- a/cmd/net.c +++ b/cmd/net.c @@ -4,6 +4,8 @@ * Wolfgang Denk, DENX Software Engineering, wd@denx.de. */ +#define LOG_CATEGORY UCLASS_ETH + /* * Boot support */ @@ -13,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -120,6 +123,38 @@ U_BOOT_CMD( "boot image via network using DHCP/TFTP protocol", "[loadAddress] [[hostIPaddr:]bootfilename]" ); + +int dhcp_run(ulong addr, const char *fname, bool autoload) +{ + char *dhcp_argv[] = {"dhcp", NULL, (char *)fname, NULL}; + struct cmd_tbl cmdtp = {}; /* dummy */ + char file_addr[17]; + int old_autoload; + int ret, result; + + log_debug("addr=%lx, fname=%s, autoload=%d\n", addr, fname, autoload); + old_autoload = env_get_yesno("autoload"); + ret = env_set("autoload", autoload ? "y" : "n"); + if (ret) + return log_msg_ret("en1", -EINVAL); + + if (autoload) { + sprintf(file_addr, "%lx", addr); + dhcp_argv[1] = file_addr; + } + + result = do_dhcp(&cmdtp, 0, !autoload ? 1 : fname ? 3 : 2, dhcp_argv); + + ret = env_set("autoload", old_autoload == -1 ? NULL : + old_autoload ? "y" : "n"); + if (ret) + return log_msg_ret("en2", -EINVAL); + + if (result) + return log_msg_ret("res", -ENOENT); + + return 0; +} #endif #if defined(CONFIG_CMD_NFS) diff --git a/include/net.h b/include/net.h index 759d4669df1..399af5e0645 100644 --- a/include/net.h +++ b/include/net.h @@ -65,6 +65,21 @@ struct in_addr { */ int do_tftpb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); +/** + * dhcp_run() - Run DHCP on the current ethernet device + * + * This sets the autoload variable, then puts it back to similar to its original + * state (y, n or unset). + * + * @addr: Address to load the file into (0 if @autoload is false) + * @fname: Filename of file to load (NULL if @autoload is false or to use the + * default filename) + * @autoload: true to load the file, false to just get the network IP + * @return 0 if OK, -EINVAL if the environment failed, -ENOENT if ant file was + * not found + */ +int dhcp_run(ulong addr, const char *fname, bool autoload); + /** * An incoming packet handler. * @param pkt pointer to the application packet -- cgit v1.3.1 From 7638c85190dccc2dfacb86fc3b70deb165337b4b Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 17 Jan 2023 10:47:56 -0700 Subject: bootstd: Include the device tree in the bootflow Some bootmeths provide a way to load a device tree as well as the base OS image. Add a way to store this in the bootflow. Update the 'bootflow info' command to show this information. Note that the device tree is not allocated, but instead is stored at an address provided by an environment variable. This may need to be adjusted at some point, but for now it works well and fits in with the existing distro-boot scripts. Signed-off-by: Simon Glass --- boot/bootflow.c | 1 + cmd/bootflow.c | 6 ++++++ include/bootflow.h | 6 ++++++ test/boot/bootflow.c | 1 + 4 files changed, 14 insertions(+) (limited to 'cmd') diff --git a/boot/bootflow.c b/boot/bootflow.c index 0345755f58f..52cc2f9d548 100644 --- a/boot/bootflow.c +++ b/boot/bootflow.c @@ -355,6 +355,7 @@ void bootflow_free(struct bootflow *bflow) free(bflow->fname); free(bflow->buf); free(bflow->os_name); + free(bflow->fdt_fname); } void bootflow_remove(struct bootflow *bflow) diff --git a/cmd/bootflow.c b/cmd/bootflow.c index 2b6ed26fdcb..56dd35b69cf 100644 --- a/cmd/bootflow.c +++ b/cmd/bootflow.c @@ -344,6 +344,12 @@ static int do_bootflow_info(struct cmd_tbl *cmdtp, int flag, int argc, printf("Logo size: %x (%d bytes)\n", bflow->logo_size, bflow->logo_size); } + printf("FDT: %s\n", bflow->fdt_fname); + if (bflow->fdt_fname) { + printf("FDT size: %x (%d bytes)\n", bflow->fdt_size, + bflow->fdt_size); + printf("FDT addr: %lx\n", bflow->fdt_addr); + } printf("Error: %d\n", bflow->err); if (dump && bflow->buf) { /* Set some sort of maximum on the size */ diff --git a/include/bootflow.h b/include/bootflow.h index 8ff9e332b1f..bf71b09edad 100644 --- a/include/bootflow.h +++ b/include/bootflow.h @@ -60,6 +60,9 @@ enum bootflow_state_t { * @err: Error number received (0 if OK) * @os_name: Name of the OS / distro being booted, or NULL if not known * (allocated) + * @fdt_fname: Filename of FDT file + * @fdt_size: Size of FDT file + * @fdt_addr: Address of loaded fdt */ struct bootflow { struct list_head bm_node; @@ -79,6 +82,9 @@ struct bootflow { int size; int err; char *os_name; + char *fdt_fname; + int fdt_size; + ulong fdt_addr; }; /** diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c index f852b6e9b6f..b71ec52eb7a 100644 --- a/test/boot/bootflow.c +++ b/test/boot/bootflow.c @@ -199,6 +199,7 @@ static int bootflow_cmd_info(struct unit_test_state *uts) ut_assert_nextline("Size: 253 (595 bytes)"); ut_assert_nextline("OS: Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl)"); ut_assert_nextline("Logo: (none)"); + ut_assert_nextline("FDT: "); ut_assert_nextline("Error: 0"); ut_assert_console_end(); -- cgit v1.3.1 From d9f48579dced9c897e718a8b0b84d56ac564a486 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 17 Jan 2023 10:48:05 -0700 Subject: bootstd: Treat DHCP and PXE as bootdev labels These are associated with the ethernet boot device but do not match its uclass name, so handle them as special cases. Provide a way to pass flags through with the bootdev so that we know how to process it. The flags are checked by the bootmeths, to ensure that only the selected bootmeth is used. While these both use the network device, they work quite differently. It is common to run only one of these, or to run PXE before DHCP. Provide bootflow flags to control which methods are used. Check these in the two bootmeths so that only the chosen one is used. Signed-off-by: Simon Glass --- boot/bootdev-uclass.c | 53 ++++++++++++++++++++++++++++---------------------- boot/bootmeth_efi.c | 4 ++++ boot/bootmeth_pxe.c | 3 +++ boot/bootmeth_script.c | 2 ++ boot/vbe_simple_fw.c | 2 +- cmd/bootdev.c | 2 +- cmd/bootflow.c | 2 +- include/bootdev.h | 15 ++++++++++---- include/bootflow.h | 15 ++++++++++++++ test/boot/bootdev.c | 17 ++++++++++++---- 10 files changed, 81 insertions(+), 34 deletions(-) (limited to 'cmd') diff --git a/boot/bootdev-uclass.c b/boot/bootdev-uclass.c index dd9ec668e16..7ac42afd7b3 100644 --- a/boot/bootdev-uclass.c +++ b/boot/bootdev-uclass.c @@ -359,14 +359,17 @@ int bootdev_unbind_dev(struct udevice *parent) * * @label: Label to look up (e.g. "mmc1" or "mmc0") * @seqp: Returns the sequence number, or -1 if none + * @method_flagsp: If non-NULL, returns any flags implied by the label + * (enum bootflow_meth_flags_t), 0 if none * Returns: sequence number on success, else -ve error code */ -static int label_to_uclass(const char *label, int *seqp) +static int label_to_uclass(const char *label, int *seqp, int *method_flagsp) { + int seq, len, method_flags; enum uclass_id id; const char *end; - int seq, len; + method_flags = 0; seq = trailing_strtoln_end(label, NULL, &end); len = end - label; if (!len) @@ -379,6 +382,14 @@ static int label_to_uclass(const char *label, int *seqp) if (IS_ENABLED(CONFIG_BOOTDEV_SPI_FLASH) && !strncmp("spi", label, len)) { id = UCLASS_SPI_FLASH; + } else if (IS_ENABLED(CONFIG_BOOTDEV_ETH) && + !strncmp("pxe", label, len)) { + id = UCLASS_ETH; + method_flags |= BOOTFLOW_METHF_PXE_ONLY; + } else if (IS_ENABLED(CONFIG_BOOTDEV_ETH) && + !strncmp("dhcp", label, len)) { + id = UCLASS_ETH; + method_flags |= BOOTFLOW_METHF_DHCP_ONLY; } else { log_warning("Unknown uclass '%s' in label\n", label); return -EINVAL; @@ -387,31 +398,21 @@ static int label_to_uclass(const char *label, int *seqp) if (id == UCLASS_USB) id = UCLASS_MASS_STORAGE; *seqp = seq; + if (method_flagsp) + *method_flagsp = method_flags; return id; } -/** - * bootdev_find_by_label() - Convert a label string to a bootdev device - * - * Looks up a label name to find the associated bootdev. For example, if the - * label name is "mmc2", this will find a bootdev for an mmc device whose - * sequence number is 2. - * - * @label: Label string to convert, e.g. "mmc2" - * @devp: Returns bootdev device corresponding to that boot label - * Return: 0 if OK, -EINVAL if the label name (e.g. "mmc") does not refer to a - * uclass, -ENOENT if no bootdev for that media has the sequence number - * (e.g. 2) - */ -int bootdev_find_by_label(const char *label, struct udevice **devp) +int bootdev_find_by_label(const char *label, struct udevice **devp, + int *method_flagsp) { + int seq, ret, method_flags = 0; struct udevice *media; struct uclass *uc; enum uclass_id id; - int seq, ret; - ret = label_to_uclass(label, &seq); + ret = label_to_uclass(label, &seq, &method_flags); if (ret < 0) return log_msg_ret("uc", ret); id = ret; @@ -441,6 +442,8 @@ int bootdev_find_by_label(const char *label, struct udevice **devp) if (!ret) { log_debug("- found %s\n", bdev->name); *devp = bdev; + if (method_flagsp) + *method_flagsp = method_flags; return 0; } log_debug("- no device in %s\n", media->name); @@ -450,9 +453,11 @@ int bootdev_find_by_label(const char *label, struct udevice **devp) return -ENOENT; } -int bootdev_find_by_any(const char *name, struct udevice **devp) +int bootdev_find_by_any(const char *name, struct udevice **devp, + int *method_flagsp) { struct udevice *dev; + int method_flags = 0; int ret, seq; char *endp; @@ -462,18 +467,18 @@ int bootdev_find_by_any(const char *name, struct udevice **devp) if (*endp) { ret = uclass_get_device_by_name(UCLASS_BOOTDEV, name, &dev); if (ret == -ENODEV) { - ret = bootdev_find_by_label(name, &dev); + ret = bootdev_find_by_label(name, &dev, &method_flags); if (ret) { printf("Cannot find bootdev '%s' (err=%d)\n", name, ret); - return ret; + return log_msg_ret("lab", ret); } ret = device_probe(dev); } if (ret) { printf("Cannot probe bootdev '%s' (err=%d)\n", name, ret); - return ret; + return log_msg_ret("pro", ret); } } else { ret = uclass_get_device_by_seq(UCLASS_BOOTDEV, seq, &dev); @@ -484,6 +489,8 @@ int bootdev_find_by_any(const char *name, struct udevice **devp) } *devp = dev; + if (method_flagsp) + *method_flagsp = method_flags; return 0; } @@ -593,7 +600,7 @@ static int build_order(struct udevice *bootstd, struct udevice **order, upto = 0; for (i = 0; labels[i]; i++) { - ret = bootdev_find_by_label(labels[i], &dev); + ret = bootdev_find_by_label(labels[i], &dev, NULL); if (!ret) { if (upto == max_count) { overflow_target = labels[i]; diff --git a/boot/bootmeth_efi.c b/boot/bootmeth_efi.c index 53a0489b93c..67c972e3fe4 100644 --- a/boot/bootmeth_efi.c +++ b/boot/bootmeth_efi.c @@ -140,6 +140,10 @@ static int distro_efi_check(struct udevice *dev, struct bootflow_iter *iter) if (bootflow_iter_check_blk(iter) && bootflow_iter_check_net(iter)) return log_msg_ret("blk", -ENOTSUPP); + /* This works on block devices and network devices */ + if (iter->method_flags & BOOTFLOW_METHF_PXE_ONLY) + return log_msg_ret("pxe", -ENOTSUPP); + return 0; } diff --git a/boot/bootmeth_pxe.c b/boot/bootmeth_pxe.c index 13e2ff486dc..ecf8557af83 100644 --- a/boot/bootmeth_pxe.c +++ b/boot/bootmeth_pxe.c @@ -48,6 +48,9 @@ static int distro_pxe_check(struct udevice *dev, struct bootflow_iter *iter) if (ret) return log_msg_ret("net", ret); + if (iter->method_flags & BOOTFLOW_METHF_DHCP_ONLY) + return log_msg_ret("dhcp", -ENOTSUPP); + return 0; } diff --git a/boot/bootmeth_script.c b/boot/bootmeth_script.c index a14c750ff61..225eb18ee6c 100644 --- a/boot/bootmeth_script.c +++ b/boot/bootmeth_script.c @@ -27,6 +27,8 @@ static int script_check(struct udevice *dev, struct bootflow_iter *iter) { /* This works on block devices, network devices and SPI Flash */ + if (iter->method_flags & BOOTFLOW_METHF_PXE_ONLY) + return log_msg_ret("pxe", -ENOTSUPP); return 0; } diff --git a/boot/vbe_simple_fw.c b/boot/vbe_simple_fw.c index 0a49d286703..d59a704ddba 100644 --- a/boot/vbe_simple_fw.c +++ b/boot/vbe_simple_fw.c @@ -176,7 +176,7 @@ static int simple_load_from_image(struct spl_image_info *spl_image, priv = dev_get_priv(meth); log_debug("simple %s\n", priv->storage); - ret = bootdev_find_by_label(priv->storage, &bdev); + ret = bootdev_find_by_label(priv->storage, &bdev, NULL); if (ret) return log_msg_ret("bd", ret); log_debug("bootdev %s\n", bdev->name); diff --git a/cmd/bootdev.c b/cmd/bootdev.c index 28866faac76..5b1efaaee87 100644 --- a/cmd/bootdev.c +++ b/cmd/bootdev.c @@ -57,7 +57,7 @@ static int do_bootdev_select(struct cmd_tbl *cmdtp, int flag, int argc, std->cur_bootdev = NULL; return 0; } - if (bootdev_find_by_any(argv[1], &dev)) + if (bootdev_find_by_any(argv[1], &dev, NULL)) return CMD_RET_FAILURE; std->cur_bootdev = dev; diff --git a/cmd/bootflow.c b/cmd/bootflow.c index 56dd35b69cf..c8b2f5efdeb 100644 --- a/cmd/bootflow.c +++ b/cmd/bootflow.c @@ -121,7 +121,7 @@ static int do_bootflow_scan(struct cmd_tbl *cmdtp, int flag, int argc, if (argc > 1) { const char *label = argv[1]; - if (bootdev_find_by_any(label, &dev)) + if (bootdev_find_by_any(label, &dev, NULL)) return CMD_RET_FAILURE; } } else { diff --git a/include/bootdev.h b/include/bootdev.h index deef7890489..db03c5c032e 100644 --- a/include/bootdev.h +++ b/include/bootdev.h @@ -222,19 +222,26 @@ int bootdev_next_bootflow(struct bootflow **bflowp); * @label: Label to look up (e.g. "mmc1" or "mmc0") * @devp: Returns the bootdev device found, or NULL if none (note it does not * return the media device, but its bootdev child) + * @method_flagsp: If non-NULL, returns any flags implied by the label + * (enum bootflow_meth_flags_t), 0 if none. Unset if function fails * Return: 0 if OK, -EINVAL if the uclass is not supported by this board, - * -ENOENT if there is no device with that number + * -ENOENT if there is no device with that number */ -int bootdev_find_by_label(const char *label, struct udevice **devp); +int bootdev_find_by_label(const char *label, struct udevice **devp, + int *method_flagsp); /** * bootdev_find_by_any() - Find a bootdev by name, label or sequence * * @name: name (e.g. "mmc2.bootdev"), label ("mmc2"), or sequence ("2") to find * @devp: returns the device found, on success - * Return: 0 if OK, -ve on error + * @method_flagsp: If non-NULL, returns any flags implied by the label + * (enum bootflow_meth_flags_t), 0 if none. Unset if function fails + * Return: 0 if OK, -EINVAL if the uclass is not supported by this board, + * -ENOENT if there is no device with that number */ -int bootdev_find_by_any(const char *name, struct udevice **devp); +int bootdev_find_by_any(const char *name, struct udevice **devp, + int *method_flagsp); /** * bootdev_setup_iter_order() - Set up the ordering of bootdevs to scan diff --git a/include/bootflow.h b/include/bootflow.h index 319dda8e0be..9c6610bb922 100644 --- a/include/bootflow.h +++ b/include/bootflow.h @@ -104,6 +104,21 @@ enum bootflow_flags_t { BOOTFLOWF_SKIP_GLOBAL = 1 << 4, }; +/** + * enum bootflow_meth_flags_t - flags controlling which bootmeths are used + * + * Used during iteration, e.g. by bootdev_find_by_label(), to determine which + * bootmeths are used for the current bootdev. The flags reset when the bootdev + * changes + * + * @BOOTFLOW_METHF_DHCP_ONLY: Only use dhcp (scripts and EFI) + * @BOOTFLOW_METHF_PXE_ONLY: Only use pxe (PXE boot) + */ +enum bootflow_meth_flags_t { + BOOTFLOW_METHF_DHCP_ONLY = 1 << 0, + BOOTFLOW_METHF_PXE_ONLY = 1 << 1, +}; + /** * struct bootflow_iter - state for iterating through bootflows * diff --git a/test/boot/bootdev.c b/test/boot/bootdev.c index ea0703fa5c8..e6045b05d81 100644 --- a/test/boot/bootdev.c +++ b/test/boot/bootdev.c @@ -102,22 +102,31 @@ BOOTSTD_TEST(bootdev_test_cmd_select, UT_TESTF_DM | UT_TESTF_SCAN_FDT); static int bootdev_test_labels(struct unit_test_state *uts) { struct udevice *dev, *media; + int mflags = 0; - ut_assertok(bootdev_find_by_label("mmc2", &dev)); + ut_assertok(bootdev_find_by_label("mmc2", &dev, &mflags)); ut_asserteq(UCLASS_BOOTDEV, device_get_uclass_id(dev)); + ut_asserteq(0, mflags); media = dev_get_parent(dev); ut_asserteq(UCLASS_MMC, device_get_uclass_id(media)); ut_asserteq_str("mmc2", media->name); + /* Check method flags */ + ut_assertok(bootdev_find_by_label("pxe", &dev, &mflags)); + ut_asserteq(BOOTFLOW_METHF_PXE_ONLY, mflags); + ut_assertok(bootdev_find_by_label("dhcp", &dev, &mflags)); + ut_asserteq(BOOTFLOW_METHF_DHCP_ONLY, mflags); + /* Check invalid uclass */ - ut_asserteq(-EINVAL, bootdev_find_by_label("fred0", &dev)); + ut_asserteq(-EINVAL, bootdev_find_by_label("fred0", &dev, &mflags)); /* Check unknown sequence number */ - ut_asserteq(-ENOENT, bootdev_find_by_label("mmc6", &dev)); + ut_asserteq(-ENOENT, bootdev_find_by_label("mmc6", &dev, &mflags)); return 0; } -BOOTSTD_TEST(bootdev_test_labels, UT_TESTF_DM | UT_TESTF_SCAN_FDT); +BOOTSTD_TEST(bootdev_test_labels, UT_TESTF_DM | UT_TESTF_SCAN_FDT | + UT_TESTF_ETH_BOOTDEV); /* Check bootdev ordering with the bootdev-order property */ static int bootdev_test_order(struct unit_test_state *uts) -- cgit v1.3.1 From d73420e4fe7c7e22a41ed140c6be9c11db6b9503 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 17 Jan 2023 10:48:06 -0700 Subject: bootstd: Use hunters when scanning for bootflows Add a flag to control whether hunters are used when scanning for bootflows. Enable it by default and tidy up the flag comments a little. Fow now this has no effect, until a future patch enables this feature. Signed-off-by: Simon Glass --- cmd/bootflow.c | 5 ++++- include/bootflow.h | 21 ++++++++++++++++----- 2 files changed, 20 insertions(+), 6 deletions(-) (limited to 'cmd') diff --git a/cmd/bootflow.c b/cmd/bootflow.c index c8b2f5efdeb..fe58de5fa59 100644 --- a/cmd/bootflow.c +++ b/cmd/bootflow.c @@ -96,7 +96,7 @@ static int do_bootflow_scan(struct cmd_tbl *cmdtp, int flag, int argc, struct udevice *dev; struct bootflow bflow; bool all = false, boot = false, errors = false, no_global = false; - bool list = false; + bool list = false, no_hunter = false; int num_valid = 0; bool has_args; int ret, i; @@ -115,6 +115,7 @@ static int do_bootflow_scan(struct cmd_tbl *cmdtp, int flag, int argc, errors = strchr(argv[1], 'e'); no_global = strchr(argv[1], 'G'); list = strchr(argv[1], 'l'); + no_hunter = strchr(argv[1], 'H'); argc--; argv++; } @@ -141,6 +142,8 @@ static int do_bootflow_scan(struct cmd_tbl *cmdtp, int flag, int argc, flags |= BOOTFLOWF_ALL; if (no_global) flags |= BOOTFLOWF_SKIP_GLOBAL; + if (!no_hunter) + flags |= BOOTFLOWF_HUNT; /* * If we have a device, just scan for bootflows attached to that device diff --git a/include/bootflow.h b/include/bootflow.h index 9c6610bb922..4012f4b8a82 100644 --- a/include/bootflow.h +++ b/include/bootflow.h @@ -91,17 +91,28 @@ struct bootflow { * enum bootflow_flags_t - flags for the bootflow iterator * * @BOOTFLOWF_FIXED: Only used fixed/internal media - * @BOOTFLOWF_SHOW: Show each bootdev before scanning it + * @BOOTFLOWF_SHOW: Show each bootdev before scanning it; show each hunter + * before using it * @BOOTFLOWF_ALL: Return bootflows with errors as well - * @BOOTFLOWF_SINGLE_DEV: Just scan one bootmeth - * @BOOTFLOWF_SKIP_GLOBAL: Don't scan global bootmeths + * @BOOTFLOWF_HUNT: Hunt for new bootdevs using the bootdrv hunters + * + * Internal flags: + * @BOOTFLOWF_SINGLE_DEV: (internal) Just scan one bootdev + * @BOOTFLOWF_SKIP_GLOBAL: (internal) Don't scan global bootmeths + * this uclass */ enum bootflow_flags_t { BOOTFLOWF_FIXED = 1 << 0, BOOTFLOWF_SHOW = 1 << 1, BOOTFLOWF_ALL = 1 << 2, - BOOTFLOWF_SINGLE_DEV = 1 << 3, - BOOTFLOWF_SKIP_GLOBAL = 1 << 4, + BOOTFLOWF_HUNT = 1 << 3, + + /* + * flags used internally by standard boot - do not set these when + * calling bootflow_scan_bootdev() etc. + */ + BOOTFLOWF_SINGLE_DEV = 1 << 16, + BOOTFLOWF_SKIP_GLOBAL = 1 << 17, }; /** -- cgit v1.3.1 From 35ce14617edb6ee7c3004c396f19d2c451255358 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 17 Jan 2023 10:48:12 -0700 Subject: extension: Refactor to allow non-command usage The current extension code is designed to be used from commands. We want to add a boot driver which uses it. To help with this, split the code into the command processing and a function which actually does the scan. Really the extension code should be in common/ or use driver model, but this is a start. Signed-off-by: Simon Glass --- cmd/extension_board.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'cmd') diff --git a/cmd/extension_board.c b/cmd/extension_board.c index f94abd612d5..f7685d47b8b 100644 --- a/cmd/extension_board.c +++ b/cmd/extension_board.c @@ -80,8 +80,7 @@ static int do_extension_list(struct cmd_tbl *cmdtp, int flag, return CMD_RET_SUCCESS; } -static int do_extension_scan(struct cmd_tbl *cmdtp, int flag, - int argc, char *const argv[]) +static int extension_scan(bool show) { struct extension *extension, *next; int extension_num; @@ -91,12 +90,23 @@ static int do_extension_scan(struct cmd_tbl *cmdtp, int flag, free(extension); } extension_num = extension_board_scan(&extension_list); + if (show && extension_num >= 0) + printf("Found %d extension board(s).\n", extension_num); + + /* either the number of extensions, or -ve for error */ + return extension_num; +} + +static int do_extension_scan(struct cmd_tbl *cmdtp, int flag, + int argc, char *const argv[]) +{ + int extension_num; + + extension_num = extension_scan(true); if (extension_num < 0) return CMD_RET_FAILURE; - printf("Found %d extension board(s).\n", extension_num); - return CMD_RET_SUCCESS; } -- cgit v1.3.1 From 18552d2a7288afd6f125b4ac99e5c27690c129b4 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 17 Jan 2023 10:48:13 -0700 Subject: bootstd: Add a hunter for the extension feature This needs to run before any bootdev is used, so add a hunter for it. Signed-off-by: Simon Glass --- cmd/extension_board.c | 25 +++++++++++++++++++++++++ test/boot/bootdev.c | 37 +++++++++++++++++++++++-------------- test/boot/bootflow.c | 20 ++++++++++---------- test/boot/bootstd_common.h | 5 +++++ 4 files changed, 63 insertions(+), 24 deletions(-) (limited to 'cmd') diff --git a/cmd/extension_board.c b/cmd/extension_board.c index f7685d47b8b..2b672d888c6 100644 --- a/cmd/extension_board.c +++ b/cmd/extension_board.c @@ -5,7 +5,9 @@ */ #include +#include #include +#include #include #include #include @@ -176,3 +178,26 @@ U_BOOT_CMD(extension, 3, 1, do_extensionops, "extension list - lists available extension(s) board(s)\n" "extension apply - applies DT overlays corresponding to extension boards\n" ); + +static int extension_bootdev_hunt(struct bootdev_hunter *info, bool show) +{ + int ret; + + ret = env_set_hex("extension_overlay_addr", + env_get_hex("fdtoverlay_addr_r", 0)); + if (ret) + return log_msg_ret("env", ret); + + ret = extension_scan(show); + if (ret < 0) + return log_msg_ret("ext", ret); + + return 0; +} + +/* extensions should have a uclass - for now we use UCLASS_SIMPLE_BUS uclass */ +BOOTDEV_HUNTER(extension_bootdev_hunter) = { + .prio = BOOTDEVP_1_PRE_SCAN, + .uclass = UCLASS_SIMPLE_BUS, + .hunt = extension_bootdev_hunt, +}; diff --git a/test/boot/bootdev.c b/test/boot/bootdev.c index 1090b92e510..8ebc27a6435 100644 --- a/test/boot/bootdev.c +++ b/test/boot/bootdev.c @@ -306,6 +306,7 @@ static int bootdev_test_hunter(struct unit_test_state *uts) ut_assert_nextline("Prio Used Uclass Hunter"); ut_assert_nextlinen("----"); ut_assert_nextline(" 6 ethernet eth_bootdev"); + ut_assert_nextline(" 1 simple_bus (none)"); ut_assert_nextline(" 5 ide ide_bootdev"); ut_assert_nextline(" 2 mmc mmc_bootdev"); ut_assert_nextline(" 4 nvme nvme_bootdev"); @@ -313,7 +314,7 @@ static int bootdev_test_hunter(struct unit_test_state *uts) ut_assert_nextline(" 4 spi_flash sf_bootdev"); ut_assert_nextline(" 5 usb usb_bootdev"); ut_assert_nextline(" 4 virtio virtio_bootdev"); - ut_assert_nextline("(total hunters: 8)"); + ut_assert_nextline("(total hunters: 9)"); ut_assert_console_end(); ut_assertok(bootdev_hunt("usb1", false)); @@ -321,8 +322,8 @@ static int bootdev_test_hunter(struct unit_test_state *uts) "Bus usb@1: scanning bus usb@1 for devices... 5 USB Device(s) found"); ut_assert_console_end(); - /* USB is fifth in the list, so bit 6 */ - ut_asserteq(BIT(6), std->hunters_used); + /* USB is sixth in the list, so bit 7 */ + ut_asserteq(BIT(7), std->hunters_used); return 0; } @@ -343,7 +344,7 @@ static int bootdev_test_cmd_hunt(struct unit_test_state *uts) ut_assert_nextline("Prio Used Uclass Hunter"); ut_assert_nextlinen("----"); ut_assert_nextline(" 6 ethernet eth_bootdev"); - ut_assert_skip_to_line("(total hunters: 8)"); + ut_assert_skip_to_line("(total hunters: 9)"); ut_assert_console_end(); /* Use the MMC hunter and see that it updates */ @@ -351,7 +352,7 @@ static int bootdev_test_cmd_hunt(struct unit_test_state *uts) ut_assertok(run_command("bootdev hunt -l", 0)); ut_assert_skip_to_line(" 5 ide ide_bootdev"); ut_assert_nextline(" 2 * mmc mmc_bootdev"); - ut_assert_skip_to_line("(total hunters: 8)"); + ut_assert_skip_to_line("(total hunters: 9)"); ut_assert_console_end(); /* Scan all hunters */ @@ -359,6 +360,10 @@ static int bootdev_test_cmd_hunt(struct unit_test_state *uts) test_set_skip_delays(true); ut_assertok(run_command("bootdev hunt", 0)); ut_assert_nextline("Hunting with: ethernet"); + + /* This is the extension feature which has no uclass at present */ + ut_assert_nextline("Hunting with: simple_bus"); + ut_assert_nextline("Found 2 extension board(s)."); ut_assert_nextline("Hunting with: ide"); ut_assert_nextline("Bus 0: not available "); @@ -379,6 +384,7 @@ static int bootdev_test_cmd_hunt(struct unit_test_state *uts) ut_assert_nextlinen("Prio"); ut_assert_nextlinen("----"); ut_assert_nextline(" 6 * ethernet eth_bootdev"); + ut_assert_nextline(" 1 * simple_bus (none)"); ut_assert_nextline(" 5 * ide ide_bootdev"); ut_assert_nextline(" 2 * mmc mmc_bootdev"); ut_assert_nextline(" 4 * nvme nvme_bootdev"); @@ -386,10 +392,10 @@ static int bootdev_test_cmd_hunt(struct unit_test_state *uts) ut_assert_nextline(" 4 * spi_flash sf_bootdev"); ut_assert_nextline(" 5 * usb usb_bootdev"); ut_assert_nextline(" 4 * virtio virtio_bootdev"); - ut_assert_nextline("(total hunters: 8)"); + ut_assert_nextline("(total hunters: 9)"); ut_assert_console_end(); - ut_asserteq(GENMASK(7, 0), std->hunters_used); + ut_asserteq(GENMASK(MAX_HUNTER, 0), std->hunters_used); return 0; } @@ -553,8 +559,8 @@ static int bootdev_test_next_label(struct unit_test_state *uts) ut_asserteq_str("scsi.id0lun0.bootdev", dev->name); ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS, mflags); - /* SCSI is fifth in the list, so bit 4 */ - ut_asserteq(BIT(2) | BIT(4), std->hunters_used); + /* SCSI is sixth in the list, so bit 5 */ + ut_asserteq(BIT(MMC_HUNTER) | BIT(5), std->hunters_used); ut_assertok(bootdev_next_label(&iter, &dev, &mflags)); ut_assert_console_end(); @@ -564,7 +570,7 @@ static int bootdev_test_next_label(struct unit_test_state *uts) mflags); /* dhcp: Ethernet is first so bit 0 */ - ut_asserteq(BIT(2) | BIT(4) | BIT(0), std->hunters_used); + ut_asserteq(BIT(MMC_HUNTER) | BIT(5) | BIT(0), std->hunters_used); ut_assertok(bootdev_next_label(&iter, &dev, &mflags)); ut_assert_console_end(); @@ -574,7 +580,7 @@ static int bootdev_test_next_label(struct unit_test_state *uts) mflags); /* pxe: Ethernet is first so bit 0 */ - ut_asserteq(BIT(2) | BIT(4) | BIT(0), std->hunters_used); + ut_asserteq(BIT(MMC_HUNTER) | BIT(5) | BIT(0), std->hunters_used); mflags = 123; ut_asserteq(-ENODEV, bootdev_next_label(&iter, &dev, &mflags)); @@ -582,7 +588,7 @@ static int bootdev_test_next_label(struct unit_test_state *uts) ut_assert_console_end(); /* no change */ - ut_asserteq(BIT(2) | BIT(4) | BIT(0), std->hunters_used); + ut_asserteq(BIT(MMC_HUNTER) | BIT(5) | BIT(0), std->hunters_used); return 0; } @@ -629,10 +635,13 @@ static int bootdev_test_next_prio(struct unit_test_state *uts) ut_assertok(bootdev_next_prio(&iter, &dev)); ut_asserteq_str("mmc2.bootdev", dev->name); + ut_assert_nextline("Hunting with: simple_bus"); + ut_assert_nextline("Found 2 extension board(s)."); ut_assert_nextline("Hunting with: mmc"); ut_assert_console_end(); - ut_assertok(bootstd_test_check_mmc_hunter(uts)); + /* extension in second in the list , so bit 1 */ + ut_asserteq(BIT(MMC_HUNTER) | BIT(1), std->hunters_used); ut_assertok(bootdev_next_prio(&iter, &dev)); ut_asserteq_str("mmc1.bootdev", dev->name); @@ -663,7 +672,7 @@ static int bootdev_test_next_prio(struct unit_test_state *uts) } while (!ret); ut_asserteq(-ENODEV, ret); ut_assertnull(dev); - ut_asserteq(GENMASK(7, 0), std->hunters_used); + ut_asserteq(GENMASK(MAX_HUNTER, 0), std->hunters_used); ut_assert_skip_to_line("Hunting with: ethernet"); ut_assert_console_end(); diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c index b71ec52eb7a..3a65d06696b 100644 --- a/test/boot/bootflow.c +++ b/test/boot/bootflow.c @@ -51,7 +51,7 @@ static int bootflow_cmd(struct unit_test_state *uts) console_record_reset_enable(); ut_assertok(run_command("bootdev select 1", 0)); ut_assert_console_end(); - ut_assertok(run_command("bootflow scan -l", 0)); + ut_assertok(run_command("bootflow scan -lH", 0)); ut_assert_nextline("Scanning for bootflows in bootdev 'mmc1.bootdev'"); ut_assert_nextline("Seq Method State Uclass Part Name Filename"); ut_assert_nextlinen("---"); @@ -77,17 +77,17 @@ BOOTSTD_TEST(bootflow_cmd, UT_TESTF_DM | UT_TESTF_SCAN_FDT); static int bootflow_cmd_label(struct unit_test_state *uts) { console_record_reset_enable(); - ut_assertok(run_command("bootflow scan -l mmc1", 0)); + ut_assertok(run_command("bootflow scan -lH mmc1", 0)); ut_assert_nextline("Scanning for bootflows in bootdev 'mmc1.bootdev'"); ut_assert_skip_to_line("(1 bootflow, 1 valid)"); ut_assert_console_end(); - ut_assertok(run_command("bootflow scan -l mmc0.bootdev", 0)); + ut_assertok(run_command("bootflow scan -lH mmc0.bootdev", 0)); ut_assert_nextline("Scanning for bootflows in bootdev 'mmc0.bootdev'"); ut_assert_skip_to_line("(0 bootflows, 0 valid)"); ut_assert_console_end(); - ut_assertok(run_command("bootflow scan -l 0", 0)); + ut_assertok(run_command("bootflow scan -lH 0", 0)); ut_assert_nextline("Scanning for bootflows in bootdev 'mmc2.bootdev'"); ut_assert_skip_to_line("(0 bootflows, 0 valid)"); ut_assert_console_end(); @@ -102,7 +102,7 @@ static int bootflow_cmd_glob(struct unit_test_state *uts) ut_assertok(bootstd_test_drop_bootdev_order(uts)); console_record_reset_enable(); - ut_assertok(run_command("bootflow scan -lG", 0)); + ut_assertok(run_command("bootflow scan -lGH", 0)); ut_assert_nextline("Scanning for bootflows in all bootdevs"); ut_assert_nextline("Seq Method State Uclass Part Name Filename"); ut_assert_nextlinen("---"); @@ -134,7 +134,7 @@ static int bootflow_cmd_scan_e(struct unit_test_state *uts) ut_assertok(bootstd_test_drop_bootdev_order(uts)); console_record_reset_enable(); - ut_assertok(run_command("bootflow scan -aleG", 0)); + ut_assertok(run_command("bootflow scan -aleGH", 0)); ut_assert_nextline("Scanning for bootflows in all bootdevs"); ut_assert_nextline("Seq Method State Uclass Part Name Filename"); ut_assert_nextlinen("---"); @@ -352,7 +352,7 @@ static int bootflow_system(struct unit_test_state *uts) /* We should get a single 'bootmgr' method right at the end */ bootstd_clear_glob(); console_record_reset_enable(); - ut_assertok(run_command("bootflow scan -l", 0)); + ut_assertok(run_command("bootflow scan -lH", 0)); ut_assert_skip_to_line( " 0 efi_mgr ready (none) 0 "); ut_assert_skip_to_line("No more bootdevs"); @@ -383,7 +383,7 @@ static int bootflow_iter_disable(struct unit_test_state *uts) bootstd_clear_glob(); console_record_reset_enable(); ut_assertok(inject_response(uts)); - ut_assertok(run_command("bootflow scan -lb", 0)); + ut_assertok(run_command("bootflow scan -lbH", 0)); /* Try to boot the bootmgr flow, which will fail */ console_record_reset_enable(); @@ -419,7 +419,7 @@ static int bootflow_scan_glob_bootmeth(struct unit_test_state *uts) */ console_record_reset_enable(); ut_assertok(bootmeth_set_order("efi firmware0")); - ut_assertok(run_command("bootflow scan -lG", 0)); + ut_assertok(run_command("bootflow scan -lGH", 0)); ut_assert_nextline("Scanning for bootflows in all bootdevs"); ut_assert_nextline( "Seq Method State Uclass Part Name Filename"); @@ -428,7 +428,7 @@ static int bootflow_scan_glob_bootmeth(struct unit_test_state *uts) ut_assert_nextline("(0 bootflows, 0 valid)"); ut_assert_console_end(); - ut_assertok(run_command("bootflow scan -l", 0)); + ut_assertok(run_command("bootflow scan -lH", 0)); ut_assert_nextline("Scanning for bootflows in all bootdevs"); ut_assert_nextline( "Seq Method State Uclass Part Name Filename"); diff --git a/test/boot/bootstd_common.h b/test/boot/bootstd_common.h index 0eb48fa1537..136a79b5178 100644 --- a/test/boot/bootstd_common.h +++ b/test/boot/bootstd_common.h @@ -20,6 +20,11 @@ #define TEST_VERSION "U-Boot v2022.04-local2" #define TEST_VERNUM 0x00010002 +enum { + MAX_HUNTER = 8, + MMC_HUNTER = 3, /* ID of MMC hunter */ +}; + struct unit_test_state; /** -- cgit v1.3.1 From 91943ff7038f9c47fb310dbc22150b5664c8fbf7 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 17 Jan 2023 10:48:15 -0700 Subject: bootstd: Allow scanning a single bootdev label We want to support scanning a single label, like 'mmc' or 'usb0'. Add this feature by plumbing the label through to the iterator, setting a flag to indicate that only siblings of the initial device should be used. This means that scanning a bootdev by its name is not supported anymore. That feature doesn't seem very useful in practice, so it is no great loss. Add a test for bootdev_find_by_any() while we are here. Signed-off-by: Simon Glass --- boot/bootdev-uclass.c | 28 ++++++++++++----- boot/bootflow.c | 43 ++++++++++++++++++++++---- cmd/bootflow.c | 86 ++++++++++++++++++++------------------------------- include/bootdev.h | 11 ++++--- include/bootflow.h | 10 ++++-- test/boot/bootdev.c | 2 +- test/boot/bootflow.c | 62 +++++++++++++++++++++++++++++++++++-- 7 files changed, 166 insertions(+), 76 deletions(-) (limited to 'cmd') diff --git a/boot/bootdev-uclass.c b/boot/bootdev-uclass.c index 334be7662a1..522ecf38eb3 100644 --- a/boot/bootdev-uclass.c +++ b/boot/bootdev-uclass.c @@ -649,10 +649,10 @@ int bootdev_next_prio(struct bootflow_iter *iter, struct udevice **devp) return 0; } -int bootdev_setup_iter(struct bootflow_iter *iter, struct udevice **devp, - int *method_flagsp) +int bootdev_setup_iter(struct bootflow_iter *iter, const char *label, + struct udevice **devp, int *method_flagsp) { - struct udevice *bootstd, *dev = *devp; + struct udevice *bootstd, *dev = NULL; bool show = iter->flags & BOOTFLOWF_SHOW; int method_flags; int ret; @@ -671,10 +671,24 @@ int bootdev_setup_iter(struct bootflow_iter *iter, struct udevice **devp, } /* Handle scanning a single device */ - if (dev) { - iter->flags |= BOOTFLOWF_SINGLE_DEV; - log_debug("Selected boodev: %s\n", dev->name); - method_flags = 0; + if (IS_ENABLED(CONFIG_BOOTSTD_FULL) && label) { + if (iter->flags & BOOTFLOWF_HUNT) { + ret = bootdev_hunt(label, show); + if (ret) + return log_msg_ret("hun", ret); + } + ret = bootdev_find_by_any(label, &dev, &method_flags); + if (ret) + return log_msg_ret("lab", ret); + + log_debug("method_flags: %x\n", method_flags); + if (method_flags & BOOTFLOW_METHF_SINGLE_UCLASS) + iter->flags |= BOOTFLOWF_SINGLE_UCLASS; + else if (method_flags & BOOTFLOW_METHF_SINGLE_DEV) + iter->flags |= BOOTFLOWF_SINGLE_DEV; + else + iter->flags |= BOOTFLOWF_SINGLE_MEDIA; + log_debug("Selected label: %s, flags %x\n", label, iter->flags); } else { bool ok; diff --git a/boot/bootflow.c b/boot/bootflow.c index 32e2aad470d..50d9c2e813a 100644 --- a/boot/bootflow.c +++ b/boot/bootflow.c @@ -215,7 +215,37 @@ static int iter_incr(struct bootflow_iter *iter) dev = iter->dev; log_debug("inc_dev=%d\n", inc_dev); if (!inc_dev) { - ret = bootdev_setup_iter(iter, &dev, &method_flags); + ret = bootdev_setup_iter(iter, NULL, &dev, + &method_flags); + } else if (IS_ENABLED(CONFIG_BOOTSTD_FULL) && + (iter->flags & BOOTFLOWF_SINGLE_UCLASS)) { + /* Move to the next bootdev in this uclass */ + uclass_find_next_device(&dev); + if (!dev) { + log_debug("finished uclass %s\n", + dev_get_uclass_name(dev)); + ret = -ENODEV; + } + } else if (IS_ENABLED(CONFIG_BOOTSTD_FULL) && + iter->flags & BOOTFLOWF_SINGLE_MEDIA) { + log_debug("next in single\n"); + method_flags = 0; + do { + /* + * Move to the next bootdev child of this media + * device. This ensures that we cover all the + * available SCSI IDs and LUNs. + */ + device_find_next_child(&dev); + log_debug("- next %s\n", + dev ? dev->name : "(none)"); + } while (dev && device_get_uclass_id(dev) != + UCLASS_BOOTDEV); + if (!dev) { + log_debug("finished uclass %s\n", + dev_get_uclass_name(dev)); + ret = -ENODEV; + } } else { log_debug("labels %p\n", iter->labels); if (iter->labels) { @@ -294,12 +324,13 @@ static int bootflow_check(struct bootflow_iter *iter, struct bootflow *bflow) return 0; } -int bootflow_scan_bootdev(struct udevice *dev, struct bootflow_iter *iter, - int flags, struct bootflow *bflow) +int bootflow_scan_bootdev(struct udevice *dev, const char *label, + struct bootflow_iter *iter, int flags, + struct bootflow *bflow) { int ret; - if (dev) + if (dev || label) flags |= BOOTFLOWF_SKIP_GLOBAL; bootflow_iter_init(iter, flags); @@ -318,7 +349,7 @@ int bootflow_scan_bootdev(struct udevice *dev, struct bootflow_iter *iter, struct udevice *dev = NULL; int method_flags; - ret = bootdev_setup_iter(iter, &dev, &method_flags); + ret = bootdev_setup_iter(iter, label, &dev, &method_flags); if (ret) return log_msg_ret("obdev", -ENODEV); @@ -345,7 +376,7 @@ int bootflow_scan_first(struct bootflow_iter *iter, int flags, { int ret; - ret = bootflow_scan_bootdev(NULL, iter, flags, bflow); + ret = bootflow_scan_bootdev(NULL, NULL, iter, flags, bflow); if (ret) return log_msg_ret("start", ret); diff --git a/cmd/bootflow.c b/cmd/bootflow.c index fe58de5fa59..72d5a8424e9 100644 --- a/cmd/bootflow.c +++ b/cmd/bootflow.c @@ -93,11 +93,12 @@ static int do_bootflow_scan(struct cmd_tbl *cmdtp, int flag, int argc, { struct bootstd_priv *std; struct bootflow_iter iter; - struct udevice *dev; + struct udevice *dev = NULL; struct bootflow bflow; bool all = false, boot = false, errors = false, no_global = false; bool list = false, no_hunter = false; int num_valid = 0; + const char *label = NULL; bool has_args; int ret, i; int flags; @@ -105,7 +106,6 @@ static int do_bootflow_scan(struct cmd_tbl *cmdtp, int flag, int argc, ret = bootstd_get_priv(&std); if (ret) return CMD_RET_FAILURE; - dev = std->cur_bootdev; has_args = argc > 1 && *argv[1] == '-'; if (IS_ENABLED(CONFIG_CMD_BOOTFLOW_FULL)) { @@ -119,12 +119,10 @@ static int do_bootflow_scan(struct cmd_tbl *cmdtp, int flag, int argc, argc--; argv++; } - if (argc > 1) { - const char *label = argv[1]; - - if (bootdev_find_by_any(label, &dev, NULL)) - return CMD_RET_FAILURE; - } + if (argc > 1) + label = argv[1]; + if (!label) + dev = std->cur_bootdev; } else { if (has_args) { printf("Flags not supported: enable CONFIG_BOOTFLOW_FULL\n"); @@ -148,54 +146,36 @@ static int do_bootflow_scan(struct cmd_tbl *cmdtp, int flag, int argc, /* * If we have a device, just scan for bootflows attached to that device */ - if (IS_ENABLED(CONFIG_CMD_BOOTFLOW_FULL) && dev) { - if (list) { - printf("Scanning for bootflows in bootdev '%s'\n", - dev->name); - show_header(); - } + if (list) { + printf("Scanning for bootflows "); + if (dev) + printf("in bootdev '%s'\n", dev->name); + else if (label) + printf("with label '%s'\n", label); + else + printf("in all bootdevs\n"); + show_header(); + } + if (dev) bootdev_clear_bootflows(dev); - for (i = 0, - ret = bootflow_scan_bootdev(dev, &iter, flags, &bflow); - i < 1000 && ret != -ENODEV; - i++, ret = bootflow_scan_next(&iter, &bflow)) { - bflow.err = ret; - if (!ret) - num_valid++; - ret = bootdev_add_bootflow(&bflow); - if (ret) { - printf("Out of memory\n"); - return CMD_RET_FAILURE; - } - if (list) - show_bootflow(i, &bflow, errors); - if (boot && !bflow.err) - bootflow_run_boot(&iter, &bflow); - } - } else { - if (list) { - printf("Scanning for bootflows in all bootdevs\n"); - show_header(); - } + else bootstd_clear_glob(); - - for (i = 0, - ret = bootflow_scan_first(&iter, flags, &bflow); - i < 1000 && ret != -ENODEV; - i++, ret = bootflow_scan_next(&iter, &bflow)) { - bflow.err = ret; - if (!ret) - num_valid++; - ret = bootdev_add_bootflow(&bflow); - if (ret) { - printf("Out of memory\n"); - return CMD_RET_FAILURE; - } - if (list) - show_bootflow(i, &bflow, errors); - if (boot && !bflow.err) - bootflow_run_boot(&iter, &bflow); + for (i = 0, + ret = bootflow_scan_bootdev(dev, label, &iter, flags, &bflow); + i < 1000 && ret != -ENODEV; + i++, ret = bootflow_scan_next(&iter, &bflow)) { + bflow.err = ret; + if (!ret) + num_valid++; + ret = bootdev_add_bootflow(&bflow); + if (ret) { + printf("Out of memory\n"); + return CMD_RET_FAILURE; } + if (list) + show_bootflow(i, &bflow, errors); + if (boot && !bflow.err) + bootflow_run_boot(&iter, &bflow); } bootflow_iter_uninit(&iter); if (list) diff --git a/include/bootdev.h b/include/bootdev.h index 8fa67487c63..b92ff4d4f15 100644 --- a/include/bootdev.h +++ b/include/bootdev.h @@ -267,10 +267,13 @@ int bootdev_find_by_any(const char *name, struct udevice **devp, /** * bootdev_setup_iter() - Set up iteration through bootdevs * - * This sets up the an interation, based on the priority of each bootdev, the - * bootdev-order property in the bootstd node (or the boot_targets env var). + * This sets up the an interation, based on the provided device or label. If + * neither is provided, the iteration is based on the priority of each bootdev, + * the * bootdev-order property in the bootstd node (or the boot_targets env + * var). * * @iter: Iterator to update with the order + * @label: label to scan, or NULL to scan all * @devp: On entry, *devp is NULL to scan all, otherwise this is the (single) * device to scan. Returns the first device to use, which is the passed-in * @devp if it was non-NULL @@ -279,8 +282,8 @@ int bootdev_find_by_any(const char *name, struct udevice **devp, * Return: 0 if OK, -ENOENT if no bootdevs, -ENOMEM if out of memory, other -ve * on other error */ -int bootdev_setup_iter(struct bootflow_iter *iter, struct udevice **devp, - int *method_flagsp); +int bootdev_setup_iter(struct bootflow_iter *iter, const char *label, + struct udevice **devp, int *method_flagsp); /** * bootdev_list_hunters() - List the available bootdev hunters diff --git a/include/bootflow.h b/include/bootflow.h index bdb37352ab9..1b7920a9572 100644 --- a/include/bootflow.h +++ b/include/bootflow.h @@ -255,14 +255,18 @@ int bootflow_iter_drop_bootmeth(struct bootflow_iter *iter, * * @dev: Boot device to scan, NULL to work through all of them until it * finds one that can supply a bootflow + * @label: Label to control the scan, NULL to work through all devices + * until it finds one that can supply a bootflow * @iter: Place to store private info (inited by this call) - * @flags: Flags for iterator (enum bootflow_flags_t) + * @flags: Flags for iterator (enum bootflow_flags_t). Note that if @dev + * is NULL, then BOOTFLOWF_SKIP_GLOBAL is set automatically by this function * @bflow: Place to put the bootflow if found * Return: 0 if found, -ENODEV if no device, other -ve on other error * (iteration can continue) */ -int bootflow_scan_bootdev(struct udevice *dev, struct bootflow_iter *iter, - int flags, struct bootflow *bflow); +int bootflow_scan_bootdev(struct udevice *dev, const char *label, + struct bootflow_iter *iter, int flags, + struct bootflow *bflow); /** * bootflow_scan_first() - find the first bootflow diff --git a/test/boot/bootdev.c b/test/boot/bootdev.c index 679ffc4d8df..1724e34af3e 100644 --- a/test/boot/bootdev.c +++ b/test/boot/bootdev.c @@ -626,7 +626,7 @@ static int bootdev_test_next_prio(struct unit_test_state *uts) struct udevice *dev; int ret; - sandbox_set_eth_enable(false); + test_set_eth_enable(false); test_set_skip_delays(true); /* get access to the used hunters */ diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c index 1a2c54c1119..0b3a2fa6acc 100644 --- a/test/boot/bootflow.c +++ b/test/boot/bootflow.c @@ -76,7 +76,6 @@ static int bootflow_cmd(struct unit_test_state *uts) } BOOTSTD_TEST(bootflow_cmd, UT_TESTF_DM | UT_TESTF_SCAN_FDT); -#if 0 /* disable for now */ /* Check 'bootflow scan' with a label / seq */ static int bootflow_cmd_label(struct unit_test_state *uts) { @@ -124,7 +123,6 @@ static int bootflow_cmd_label(struct unit_test_state *uts) } BOOTSTD_TEST(bootflow_cmd_label, UT_TESTF_DM | UT_TESTF_SCAN_FDT | UT_TESTF_ETH_BOOTDEV); -#endif /* Check 'bootflow scan/list' commands using all bootdevs */ static int bootflow_cmd_glob(struct unit_test_state *uts) @@ -564,6 +562,66 @@ static int bootflow_cmd_menu(struct unit_test_state *uts) } BOOTSTD_TEST(bootflow_cmd_menu, UT_TESTF_DM | UT_TESTF_SCAN_FDT); +/* Check searching for a single bootdev using the hunters */ +static int bootflow_cmd_hunt_single(struct unit_test_state *uts) +{ + struct bootstd_priv *std; + + /* get access to the used hunters */ + ut_assertok(bootstd_get_priv(&std)); + + ut_assertok(bootstd_test_drop_bootdev_order(uts)); + + console_record_reset_enable(); + ut_assertok(run_command("bootflow scan -l mmc1", 0)); + ut_assert_nextline("Scanning for bootflows with label 'mmc1'"); + ut_assert_skip_to_line("(1 bootflow, 1 valid)"); + ut_assert_console_end(); + + /* check that the hunter was used */ + ut_asserteq(BIT(MMC_HUNTER) | BIT(1), std->hunters_used); + + return 0; +} +BOOTSTD_TEST(bootflow_cmd_hunt_single, UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +/* Check searching for a uclass label using the hunters */ +static int bootflow_cmd_hunt_label(struct unit_test_state *uts) +{ + struct bootstd_priv *std; + + /* get access to the used hunters */ + ut_assertok(bootstd_get_priv(&std)); + + test_set_skip_delays(true); + test_set_eth_enable(false); + ut_assertok(bootstd_test_drop_bootdev_order(uts)); + + console_record_reset_enable(); + ut_assertok(run_command("bootflow scan -l mmc", 0)); + + /* check that the hunter was used */ + ut_asserteq(BIT(MMC_HUNTER) | BIT(1), std->hunters_used); + + /* check that we got the mmc1 bootflow */ + ut_assert_nextline("Scanning for bootflows with label 'mmc'"); + ut_assert_nextlinen("Seq"); + ut_assert_nextlinen("---"); + ut_assert_nextline("Hunting with: simple_bus"); + ut_assert_nextline("Found 2 extension board(s)."); + ut_assert_nextline("Hunting with: mmc"); + ut_assert_nextline("Scanning bootdev 'mmc2.bootdev':"); + ut_assert_nextline("Scanning bootdev 'mmc1.bootdev':"); + ut_assert_nextline( + " 0 syslinux ready mmc 1 mmc1.bootdev.part_1 /extlinux/extlinux.conf"); + ut_assert_nextline("Scanning bootdev 'mmc0.bootdev':"); + ut_assert_skip_to_line("(1 bootflow, 1 valid)"); + ut_assert_console_end(); + + return 0; +} +BOOTSTD_TEST(bootflow_cmd_hunt_label, UT_TESTF_DM | UT_TESTF_SCAN_FDT); + /** * check_font() - Check that the font size for an item matches expectations * -- cgit v1.3.1 From 4b7cb058df35222632efa3f71aad63757b226440 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 17 Jan 2023 10:48:16 -0700 Subject: bootstd: Drop the old bootflow_scan_first() This function is not used outside tests. Drop it and rename bootflow_scan_dev() since it is how we start a scan now. Signed-off-by: Simon Glass --- boot/bootflow.c | 18 +++--------------- cmd/bootflow.c | 2 +- include/bootflow.h | 23 +++-------------------- test/boot/bootdev.c | 16 +++++++++------- test/boot/bootflow.c | 5 +++-- 5 files changed, 19 insertions(+), 45 deletions(-) (limited to 'cmd') diff --git a/boot/bootflow.c b/boot/bootflow.c index 50d9c2e813a..750732f7083 100644 --- a/boot/bootflow.c +++ b/boot/bootflow.c @@ -324,9 +324,9 @@ static int bootflow_check(struct bootflow_iter *iter, struct bootflow *bflow) return 0; } -int bootflow_scan_bootdev(struct udevice *dev, const char *label, - struct bootflow_iter *iter, int flags, - struct bootflow *bflow) +int bootflow_scan_first(struct udevice *dev, const char *label, + struct bootflow_iter *iter, int flags, + struct bootflow *bflow) { int ret; @@ -371,18 +371,6 @@ int bootflow_scan_bootdev(struct udevice *dev, const char *label, return 0; } -int bootflow_scan_first(struct bootflow_iter *iter, int flags, - struct bootflow *bflow) -{ - int ret; - - ret = bootflow_scan_bootdev(NULL, NULL, iter, flags, bflow); - if (ret) - return log_msg_ret("start", ret); - - return 0; -} - int bootflow_scan_next(struct bootflow_iter *iter, struct bootflow *bflow) { int ret; diff --git a/cmd/bootflow.c b/cmd/bootflow.c index 72d5a8424e9..692bc6d117f 100644 --- a/cmd/bootflow.c +++ b/cmd/bootflow.c @@ -161,7 +161,7 @@ static int do_bootflow_scan(struct cmd_tbl *cmdtp, int flag, int argc, else bootstd_clear_glob(); for (i = 0, - ret = bootflow_scan_bootdev(dev, label, &iter, flags, &bflow); + ret = bootflow_scan_first(dev, label, &iter, flags, &bflow); i < 1000 && ret != -ENODEV; i++, ret = bootflow_scan_next(&iter, &bflow)) { bflow.err = ret; diff --git a/include/bootflow.h b/include/bootflow.h index 1b7920a9572..c2368912061 100644 --- a/include/bootflow.h +++ b/include/bootflow.h @@ -249,7 +249,7 @@ int bootflow_iter_drop_bootmeth(struct bootflow_iter *iter, const struct udevice *bmeth); /** - * bootflow_scan_bootdev() - find the first bootflow in a bootdev + * bootflow_scan_first() - find the first bootflow for a device or label * * If @flags includes BOOTFLOWF_ALL then bootflows with errors are returned too * @@ -264,25 +264,8 @@ int bootflow_iter_drop_bootmeth(struct bootflow_iter *iter, * Return: 0 if found, -ENODEV if no device, other -ve on other error * (iteration can continue) */ -int bootflow_scan_bootdev(struct udevice *dev, const char *label, - struct bootflow_iter *iter, int flags, - struct bootflow *bflow); - -/** - * bootflow_scan_first() - find the first bootflow - * - * This works through the available bootdev devices until it finds one that - * can supply a bootflow. It then returns that - * - * If @flags includes BOOTFLOWF_ALL then bootflows with errors are returned too - * - * @iter: Place to store private info (inited by this call), with - * @flags: Flags for bootdev (enum bootflow_flags_t) - * @bflow: Place to put the bootflow if found - * Return: 0 if found, -ENODEV if no device, other -ve on other error (iteration - * can continue) - */ -int bootflow_scan_first(struct bootflow_iter *iter, int flags, +int bootflow_scan_first(struct udevice *dev, const char *label, + struct bootflow_iter *iter, int flags, struct bootflow *bflow); /** diff --git a/test/boot/bootdev.c b/test/boot/bootdev.c index 1724e34af3e..5d5ce7f48cf 100644 --- a/test/boot/bootdev.c +++ b/test/boot/bootdev.c @@ -203,7 +203,7 @@ static int bootdev_test_order(struct unit_test_state *uts) * mmc2 - nothing connected */ ut_assertok(env_set("boot_targets", NULL)); - ut_assertok(bootflow_scan_first(&iter, 0, &bflow)); + ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow)); ut_asserteq(2, iter.num_devs); ut_asserteq_str("mmc2.bootdev", iter.dev_order[0]->name); ut_asserteq_str("mmc1.bootdev", iter.dev_order[1]->name); @@ -211,7 +211,7 @@ static int bootdev_test_order(struct unit_test_state *uts) /* Use the environment variable to override it */ ut_assertok(env_set("boot_targets", "mmc1 mmc2")); - ut_assertok(bootflow_scan_first(&iter, 0, &bflow)); + ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow)); ut_asserteq(2, iter.num_devs); ut_asserteq_str("mmc1.bootdev", iter.dev_order[0]->name); ut_asserteq_str("mmc2.bootdev", iter.dev_order[1]->name); @@ -224,7 +224,7 @@ static int bootdev_test_order(struct unit_test_state *uts) ut_assertok(env_set("boot_targets", NULL)); ut_assertok(bootstd_test_drop_bootdev_order(uts)); - ut_assertok(bootflow_scan_first(&iter, 0, &bflow)); + ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow)); ut_asserteq(3, iter.num_devs); ut_asserteq_str("mmc2.bootdev", iter.dev_order[0]->name); ut_asserteq_str("mmc1.bootdev", iter.dev_order[1]->name); @@ -239,7 +239,7 @@ static int bootdev_test_order(struct unit_test_state *uts) iter.dev_order[2]->seq_ = 2; bootflow_iter_uninit(&iter); - ut_assertok(bootflow_scan_first(&iter, 0, &bflow)); + ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow)); ut_asserteq(3, iter.num_devs); ut_asserteq_str("mmc2.bootdev", iter.dev_order[0]->name); ut_asserteq_str("mmc0.bootdev", iter.dev_order[1]->name); @@ -268,7 +268,7 @@ static int bootdev_test_prio(struct unit_test_state *uts) /* 3 MMC and 3 USB bootdevs: MMC should come before USB */ console_record_reset_enable(); - ut_assertok(bootflow_scan_first(&iter, 0, &bflow)); + ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow)); ut_asserteq(6, iter.num_devs); ut_asserteq_str("mmc2.bootdev", iter.dev_order[0]->name); ut_asserteq_str("usb_mass_storage.lun0.bootdev", @@ -282,7 +282,8 @@ static int bootdev_test_prio(struct unit_test_state *uts) ucp->prio = 1; bootflow_iter_uninit(&iter); - ut_assertok(bootflow_scan_first(&iter, 0, &bflow)); + ut_assertok(bootflow_scan_first(NULL, NULL, &iter, BOOTFLOWF_HUNT, + &bflow)); ut_asserteq(6, iter.num_devs); ut_asserteq_str("usb_mass_storage.lun0.bootdev", iter.dev_order[0]->name); @@ -415,7 +416,8 @@ static int bootdev_test_hunt_scan(struct unit_test_state *uts) ut_assertok(bootstd_get_priv(&std)); ut_assertok(bootstd_test_drop_bootdev_order(uts)); - ut_assertok(bootflow_scan_first(&iter, BOOTFLOWF_SHOW | BOOTFLOWF_HUNT | + ut_assertok(bootflow_scan_first(NULL, NULL, &iter, + BOOTFLOWF_SHOW | BOOTFLOWF_HUNT | BOOTFLOWF_SKIP_GLOBAL, &bflow)); ut_asserteq(BIT(MMC_HUNTER) | BIT(1), std->hunters_used); diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c index 0b3a2fa6acc..b9284fc464a 100644 --- a/test/boot/bootflow.c +++ b/test/boot/bootflow.c @@ -276,7 +276,8 @@ static int bootflow_iter(struct unit_test_state *uts) /* The first device is mmc2.bootdev which has no media */ ut_asserteq(-EPROTONOSUPPORT, - bootflow_scan_first(&iter, BOOTFLOWF_ALL | BOOTFLOWF_SKIP_GLOBAL, &bflow)); + bootflow_scan_first(NULL, NULL, &iter, + BOOTFLOWF_ALL | BOOTFLOWF_SKIP_GLOBAL, &bflow)); ut_asserteq(2, iter.num_methods); ut_asserteq(0, iter.cur_method); ut_asserteq(0, iter.part); @@ -415,7 +416,7 @@ static int bootflow_iter_disable(struct unit_test_state *uts) /* Try to boot the bootmgr flow, which will fail */ console_record_reset_enable(); - ut_assertok(bootflow_scan_first(&iter, 0, &bflow)); + ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow)); ut_asserteq(3, iter.num_methods); ut_asserteq_str("sandbox", iter.method->name); ut_assertok(inject_response(uts)); -- cgit v1.3.1