if (!ret) {
log_debug("- found %s\n", bdev->name);
*devp = bdev;
+
+ /*
+ * if no sequence number was provided, we must scan all
+ * bootdevs for this media uclass
+ */
+ if (IS_ENABLED(CONFIG_BOOTSTD_FULL) && seq == -1)
+ method_flags |= BOOTFLOW_METHF_SINGLE_UCLASS;
if (method_flagsp)
*method_flagsp = method_flags;
return 0;
{
struct udevice *dev;
int method_flags = 0;
- int ret, seq;
+ int ret = -ENODEV, seq;
char *endp;
seq = simple_strtol(name, &endp, 16);
ret);
return log_msg_ret("pro", ret);
}
- } else {
+ } else if (IS_ENABLED(CONFIG_BOOTSTD_FULL)) {
ret = uclass_get_device_by_seq(UCLASS_BOOTDEV, seq, &dev);
+ method_flags |= BOOTFLOW_METHF_SINGLE_DEV;
}
if (ret) {
printf("Cannot find '%s' (err=%d)\n", name, ret);
return 0;
}
+int bootdev_hunt_and_find_by_label(const char *label, struct udevice **devp,
+ int *method_flagsp)
+{
+ int ret;
+
+ ret = bootdev_hunt(label, false);
+ if (ret)
+ return log_msg_ret("scn", ret);
+ ret = bootdev_find_by_label(label, devp, method_flagsp);
+ if (ret)
+ return log_msg_ret("fnd", ret);
+
+ return 0;
+}
+
static int default_get_bootflow(struct udevice *dev, struct bootflow_iter *iter,
struct bootflow *bflow)
{
* Internal flags:
* @BOOTFLOWF_SINGLE_DEV: (internal) Just scan one bootdev
* @BOOTFLOWF_SKIP_GLOBAL: (internal) Don't scan global bootmeths
- * this uclass
+ * @BOOTFLOWF_SINGLE_UCLASS: (internal) Keep scanning through all devices in
+ * this uclass (used with things like "mmc")
+ * @BOOTFLOWF_SINGLE_MEDIA: (internal) Scan one media device in the uclass (used
+ * with things like "mmc1")
*/
enum bootflow_flags_t {
BOOTFLOWF_FIXED = 1 << 0,
*/
BOOTFLOWF_SINGLE_DEV = 1 << 16,
BOOTFLOWF_SKIP_GLOBAL = 1 << 17,
+ BOOTFLOWF_SINGLE_UCLASS = 1 << 18,
+ BOOTFLOWF_SINGLE_MEDIA = 1 << 19,
};
/**
*
* @BOOTFLOW_METHF_DHCP_ONLY: Only use dhcp (scripts and EFI)
* @BOOTFLOW_METHF_PXE_ONLY: Only use pxe (PXE boot)
+ * @BOOTFLOW_METHF_SINGLE_DEV: Scan only a single bootdev (used for labels like
+ * "3"). This is used if a sequence number is provided instead of a label
+ * @BOOTFLOW_METHF_SINGLE_UCLASS: Scan all bootdevs in this one uclass (used
+ * with things like "mmc"). If this is not set, then the bootdev has an integer
+ * value in the label (like "mmc2")
*/
enum bootflow_meth_flags_t {
BOOTFLOW_METHF_DHCP_ONLY = 1 << 0,
BOOTFLOW_METHF_PXE_ONLY = 1 << 1,
+ BOOTFLOW_METHF_SINGLE_DEV = 1 << 2,
+ BOOTFLOW_METHF_SINGLE_UCLASS = 1 << 3,
};
/**
/* Check method flags */
ut_assertok(bootdev_find_by_label("pxe", &dev, &mflags));
- ut_asserteq(BOOTFLOW_METHF_PXE_ONLY, mflags);
+ ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS | BOOTFLOW_METHF_PXE_ONLY,
+ mflags);
ut_assertok(bootdev_find_by_label("dhcp", &dev, &mflags));
- ut_asserteq(BOOTFLOW_METHF_DHCP_ONLY, mflags);
+ ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS | BOOTFLOW_METHF_DHCP_ONLY,
+ mflags);
/* Check invalid uclass */
ut_asserteq(-EINVAL, bootdev_find_by_label("fred0", &dev, &mflags));
BOOTSTD_TEST(bootdev_test_labels, UT_TESTF_DM | UT_TESTF_SCAN_FDT |
UT_TESTF_ETH_BOOTDEV);
+/* Check bootdev_find_by_any() */
+static int bootdev_test_any(struct unit_test_state *uts)
+{
+ struct udevice *dev, *media;
+ int mflags;
+
+ /*
+ * with ethernet enabled we have 8 devices ahead of the mmc ones:
+ *
+ * ut_assertok(run_command("bootdev list", 0));
+ * Seq Probed Status Uclass Name
+ * --- ------ ------ -------- ------------------
+ * 0 [ + ] OK ethernet eth@10002000.bootdev
+ * 1 [ ] OK ethernet eth@10003000.bootdev
+ * 2 [ ] OK ethernet sbe5.bootdev
+ * 3 [ ] OK ethernet eth@10004000.bootdev
+ * 4 [ ] OK ethernet phy-test-eth.bootdev
+ * 5 [ ] OK ethernet dsa-test-eth.bootdev
+ * 6 [ ] OK ethernet dsa-test@0.bootdev
+ * 7 [ ] OK ethernet dsa-test@1.bootdev
+ * 8 [ ] OK mmc mmc2.bootdev
+ * 9 [ + ] OK mmc mmc1.bootdev
+ * a [ ] OK mmc mmc0.bootdev
+ */
+ console_record_reset_enable();
+ ut_assertok(bootdev_find_by_any("8", &dev, &mflags));
+ ut_asserteq(UCLASS_BOOTDEV, device_get_uclass_id(dev));
+ ut_asserteq(BOOTFLOW_METHF_SINGLE_DEV, mflags);
+ media = dev_get_parent(dev);
+ ut_asserteq(UCLASS_MMC, device_get_uclass_id(media));
+ ut_asserteq_str("mmc2", media->name);
+ ut_assert_console_end();
+
+ /* there should not be this many bootdevs */
+ ut_asserteq(-ENODEV, bootdev_find_by_any("50", &dev, &mflags));
+ ut_assert_nextline("Cannot find '50' (err=-19)");
+ ut_assert_console_end();
+
+ /* Check method flags */
+ ut_assertok(bootdev_find_by_any("pxe", &dev, &mflags));
+ ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS | BOOTFLOW_METHF_PXE_ONLY,
+ mflags);
+
+ /* Check invalid uclass */
+ mflags = 123;
+ ut_asserteq(-EINVAL, bootdev_find_by_any("fred0", &dev, &mflags));
+ ut_assert_nextline("Unknown uclass 'fred0' in label");
+ ut_assert_nextline("Cannot find bootdev 'fred0' (err=-22)");
+ ut_asserteq(123, mflags);
+ ut_assert_console_end();
+
+ return 0;
+}
+BOOTSTD_TEST(bootdev_test_any, 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)
{
return 0;
}
BOOTSTD_TEST(bootdev_test_hunt_prio, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check hunting for bootdevs with a particular label */
+static int bootdev_test_hunt_label(struct unit_test_state *uts)
+{
+ struct udevice *dev, *old;
+ struct bootstd_priv *std;
+ int mflags;
+
+ /* get access to the used hunters */
+ ut_assertok(bootstd_get_priv(&std));
+
+ /* scan an unknown uclass */
+ console_record_reset_enable();
+ old = (void *)&mflags; /* arbitrary pointer to check against dev */
+ dev = old;
+ mflags = 123;
+ ut_asserteq(-EINVAL,
+ bootdev_hunt_and_find_by_label("fred", &dev, &mflags));
+ ut_assert_nextline("Unknown uclass 'fred' in label");
+ ut_asserteq_ptr(old, dev);
+ ut_asserteq(123, mflags);
+ ut_assert_console_end();
+ ut_asserteq(0, std->hunters_used);
+
+ /* scan an invalid mmc controllers */
+ ut_asserteq(-ENOENT,
+ bootdev_hunt_and_find_by_label("mmc4", &dev, &mflags));
+ ut_asserteq_ptr(old, dev);
+ ut_asserteq(123, mflags);
+ ut_assert_nextline("Unknown seq 4 for label 'mmc4'");
+ ut_assert_console_end();
+
+ ut_assertok(bootstd_test_check_mmc_hunter(uts));
+
+ /* scan for a particular mmc controller */
+ ut_assertok(bootdev_hunt_and_find_by_label("mmc1", &dev, &mflags));
+ ut_assertnonnull(dev);
+ ut_asserteq_str("mmc1.bootdev", dev->name);
+ ut_asserteq(0, mflags);
+ ut_assert_console_end();
+
+ /* scan all of usb */
+ test_set_skip_delays(true);
+ ut_assertok(bootdev_hunt_and_find_by_label("usb", &dev, &mflags));
+ ut_assertnonnull(dev);
+ ut_asserteq_str("usb_mass_storage.lun0.bootdev", dev->name);
+ ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS, mflags);
+ ut_assert_nextlinen("Bus usb@1: scanning bus usb@1");
+ ut_assert_console_end();
+
+ return 0;
+}
+BOOTSTD_TEST(bootdev_test_hunt_label, UT_TESTF_DM | UT_TESTF_SCAN_FDT);