From patchwork Wed Dec 7 08:51:32 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1713166 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=cQYCqHxI; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4NRs2h1Mt9z23yq for ; Wed, 7 Dec 2022 20:10:52 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 65589855AA; Wed, 7 Dec 2022 10:04:02 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="cQYCqHxI"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 686B984BD1; Wed, 7 Dec 2022 10:03:59 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.2 Received: from mail-pf1-x429.google.com (mail-pf1-x429.google.com [IPv6:2607:f8b0:4864:20::429]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 61B3685748 for ; Wed, 7 Dec 2022 09:57:41 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-pf1-x429.google.com with SMTP id c13so9851073pfp.5 for ; Wed, 07 Dec 2022 00:57:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=n/gOUJPhduG4/Ue3SztJArVn08OWNiGTpsDFHKYmLHQ=; b=cQYCqHxIOfX8tFVb+5rAbG7OubreAIXrkTcUAD2+GyABL+2jzlD+AROCk/2vWgVqoj +Vr86FCUfg9qViD8Ljoy9ddFrWFbCFe7aXiAFx3IIO1XFca7J3lL0EV0S+4ldKnWEJxR MVm5Fl2nOR2ie/BTM2AcaCOMuOXgD8FYJuk1I= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=n/gOUJPhduG4/Ue3SztJArVn08OWNiGTpsDFHKYmLHQ=; b=AZRwxtGwk+kHQlS7gBWaBkryxI4Fbr45+oEkvcnth/R3jKq2MTLlw5jx5r3UAXc3VG 7JypNSGy7Imfz4T6S/u8hVHH1duW5KNLivsxNiX025HY0fSi72yDybo9zyTolveI+w57 d1UgS8TEpABjV79uRjLx+rPnuMC64dT/h44vA6bCDpDRaWSwxSZ+QH6eMM9g94P9w+Lw ZtwPhvw6M2NkN9vgR0ZjQtbkL/auW5UKffgrfZP4mFNbIIHOQjr3QShmsVrrun5+s1/i vxDVQOkI2jEl+peVFZigbcknpBVTBKJv50Dgf50Id5DbFQASuSpsMS5gGl5dF9mj3/e9 XzcA== X-Gm-Message-State: ANoB5plgbzTTp4Nn8Y6GySsfygYxiN8yTbc2O3jK1u11UygdoXgK9+FR dcGRz0oi38yiBWa8UZmTTU2oQ8WASstHd64/ X-Google-Smtp-Source: AA0mqf6m5dHUU6dpNSydTHCIHyEFeyso5EHdVyWopf6IzlPT0kyKL9k5fzx7rNaiL9RyhHFv33j2Tw== X-Received: by 2002:a62:aa15:0:b0:576:dc64:2dee with SMTP id e21-20020a62aa15000000b00576dc642deemr14966767pff.2.1670403459281; Wed, 07 Dec 2022 00:57:39 -0800 (PST) Received: from localhost.localdomain ([27.110.126.54]) by smtp.gmail.com with ESMTPSA id l16-20020a170903121000b0018157b415dbsm14145514plh.63.2022.12.07.00.57.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 07 Dec 2022 00:57:39 -0800 (PST) From: Simon Glass To: U-Boot Mailing List Cc: U-Boot Custodians , Simon Glass Subject: [PATCH 66/71] bootstd: Allow scanning a single bootdev label Date: Wed, 7 Dec 2022 21:51:32 +1300 Message-Id: <20221207085137.445249-67-sjg@chromium.org> X-Mailer: git-send-email 2.39.0.rc0.267.gcb52ba06e7-goog In-Reply-To: <20221207085137.445249-1-sjg@chromium.org> References: <20221207085137.445249-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.6 at phobos.denx.de X-Virus-Status: Clean 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(-) 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 b84df6fefbe..da462a6ffdc 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 fdccb775a15..040ecf3a088 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 bd97162c309..738edd22a0a 100644 --- a/include/bootflow.h +++ b/include/bootflow.h @@ -244,14 +244,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 1d1d88934a4..6c7e7c813f3 100644 --- a/test/boot/bootflow.c +++ b/test/boot/bootflow.c @@ -68,7 +68,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) { @@ -116,7 +115,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) @@ -494,3 +492,63 @@ static int bootflow_cmd_boot(struct unit_test_state *uts) return 0; } BOOTSTD_TEST(bootflow_cmd_boot, 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);