Skip to content

Commit e4b6948

Browse files
sjg20trini
authored andcommitted
bootstd: Allow iterating to the next label in a list
Add a function which moves to the next label in a list of labels. This allows processing the boot_targets environment variable. This works using a new label list in the bootflow iterator. The logic to set this up is included in a subsequent commit. Signed-off-by: Simon Glass <sjg@chromium.org>
1 parent 66e3dce commit e4b6948

File tree

4 files changed

+123
-3
lines changed

4 files changed

+123
-3
lines changed

boot/bootdev-uclass.c

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,25 @@ void bootdev_clear_bootflows(struct udevice *dev)
566566
}
567567
}
568568

569+
int bootdev_next_label(struct bootflow_iter *iter, struct udevice **devp,
570+
int *method_flagsp)
571+
{
572+
struct udevice *dev;
573+
574+
log_debug("next\n");
575+
for (dev = NULL; !dev && iter->labels[++iter->cur_label];) {
576+
log_debug("Scanning: %s\n", iter->labels[iter->cur_label]);
577+
bootdev_hunt_and_find_by_label(iter->labels[iter->cur_label],
578+
&dev, method_flagsp);
579+
}
580+
581+
if (!dev)
582+
return log_msg_ret("fin", -ENODEV);
583+
*devp = dev;
584+
585+
return 0;
586+
}
587+
569588
/**
570589
* h_cmp_bootdev() - Compare two bootdevs to find out which should go first
571590
*
@@ -763,8 +782,11 @@ int bootdev_hunt(const char *spec, bool show)
763782

764783
log_debug("looking at %.*s for %s\n",
765784
(int)max(strlen(name), len), spec, name);
766-
if (spec && strncmp(spec, name, max(strlen(name), len)))
767-
continue;
785+
if (spec && strncmp(spec, name, max(strlen(name), len))) {
786+
if (info->uclass != UCLASS_ETH ||
787+
(strcmp("dhcp", spec) && strcmp("pxe", spec)))
788+
continue;
789+
}
768790
ret = bootdev_hunt_drv(info, i, show);
769791
if (ret)
770792
result = ret;

include/bootdev.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,22 @@ int bootdev_hunt_prio(enum bootdev_prio_t prio, bool show);
333333
int bootdev_hunt_and_find_by_label(const char *label, struct udevice **devp,
334334
int *method_flagsp);
335335

336+
/**
337+
* bootdev_next_label() - Move to the next bootdev in the label sequence
338+
*
339+
* Looks through the remaining labels until it finds one that matches a bootdev.
340+
* Bootdev scanners are used as needed. For example a label "mmc1" results in
341+
* running the "mmc" bootdrv.
342+
*
343+
* @iter: Interation info, containing iter->cur_label
344+
* @devp: New bootdev found, if any was found
345+
* @method_flagsp: If non-NULL, returns any flags implied by the label
346+
* (enum bootflow_meth_flags_t), 0 if none
347+
* Returns 0 if OK, -ENODEV if no bootdev was found
348+
*/
349+
int bootdev_next_label(struct bootflow_iter *iter, struct udevice **devp,
350+
int *method_flagsp);
351+
336352
#if CONFIG_IS_ENABLED(BOOTSTD)
337353
/**
338354
* bootdev_setup_for_dev() - Bind a new bootdev device (deprecated)

include/bootflow.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,8 @@ enum bootflow_meth_flags_t {
175175
* @cur_dev: Current bootdev number, an index into @dev_order[]
176176
* @dev_order: List of bootdevs to scan, in order of priority. The scan starts
177177
* with the first one on the list
178+
* @labels: List of labels to scan for bootdevs
179+
* @cur_label: Current label being processed
178180
* @num_methods: Number of bootmeth devices in @method_order
179181
* @cur_method: Current method number, an index into @method_order
180182
* @first_glob_method: First global method, if any, else -1
@@ -196,6 +198,8 @@ struct bootflow_iter {
196198
int num_devs;
197199
int cur_dev;
198200
struct udevice **dev_order;
201+
const char *const *labels;
202+
int cur_label;
199203
int num_methods;
200204
int cur_method;
201205
int first_glob_method;

test/boot/bootdev.c

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ static int bootdev_test_cmd_hunt(struct unit_test_state *uts)
355355
ut_assert_console_end();
356356

357357
/* Scan all hunters */
358-
sandbox_set_eth_enable(false);
358+
test_set_eth_enable(false);
359359
test_set_skip_delays(true);
360360
ut_assertok(run_command("bootdev hunt", 0));
361361
ut_assert_nextline("Hunting with: ethernet");
@@ -510,3 +510,81 @@ static int bootdev_test_hunt_label(struct unit_test_state *uts)
510510
return 0;
511511
}
512512
BOOTSTD_TEST(bootdev_test_hunt_label, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
513+
514+
/* Check iterating to the next label in a list */
515+
static int bootdev_test_next_label(struct unit_test_state *uts)
516+
{
517+
const char *const labels[] = {"mmc0", "scsi", "dhcp", "pxe", NULL};
518+
struct bootflow_iter iter;
519+
struct bootstd_priv *std;
520+
struct bootflow bflow;
521+
struct udevice *dev;
522+
int mflags;
523+
524+
test_set_eth_enable(false);
525+
526+
/* get access to the used hunters */
527+
ut_assertok(bootstd_get_priv(&std));
528+
529+
memset(&iter, '\0', sizeof(iter));
530+
memset(&bflow, '\0', sizeof(bflow));
531+
iter.part = 0;
532+
uclass_first_device(UCLASS_BOOTMETH, &bflow.method);
533+
iter.cur_label = -1;
534+
iter.labels = labels;
535+
536+
dev = NULL;
537+
mflags = 123;
538+
ut_assertok(bootdev_next_label(&iter, &dev, &mflags));
539+
console_record_reset_enable();
540+
ut_assert_console_end();
541+
ut_assertnonnull(dev);
542+
ut_asserteq_str("mmc0.bootdev", dev->name);
543+
ut_asserteq(0, mflags);
544+
545+
ut_assertok(bootstd_test_check_mmc_hunter(uts));
546+
547+
ut_assertok(bootdev_next_label(&iter, &dev, &mflags));
548+
ut_assert_nextline("scanning bus for devices...");
549+
ut_assert_skip_to_line(
550+
" Capacity: 1.9 MB = 0.0 GB (4095 x 512)");
551+
ut_assert_console_end();
552+
ut_assertnonnull(dev);
553+
ut_asserteq_str("scsi.id0lun0.bootdev", dev->name);
554+
ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS, mflags);
555+
556+
/* SCSI is fifth in the list, so bit 4 */
557+
ut_asserteq(BIT(2) | BIT(4), std->hunters_used);
558+
559+
ut_assertok(bootdev_next_label(&iter, &dev, &mflags));
560+
ut_assert_console_end();
561+
ut_assertnonnull(dev);
562+
ut_asserteq_str("eth@10002000.bootdev", dev->name);
563+
ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS | BOOTFLOW_METHF_DHCP_ONLY,
564+
mflags);
565+
566+
/* dhcp: Ethernet is first so bit 0 */
567+
ut_asserteq(BIT(2) | BIT(4) | BIT(0), std->hunters_used);
568+
569+
ut_assertok(bootdev_next_label(&iter, &dev, &mflags));
570+
ut_assert_console_end();
571+
ut_assertnonnull(dev);
572+
ut_asserteq_str("eth@10002000.bootdev", dev->name);
573+
ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS | BOOTFLOW_METHF_PXE_ONLY,
574+
mflags);
575+
576+
/* pxe: Ethernet is first so bit 0 */
577+
ut_asserteq(BIT(2) | BIT(4) | BIT(0), std->hunters_used);
578+
579+
mflags = 123;
580+
ut_asserteq(-ENODEV, bootdev_next_label(&iter, &dev, &mflags));
581+
ut_asserteq(123, mflags);
582+
ut_assert_console_end();
583+
584+
/* no change */
585+
ut_asserteq(BIT(2) | BIT(4) | BIT(0), std->hunters_used);
586+
587+
return 0;
588+
}
589+
BOOTSTD_TEST(bootdev_test_next_label, UT_TESTF_DM | UT_TESTF_SCAN_FDT |
590+
UT_TESTF_ETH_BOOTDEV | UT_TESTF_SF_BOOTDEV);

0 commit comments

Comments
 (0)