mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-10 15:14:43 +00:00
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 <sjg@chromium.org>
This commit is contained in:
parent
47aedc29dc
commit
91943ff703
7 changed files with 166 additions and 76 deletions
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
Loading…
Reference in a new issue