@@ -117,11 +117,12 @@ static int extlinux_check_luks(struct bootflow *bflow)
/**
* extlinux_fill_info() - Decode the extlinux file to find out its info
*
- * Uses pxe_parse() to parse the configuration file and extract the first
- * label's name to use as the bootflow OS name.
+ * Uses pxe_parse() to parse the configuration file and extract the label
+ * selected by @bflow->entry to use as the bootflow OS name.
*
- * @bflow: Bootflow to process
- * Return: 0 if OK, -ve on error
+ * @bflow: Bootflow to process (entry selects which label)
+ * Return: 0 if OK, -ENOENT if entry index exceeds available labels, other
+ * -ve on error
*/
static int extlinux_fill_info(struct bootflow *bflow)
{
@@ -129,19 +130,28 @@ static int extlinux_fill_info(struct bootflow *bflow)
struct pxe_label *label;
const char *name;
ulong addr;
+ int i;
- log_debug("parsing bflow file size %x\n", bflow->size);
+ log_debug("parsing bflow file size %x entry %d\n", bflow->size,
+ bflow->entry);
addr = map_to_sysmem(bflow->buf);
ctx = pxe_parse(addr, bflow->size, bflow->fname);
if (!ctx)
return log_msg_ret("prs", -EINVAL);
- if (list_empty(&ctx->cfg->labels)) {
- pxe_cleanup(ctx);
- return log_msg_ret("lab", -ENOENT);
+ /* Walk to the requested label */
+ i = 0;
+ list_for_each_entry(label, &ctx->cfg->labels, list) {
+ if (i == bflow->entry)
+ goto found;
+ i++;
}
- label = list_first_entry(&ctx->cfg->labels, struct pxe_label, list);
+ /* No more entries at this index */
+ pxe_cleanup(ctx);
+ return -ENOENT;
+
+found:
name = label->menu ? label->menu : label->name;
if (name) {
bflow->os_name = strdup(name);
@@ -267,6 +277,7 @@ static int extlinux_bootmeth_bind(struct udevice *dev)
plat->desc = IS_ENABLED(CONFIG_BOOTSTD_FULL) ?
"Extlinux boot from a block device" : "extlinux";
+ plat->flags = BOOTMETHF_MULTI;
return 0;
}
@@ -228,6 +228,9 @@ static int bootdev_test_order(struct unit_test_state *uts)
/* get the second usb device which has a backing file (flash3.img) */
ut_asserteq(0, bootflow_scan_next(&iter, &bflow));
+ /* get the second entry from flash3 (Ubuntu has two extlinux labels) */
+ ut_asserteq(0, bootflow_scan_next(&iter, &bflow));
+
ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow));
ut_asserteq(6, iter.num_devs);
ut_asserteq_str("mmc1.bootdev", iter.dev_used[0]->name);
@@ -269,10 +272,12 @@ static int bootdev_test_order(struct unit_test_state *uts)
/*
* Now scan past mmc1 and make sure that the 4 USB devices show up. The
- * first two have a backing file so returns success
+ * first two have a backing file so returns success. flash3 has two
+ * extlinux labels so produces an extra bootflow.
*/
ut_asserteq(0, bootflow_scan_next(&iter, &bflow));
ut_asserteq(0, bootflow_scan_next(&iter, &bflow));
+ ut_asserteq(0, bootflow_scan_next(&iter, &bflow));
ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow));
ut_asserteq(7, iter.num_devs);
ut_asserteq_str("mmc2.bootdev", iter.dev_used[0]->name);
@@ -341,6 +346,9 @@ static int bootdev_test_prio(struct unit_test_state *uts)
/* get the second usb device which has a backing file (flash3.img) */
ut_asserteq(0, bootflow_scan_next(&iter, &bflow));
+ /* get the second entry from flash3 (Ubuntu has two extlinux labels) */
+ ut_asserteq(0, bootflow_scan_next(&iter, &bflow));
+
ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow));
ut_asserteq(7, iter.num_devs);
ut_asserteq_str("mmc2.bootdev", iter.dev_used[0]->name);
@@ -365,6 +373,9 @@ static int bootdev_test_prio(struct unit_test_state *uts)
/* get the second usb device which has a backing file (flash3.img) */
ut_asserteq(0, bootflow_scan_next(&iter, &bflow));
+ /* get the second entry from flash3 (Ubuntu has two extlinux labels) */
+ ut_asserteq(0, bootflow_scan_next(&iter, &bflow));
+
ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow));
ut_asserteq(9, iter.num_devs);
ut_asserteq_str("hub1.p1.usb_mass_storage.lun0.bootdev",
@@ -211,17 +211,20 @@ static int bootflow_cmd_scan_e(struct unit_test_state *uts)
ut_assert_nextline(" 5 vbe media mmc 0 mmc1.bootdev.whole ");
ut_assert_nextline(" ** No partition found, err=-2: No such file or directory");
ut_assert_nextline(" 6 extlinux ready mmc 1 mmc1.bootdev.part_1 /extlinux/extlinux.conf");
+ /* multi-entry tries entry 1 on extlinux (Fedora has one label) */
+ ut_assert_nextline(" 7 extlinux ready mmc 1 mmc1.bootdev.part_1 /extlinux/extlinux.conf");
+ ut_assert_nextline(" ** Ready, err=-2: No such file or directory");
ut_assert_nextline(
- " 7 efi fs mmc 1 mmc1.bootdev.part_1 /EFI/BOOT/%s",
+ " 8 efi fs mmc 1 mmc1.bootdev.part_1 /EFI/BOOT/%s",
efi_get_basename());
ut_assert_skip_to_line("Scanning bootdev 'mmc0.bootdev':");
ut_assert_skip_to_line(
- " 5f vbe media mmc 0 mmc0.bootdev.whole ");
+ " 60 vbe media mmc 0 mmc0.bootdev.whole ");
ut_assert_nextline(" ** No partition found, err=-93: Protocol not supported");
ut_assert_nextline("No more bootdevs");
ut_assert_nextlinen("---");
- ut_assert_nextline("(96 bootflows, 1 valid)");
+ ut_assert_nextline("(97 bootflows, 1 valid)");
ut_assert_console_end();
ut_assertok(run_command("bootflow list", 0));
@@ -230,9 +233,9 @@ static int bootflow_cmd_scan_e(struct unit_test_state *uts)
ut_assert_nextlinen("---");
ut_assert_nextline(" 0 extlinux media mmc 0 mmc2.bootdev.whole ");
ut_assert_nextline(" 1 efi media mmc 0 mmc2.bootdev.whole ");
- ut_assert_skip_to_line(" 5f vbe media mmc 0 mmc0.bootdev.whole ");
+ ut_assert_skip_to_line(" 60 vbe media mmc 0 mmc0.bootdev.whole ");
ut_assert_nextlinen("---");
- ut_assert_nextline("(96 bootflows, 1 valid)");
+ ut_assert_nextline("(97 bootflows, 2 valid)");
ut_assert_console_end();
return 0;
@@ -406,6 +409,17 @@ static int bootflow_iter(struct unit_test_state *uts)
ut_asserteq(BOOTFLOWST_READY, bflow.state);
bootflow_free(&bflow);
+ /*
+ * With BOOTMETHF_MULTI, the iterator tries entry 1 on extlinux.
+ * Fedora has only one label, so entry 1 fails. Since BOOTFLOWIF_ALL
+ * is set, this failed attempt is returned.
+ */
+ ut_asserteq(-ENOENT, bootflow_scan_next(&iter, &bflow));
+ ut_asserteq(0, iter.cur_method);
+ ut_asserteq(1, iter.entry);
+ ut_asserteq(1, iter.part);
+ bootflow_free(&bflow);
+
ut_asserteq(-ENOENT, bootflow_scan_next(&iter, &bflow));
ut_asserteq(3, iter.num_methods);
ut_asserteq(1, iter.cur_method);
@@ -1435,8 +1449,10 @@ static int bootflow_efi(struct unit_test_state *uts)
" 1 efi ready usb 1 hub1.p2.usb_mass_storage. /EFI/BOOT/BOOTSBOX.EFI");
ut_assert_nextlinen(
" 2 extlinux ready usb 1 hub1.p4.usb_mass_storage. /extlinux/extlinux.conf");
+ ut_assert_nextlinen(
+ " 3 extlinux ready usb 1 hub1.p4.usb_mass_storage. /extlinux/extlinux.conf");
ut_assert_nextlinen("---");
- ut_assert_skip_to_line("(3 bootflows, 3 valid)");
+ ut_assert_skip_to_line("(4 bootflows, 4 valid)");
ut_assert_console_end();
ut_assertok(run_command("bootflow select 1", 0));
@@ -1812,8 +1828,11 @@ static int bootflow_cmd_info_encrypted(struct unit_test_state *uts)
ut_assert_nextline(
" 1 extlinux ready mmc 1 %c mmc12.bootdev.part_1 /extlinux/extlinux.conf",
IS_ENABLED(CONFIG_BLK_LUKS) ? 'E' : ' ');
+ ut_assert_nextline(
+ " 2 extlinux ready mmc 1 %c mmc12.bootdev.part_1 /extlinux/extlinux.conf",
+ IS_ENABLED(CONFIG_BLK_LUKS) ? 'E' : ' ');
ut_assert_nextline("--- ----------- ------ -------- ---- - ------------------------ ----------------");
- ut_assert_nextline("(2 bootflows, 2 valid)");
+ ut_assert_nextline("(3 bootflows, 3 valid)");
ut_assert_console_end();
/* Select the mmc12 bootflow and check info shows encryption */