From abd1e94f70c9a2828d5ebec05013b055fb33c21d Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 23 Oct 2023 00:02:10 -0700 Subject: Revert "bootstd: Scan all bootdevs in a boot_targets entry" This commit was intended to allow all bootdevs in each boot_targets entry to be scanned. However it causes bad ordering with bootdevs, e.g. scanning Ethernet bootdevs when it should be keeping to mmc. Revert it so we can try another approach. This reverts commit e824d0d0c219bc6da767f13f90c5b00eefe929f0. Signed-off-by: Simon Glass Tested-by: Ivan T.Ivanov --- boot/bootdev-uclass.c | 3 +-- boot/bootflow.c | 21 ++------------------- test/boot/bootdev.c | 10 ---------- 3 files changed, 3 insertions(+), 31 deletions(-) diff --git a/boot/bootdev-uclass.c b/boot/bootdev-uclass.c index 44ae98a9269..974ddee5d2f 100644 --- a/boot/bootdev-uclass.c +++ b/boot/bootdev-uclass.c @@ -469,11 +469,10 @@ int bootdev_find_by_label(const char *label, struct udevice **devp, * if no sequence number was provided, we must scan all * bootdevs for this media uclass */ - if (seq == -1) + if (IS_ENABLED(CONFIG_BOOTSTD_FULL) && seq == -1) method_flags |= BOOTFLOW_METHF_SINGLE_UCLASS; if (method_flagsp) *method_flagsp = method_flags; - log_debug("method flags %x\n", method_flags); return 0; } log_debug("- no device in %s\n", media->name); diff --git a/boot/bootflow.c b/boot/bootflow.c index e03932e65a7..6ef62e1d189 100644 --- a/boot/bootflow.c +++ b/boot/bootflow.c @@ -260,25 +260,8 @@ static int iter_incr(struct bootflow_iter *iter) } else { log_debug("labels %p\n", iter->labels); if (iter->labels) { - /* - * when the label is "mmc" we want to scan all - * mmc bootdevs, not just the first. See - * bootdev_find_by_label() where this flag is - * set up - */ - if (iter->method_flags & BOOTFLOW_METHF_SINGLE_UCLASS) { - uclass_next_device(&dev); - log_debug("looking for next device %s: %s\n", - iter->dev->name, - dev ? dev->name : ""); - } else { - dev = NULL; - } - if (!dev) { - log_debug("looking at next label\n"); - ret = bootdev_next_label(iter, &dev, - &method_flags); - } + ret = bootdev_next_label(iter, &dev, + &method_flags); } else { ret = bootdev_next_prio(iter, &dev); method_flags = 0; diff --git a/test/boot/bootdev.c b/test/boot/bootdev.c index c5f14a7a132..6b29213416d 100644 --- a/test/boot/bootdev.c +++ b/test/boot/bootdev.c @@ -221,16 +221,6 @@ static int bootdev_test_order(struct unit_test_state *uts) ut_asserteq_str("mmc2.bootdev", iter.dev_used[1]->name); bootflow_iter_uninit(&iter); - /* Make sure it scans a bootdevs in each target */ - ut_assertok(env_set("boot_targets", "mmc spi")); - ut_asserteq(0, bootflow_scan_first(NULL, NULL, &iter, 0, &bflow)); - ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow)); - ut_asserteq(3, iter.num_devs); - ut_asserteq_str("mmc2.bootdev", iter.dev_used[0]->name); - ut_asserteq_str("mmc1.bootdev", iter.dev_used[1]->name); - ut_asserteq_str("mmc0.bootdev", iter.dev_used[2]->name); - bootflow_iter_uninit(&iter); - return 0; } BOOTSTD_TEST(bootdev_test_order, UT_TESTF_DM | UT_TESTF_SCAN_FDT); -- cgit v1.2.3 From 7ae83bfaf437320ec6b6e883bd2896fba784fbf9 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 23 Oct 2023 00:02:11 -0700 Subject: bootstd: Expand boot-ordering test to include USB Scan the USB bus as well, so we can check that different uclasses work correctly in boot_targets update the function comment with more detail. Signed-off-by: Simon Glass Tested-by: Ivan T.Ivanov --- test/boot/bootdev.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/test/boot/bootdev.c b/test/boot/bootdev.c index 6b29213416d..7228f545e9e 100644 --- a/test/boot/bootdev.c +++ b/test/boot/bootdev.c @@ -190,12 +190,21 @@ static int bootdev_test_any(struct unit_test_state *uts) BOOTSTD_TEST(bootdev_test_any, UT_TESTF_DM | UT_TESTF_SCAN_FDT | UT_TESTF_ETH_BOOTDEV); -/* Check bootdev ordering with the bootdev-order property */ +/* + * Check bootdev ordering with the bootdev-order property and boot_targets + * environment variable + */ static int bootdev_test_order(struct unit_test_state *uts) { struct bootflow_iter iter; struct bootflow bflow; + test_set_skip_delays(true); + + /* Start up USB which gives us three additional bootdevs */ + usb_started = false; + ut_assertok(run_command("usb start", 0)); + /* * First try the order set by the bootdev-order property * Like all sandbox unit tests this relies on the devicetree setting up @@ -213,12 +222,14 @@ static int bootdev_test_order(struct unit_test_state *uts) bootflow_iter_uninit(&iter); /* Use the environment variable to override it */ - ut_assertok(env_set("boot_targets", "mmc1 mmc2")); + ut_assertok(env_set("boot_targets", "mmc1 mmc2 usb")); ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow)); ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow)); - ut_asserteq(2, iter.num_devs); + ut_asserteq(3, iter.num_devs); ut_asserteq_str("mmc1.bootdev", iter.dev_used[0]->name); ut_asserteq_str("mmc2.bootdev", iter.dev_used[1]->name); + ut_asserteq_str("usb_mass_storage.lun0.bootdev", + iter.dev_used[2]->name); bootflow_iter_uninit(&iter); return 0; -- cgit v1.2.3 From 16e19350d91e3c7e916b85b84c0364b20ac193d2 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 23 Oct 2023 00:02:12 -0700 Subject: bootstd: Correct logic for single uclass The current logic for "bootflow mmc" is flawed since it checks the uclass of the bootdev instead of its parent, the media device. Correct this and add a test that covers this scenario. Signed-off-by: Simon Glass Tested-by: Ivan T.Ivanov --- boot/bootflow.c | 24 ++++++++++++++++++++++-- test/boot/bootdev.c | 13 +++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/boot/bootflow.c b/boot/bootflow.c index 6ef62e1d189..7f5b0e94207 100644 --- a/boot/bootflow.c +++ b/boot/bootflow.c @@ -155,6 +155,27 @@ static void bootflow_iter_set_dev(struct bootflow_iter *iter, } } +/** + * scan_next_in_uclass() - Scan for the next bootdev in the same media uclass + * + * Move through the following bootdevs until we find another in this media + * uclass, or run out + * + * @devp: On entry, the device to check, on exit the new device, or NULL if + * there is none + */ +static void scan_next_in_uclass(struct udevice **devp) +{ + struct udevice *dev = *devp; + enum uclass_id cur_id = device_get_uclass_id(dev->parent); + + do { + uclass_find_next_device(&dev); + } while (dev && cur_id != device_get_uclass_id(dev->parent)); + + *devp = dev; +} + /** * iter_incr() - Move to the next item (method, part, bootdev) * @@ -230,8 +251,7 @@ static int iter_incr(struct bootflow_iter *iter) &method_flags); } else if (IS_ENABLED(CONFIG_BOOTSTD_FULL) && (iter->flags & BOOTFLOWIF_SINGLE_UCLASS)) { - /* Move to the next bootdev in this uclass */ - uclass_find_next_device(&dev); + scan_next_in_uclass(&dev); if (!dev) { log_debug("finished uclass %s\n", dev_get_uclass_name(dev)); diff --git a/test/boot/bootdev.c b/test/boot/bootdev.c index 7228f545e9e..63786174805 100644 --- a/test/boot/bootdev.c +++ b/test/boot/bootdev.c @@ -232,6 +232,19 @@ static int bootdev_test_order(struct unit_test_state *uts) iter.dev_used[2]->name); bootflow_iter_uninit(&iter); + /* Try a single uclass */ + ut_assertok(env_set("boot_targets", NULL)); + ut_assertok(bootflow_scan_first(NULL, "mmc", &iter, 0, &bflow)); + ut_asserteq(2, iter.num_devs); + + /* Now scan pass mmc1 and make sure that only mmc0 shows up */ + ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow)); + ut_asserteq(3, iter.num_devs); + ut_asserteq_str("mmc2.bootdev", iter.dev_used[0]->name); + ut_asserteq_str("mmc1.bootdev", iter.dev_used[1]->name); + ut_asserteq_str("mmc0.bootdev", iter.dev_used[2]->name); + bootflow_iter_uninit(&iter); + return 0; } BOOTSTD_TEST(bootdev_test_order, UT_TESTF_DM | UT_TESTF_SCAN_FDT); -- cgit v1.2.3 From 7a790f018a812b5897fc144c46291de8df633429 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 23 Oct 2023 00:02:13 -0700 Subject: bootstd: Scan all bootdevs in a boot_targets entry (take 2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the boot_targets environment variable is used with the distro-boot scripts, each device is included individually. For example, if there are three mmc devices, then we will have something like: boot_targets="mmc0 mmc1 mmc2" In contrast, standard boot supports specifying just the uclass, i.e.: boot_targets="mmc" The intention is that this should scan all MMC devices, but in fact it currently only scans the first. Update the logic to handle this case, without required BOOTSTD_FULL to be enabled. Signed-off-by: Simon Glass Reported-by: Date Huang Reported-by: Vincent Stehlé Reported-by: Ivan Ivanov Tested-by: Ivan T.Ivanov --- boot/bootdev-uclass.c | 3 ++- boot/bootflow.c | 22 ++++++++++++++++++++-- test/boot/bootdev.c | 32 ++++++++++++++++++++++++++++++-- 3 files changed, 52 insertions(+), 5 deletions(-) diff --git a/boot/bootdev-uclass.c b/boot/bootdev-uclass.c index 974ddee5d2f..44ae98a9269 100644 --- a/boot/bootdev-uclass.c +++ b/boot/bootdev-uclass.c @@ -469,10 +469,11 @@ int bootdev_find_by_label(const char *label, struct udevice **devp, * if no sequence number was provided, we must scan all * bootdevs for this media uclass */ - if (IS_ENABLED(CONFIG_BOOTSTD_FULL) && seq == -1) + if (seq == -1) method_flags |= BOOTFLOW_METHF_SINGLE_UCLASS; if (method_flagsp) *method_flagsp = method_flags; + log_debug("method flags %x\n", method_flags); return 0; } log_debug("- no device in %s\n", media->name); diff --git a/boot/bootflow.c b/boot/bootflow.c index 7f5b0e94207..be543c8588c 100644 --- a/boot/bootflow.c +++ b/boot/bootflow.c @@ -280,8 +280,26 @@ static int iter_incr(struct bootflow_iter *iter) } else { log_debug("labels %p\n", iter->labels); if (iter->labels) { - ret = bootdev_next_label(iter, &dev, - &method_flags); + /* + * when the label is "mmc" we want to scan all + * mmc bootdevs, not just the first. See + * bootdev_find_by_label() where this flag is + * set up + */ + if (iter->method_flags & + BOOTFLOW_METHF_SINGLE_UCLASS) { + scan_next_in_uclass(&dev); + log_debug("looking for next device %s: %s\n", + iter->dev->name, + dev ? dev->name : ""); + } else { + dev = NULL; + } + if (!dev) { + log_debug("looking at next label\n"); + ret = bootdev_next_label(iter, &dev, + &method_flags); + } } else { ret = bootdev_next_prio(iter, &dev); method_flags = 0; diff --git a/test/boot/bootdev.c b/test/boot/bootdev.c index 63786174805..0702fccdae6 100644 --- a/test/boot/bootdev.c +++ b/test/boot/bootdev.c @@ -225,7 +225,7 @@ static int bootdev_test_order(struct unit_test_state *uts) ut_assertok(env_set("boot_targets", "mmc1 mmc2 usb")); ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow)); ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow)); - ut_asserteq(3, iter.num_devs); + ut_asserteq(5, iter.num_devs); ut_asserteq_str("mmc1.bootdev", iter.dev_used[0]->name); ut_asserteq_str("mmc2.bootdev", iter.dev_used[1]->name); ut_asserteq_str("usb_mass_storage.lun0.bootdev", @@ -237,7 +237,20 @@ static int bootdev_test_order(struct unit_test_state *uts) ut_assertok(bootflow_scan_first(NULL, "mmc", &iter, 0, &bflow)); ut_asserteq(2, iter.num_devs); - /* Now scan pass mmc1 and make sure that only mmc0 shows up */ + /* Now scan past mmc1 and make sure that only mmc0 shows up */ + ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow)); + ut_asserteq(3, iter.num_devs); + ut_asserteq_str("mmc2.bootdev", iter.dev_used[0]->name); + ut_asserteq_str("mmc1.bootdev", iter.dev_used[1]->name); + ut_asserteq_str("mmc0.bootdev", iter.dev_used[2]->name); + bootflow_iter_uninit(&iter); + + /* Try a single uclass with boot_targets */ + ut_assertok(env_set("boot_targets", "mmc")); + ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow)); + ut_asserteq(2, iter.num_devs); + + /* Now scan past mmc1 and make sure that only mmc0 shows up */ ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow)); ut_asserteq(3, iter.num_devs); ut_asserteq_str("mmc2.bootdev", iter.dev_used[0]->name); @@ -245,6 +258,21 @@ static int bootdev_test_order(struct unit_test_state *uts) ut_asserteq_str("mmc0.bootdev", iter.dev_used[2]->name); bootflow_iter_uninit(&iter); + /* Try a single uclass with boot_targets */ + ut_assertok(env_set("boot_targets", "mmc usb")); + ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow)); + ut_asserteq(2, iter.num_devs); + + /* Now scan past mmc1 and make sure that the 3 USB devices show up */ + ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow)); + ut_asserteq(6, iter.num_devs); + ut_asserteq_str("mmc2.bootdev", iter.dev_used[0]->name); + ut_asserteq_str("mmc1.bootdev", iter.dev_used[1]->name); + ut_asserteq_str("mmc0.bootdev", iter.dev_used[2]->name); + ut_asserteq_str("usb_mass_storage.lun0.bootdev", + iter.dev_used[3]->name); + bootflow_iter_uninit(&iter); + return 0; } BOOTSTD_TEST(bootdev_test_order, UT_TESTF_DM | UT_TESTF_SCAN_FDT); -- cgit v1.2.3 From a7527fbbf20619e16f4b3bf13139f6f9a881b964 Mon Sep 17 00:00:00 2001 From: Tony Dinh Date: Wed, 11 Oct 2023 13:26:42 -0700 Subject: bootstd: sata: Add bootstd support for ahci sata Add ahci sata bootdev and corresponding hunting function. Signed-off-by: Tony Dinh Reviewed-by: Simon Glass Reviewed-by: Stefan Roese --- boot/bootmeth_script.c | 16 +++++++++--- drivers/ata/Makefile | 2 +- drivers/ata/sata.c | 32 ++++++++++++++++++++++++ drivers/ata/sata_bootdev.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++ include/sata.h | 6 +++++ 5 files changed, 113 insertions(+), 5 deletions(-) create mode 100644 drivers/ata/sata_bootdev.c diff --git a/boot/bootmeth_script.c b/boot/bootmeth_script.c index 345114dabf7..06340e43d2d 100644 --- a/boot/bootmeth_script.c +++ b/boot/bootmeth_script.c @@ -188,12 +188,20 @@ static int script_boot(struct udevice *dev, struct bootflow *bflow) { struct blk_desc *desc = dev_get_uclass_plat(bflow->blk); ulong addr; - int ret; + int ret = 0; - if (desc->uclass_id == UCLASS_USB) + if (desc->uclass_id == UCLASS_USB) { ret = env_set("devtype", "usb"); - else - ret = env_set("devtype", blk_get_devtype(bflow->blk)); + } else { + /* If the uclass is AHCI, but the driver is ATA + * (not scsi), set devtype to sata + */ + if (IS_ENABLED(CONFIG_SATA) && + desc->uclass_id == UCLASS_AHCI) + ret = env_set("devtype", "sata"); + else + ret = env_set("devtype", blk_get_devtype(bflow->blk)); + } if (!ret) ret = env_set_hex("devnum", desc->devnum); if (!ret) diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile index 6e30180b8b4..0b6f91098a3 100644 --- a/drivers/ata/Makefile +++ b/drivers/ata/Makefile @@ -10,7 +10,7 @@ obj-$(CONFIG_SCSI_AHCI) += ahci.o obj-$(CONFIG_DWC_AHSATA) += dwc_ahsata.o obj-$(CONFIG_FSL_SATA) += fsl_sata.o obj-$(CONFIG_LIBATA) += libata.o -obj-$(CONFIG_SATA) += sata.o +obj-$(CONFIG_SATA) += sata.o sata_bootdev.o obj-$(CONFIG_SATA_CEVA) += sata_ceva.o obj-$(CONFIG_SATA_MV) += sata_mv.o obj-$(CONFIG_SATA_SIL) += sata_sil.o diff --git a/drivers/ata/sata.c b/drivers/ata/sata.c index ce3e9b5a400..f126b84e050 100644 --- a/drivers/ata/sata.c +++ b/drivers/ata/sata.c @@ -15,6 +15,8 @@ #include #include #include +#include +#include #ifndef CONFIG_AHCI struct blk_desc sata_dev_desc[CONFIG_SYS_SATA_MAX_DEVICE]; @@ -50,6 +52,36 @@ int sata_scan(struct udevice *dev) return ops->scan(dev); } +int sata_rescan(bool verbose) +{ + int ret; + struct udevice *dev; + + if (verbose) + printf("Removing devices on SATA bus...\n"); + + blk_unbind_all(UCLASS_AHCI); + + ret = uclass_find_first_device(UCLASS_AHCI, &dev); + if (ret || !dev) { + printf("Cannot find SATA device (err=%d)\n", ret); + return -ENOSYS; + } + + ret = device_remove(dev, DM_REMOVE_NORMAL); + if (ret) { + printf("Cannot remove SATA device '%s' (err=%d)\n", dev->name, ret); + return -ENOSYS; + } + + if (verbose) + printf("Rescanning SATA bus for devices...\n"); + + ret = uclass_probe_all(UCLASS_AHCI); + + return ret; +} + #ifndef CONFIG_AHCI #ifdef CONFIG_PARTITIONS struct blk_desc *sata_get_dev(int dev) diff --git a/drivers/ata/sata_bootdev.c b/drivers/ata/sata_bootdev.c new file mode 100644 index 00000000000..f638493ce04 --- /dev/null +++ b/drivers/ata/sata_bootdev.c @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Bootdev for sata + * + * Copyright 2023 Tony Dinh + */ + +#include +#include +#include +#include +#include +#include + +static int sata_bootdev_bind(struct udevice *dev) +{ + struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev); + + ucp->prio = BOOTDEVP_4_SCAN_FAST; + + return 0; +} + +static int sata_bootdev_hunt(struct bootdev_hunter *info, bool show) +{ + int ret; + + if (IS_ENABLED(CONFIG_PCI)) { + ret = pci_init(); + if (ret) + return ret; + } + + ret = sata_rescan(true); + if (ret) + return ret; + + return 0; +} + +struct bootdev_ops sata_bootdev_ops = { +}; + +static const struct udevice_id sata_bootdev_ids[] = { + { .compatible = "u-boot,bootdev-sata" }, + { } +}; + +U_BOOT_DRIVER(sata_bootdev) = { + .name = "sata_bootdev", + .id = UCLASS_BOOTDEV, + .ops = &sata_bootdev_ops, + .bind = sata_bootdev_bind, + .of_match = sata_bootdev_ids, +}; + +BOOTDEV_HUNTER(sata_bootdev_hunter) = { + .prio = BOOTDEVP_4_SCAN_FAST, + .uclass = UCLASS_AHCI, + .hunt = sata_bootdev_hunt, + .drv = DM_DRIVER_REF(sata_bootdev), +}; diff --git a/include/sata.h b/include/sata.h index d89f7a8a298..6111cf65d9d 100644 --- a/include/sata.h +++ b/include/sata.h @@ -21,4 +21,10 @@ extern struct blk_desc sata_dev_desc[]; int sata_probe(int devnum); int sata_remove(int devnum); +/* + * Remove existing AHCI SATA device uclass and all of its children, + * if any, and probe it again. + */ +int sata_rescan(bool verbose); + #endif -- cgit v1.2.3 From 1052920aa987061f4d2aaa768dfe0ba15b6f10f7 Mon Sep 17 00:00:00 2001 From: Tony Dinh Date: Fri, 6 Oct 2023 20:34:28 -0700 Subject: bootstd: sata: bootdev scanning for ahci sata with no drive attached It's normal to have no SATA drive attached to the controller, so return a successful status when there is no block device found after probing. Note: this patch depends on the previous patch https://patchwork.ozlabs.org/project/uboot/patch/20230917230649.30357-1-mibodhi@gmail.com/ Resend the right patch. Signed-off-by: Tony Dinh Reviewed-by: Simon Glass Reviewed-by: Stefan Roese --- drivers/ata/sata.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/ata/sata.c b/drivers/ata/sata.c index f126b84e050..dcb5fcf476b 100644 --- a/drivers/ata/sata.c +++ b/drivers/ata/sata.c @@ -79,6 +79,12 @@ int sata_rescan(bool verbose) ret = uclass_probe_all(UCLASS_AHCI); + if (ret == -ENODEV) { + if (verbose) + printf("No SATA block device found\n"); + return 0; + } + return ret; } -- cgit v1.2.3