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;
}
/* 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;
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) {
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);
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);
{
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);
{
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;
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)) {
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");
/*
* 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)
/**
* 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
* 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
*
* @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
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 */
}
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)
{
}
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)
}
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
*