bootstd: Support running bootdev hunters

Add a way to run a bootdev hunter to find bootdevs of a certain type. Add
this to the 'bootdev hunt' command. Test for this are added in a later
patch, since a useful test needs some hunters to work with.

Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
Simon Glass 2023-01-17 10:47:34 -07:00 committed by Tom Rini
parent bd90b09288
commit c7b63d500d
4 changed files with 84 additions and 1 deletions

View File

@ -636,6 +636,67 @@ int bootdev_setup_iter_order(struct bootflow_iter *iter, struct udevice **devp)
return 0;
}
static int bootdev_hunt_drv(struct bootdev_hunter *info, uint seq, bool show)
{
const char *name = uclass_get_name(info->uclass);
struct bootstd_priv *std;
int ret;
ret = bootstd_get_priv(&std);
if (ret)
return log_msg_ret("std", ret);
if (!(std->hunters_used & BIT(seq))) {
if (show)
printf("Hunting with: %s\n",
uclass_get_name(info->uclass));
log_debug("Hunting with: %s\n", name);
if (info->hunt) {
ret = info->hunt(info, show);
if (ret)
return ret;
}
std->hunters_used |= BIT(seq);
}
return 0;
}
int bootdev_hunt(const char *spec, bool show)
{
struct bootdev_hunter *start;
const char *end;
int n_ent, i;
int result;
size_t len;
start = ll_entry_start(struct bootdev_hunter, bootdev_hunter);
n_ent = ll_entry_count(struct bootdev_hunter, bootdev_hunter);
result = 0;
len = SIZE_MAX;
if (spec) {
trailing_strtoln_end(spec, NULL, &end);
len = end - spec;
}
for (i = 0; i < n_ent; i++) {
struct bootdev_hunter *info = start + i;
const char *name = uclass_get_name(info->uclass);
int ret;
log_debug("looking at %.*s for %s\n",
(int)max(strlen(name), len), spec, name);
if (spec && strncmp(spec, name, max(strlen(name), len)))
continue;
ret = bootdev_hunt_drv(info, i, show);
if (ret)
result = ret;
}
return result;
}
void bootdev_list_hunters(struct bootstd_priv *std)
{
struct bootdev_hunter *orig, *start;

View File

@ -128,7 +128,12 @@ static int do_bootdev_hunt(struct cmd_tbl *cmdtp, int flag, int argc,
if (list) {
bootdev_list_hunters(priv);
} else {
/* TODO: implement hunting */
ret = bootdev_hunt(spec, true);
if (ret) {
printf("Failed (err=%dE)\n", ret);
return CMD_RET_FAILURE;
}
}
return 0;

View File

@ -263,6 +263,20 @@ int bootdev_setup_iter_order(struct bootflow_iter *iter, struct udevice **devp);
*/
void bootdev_list_hunters(struct bootstd_priv *std);
/**
* bootdev_hunt() - Hunt for bootdevs matching a particular spec
*
* This runs the selected hunter (or all if @spec is NULL) to try to find new
* bootdevs.
*
* @spec: Spec to match, e.g. "mmc0", or NULL for any. If provided, this must
* match a uclass name so that the hunter can be determined. Any trailing number
* is ignored
* @show: true to show each hunter before using it
* Returns: 0 if OK, -ve on error
*/
int bootdev_hunt(const char *spec, bool show);
#if CONFIG_IS_ENABLED(BOOTSTD)
/**
* bootdev_setup_for_dev() - Bind a new bootdev device (deprecated)

View File

@ -237,6 +237,9 @@ static int bootdev_test_hunter(struct unit_test_state *uts)
ut_assert_nextline("(total hunters: 0)");
ut_assert_console_end();
ut_assertok(bootdev_hunt("mmc1", false));
ut_assert_console_end();
return 0;
}
BOOTSTD_TEST(bootdev_test_hunter, UT_TESTF_DM | UT_TESTF_SCAN_FDT);