From patchwork Tue Mar 24 22:18:57 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 2050 Return-Path: X-Original-To: u-boot-concept@u-boot.org Delivered-To: u-boot-concept@u-boot.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1774390784; bh=8mjqbk2GYrsZoz4Qun/aQHKZfCD5MteNzH2B/Bjkt7g=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=Om4y0PZuLYbti5N9CahGwvVLo7WOXNRBEcoXnQ4+f45QDnLWnUPaYcmH23+5wS4a4 6uqJDfY4aQa7X7DECvKDFVDj7hjfVBwHYk3b8QR66cXPsCxSymnp7apoQSR+1E9+Kw m0EcKje4VqFjmgukrD3/rCHJwpS7KFWAc+25l1s7/6o/ffn21mL3XxIOH4hcAZL0yP n6qLn+2pHAKWFVrlhALb95NJIneFlevDr7EXddYEszSKeNg5qaNpDixTwm8RbCS05l K1uyImcm5z3VnRcojjcq4vuOXjAHWq/lfqKTslGKj/SbqxRlFfk1zQPm5HMGS3or+z BVPHsFh1WqHhQ== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id AB9D26A24D for ; Tue, 24 Mar 2026 16:19:44 -0600 (MDT) X-Virus-Scanned: Debian amavis at Received: from mail.u-boot.org ([127.0.0.1]) by localhost (mail.u-boot.org [127.0.0.1]) (amavis, port 10024) with ESMTP id jrxf6EudSavp for ; Tue, 24 Mar 2026 16:19:44 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1774390783; bh=8mjqbk2GYrsZoz4Qun/aQHKZfCD5MteNzH2B/Bjkt7g=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=Ghv7K5LT9UQZtYf7rJYPuts0jDDfrL+bcOx1DK93B+lV2MEiQWwBVPbxZRc7xFKdQ /2aqcqv9rxFGoONMRo7WGN98Jg00OtSOA60/Z5ilFMY94/ratsZKlrYZ2jBQgx6Upi ivaEWu+m+DHH6cizpTD4wHUR5v9JQPsoUjGoeeQZ6CKTndk/PRDVuhBfx2p36PGWDr dYL6aLlTgaoxzM8Ontz4Ya+ewY4It+h6PNULZdnwf2IVo5e/VVw8O59qidkJ3yxHO/ 9gkg/QPZej1hSWboMwdjJ8mPfPsUbs+Cy5p9AF8gIwUaauN+nbL13lgY5C/ILLUSOA fArIXJ3qLXFVw== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id F0F916A1FD for ; Tue, 24 Mar 2026 16:19:43 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1774390781; bh=HeGNTKdCHB1DXOsbsAAhfIogH0qznl4TM5sVD2Zp1zg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=l7d88qTUnEeDti3GkmT+s/zNZUn2I9e7EeGmfKX4F2+kI2nAajE21uSlZQkLXNAE+ WEhXD4ERxXrVbkSnP3HKtNVs7CZQJKXQ3c1on6ziZ+8ltD1Up6OYCcIYk1Zc3fpXIM Z60ZGsjE13m/B3EV2T7lVWLe2NjiTQk/G+nPpedd/hegxYNJjLuuvENSbbZ0UVWKC7 ugMrtPxjmyRHc3DiFT2abO4mLxlmFiMt2Se07lc1aX4T/KFLvgqXY9GdhkziiiIPx/ J3LgGBFk4Eot98fJXh7Dl3bxGeF2L+NPICk1oAulj2s3s4I/npbnFyISu5BTf6lNpl HnAgJpIaQvpmg== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 736346A249; Tue, 24 Mar 2026 16:19:41 -0600 (MDT) X-Virus-Scanned: Debian amavis at Received: from mail.u-boot.org ([127.0.0.1]) by localhost (mail.u-boot.org [127.0.0.1]) (amavis, port 10026) with ESMTP id FpQwLQN31T8W; Tue, 24 Mar 2026 16:19:41 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1774390777; bh=Gg4FueBkXs3wTLsAEsyTn+OCd7NwWFJgOPUgy4KIW7M=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=O0CscG1KA4oWOpDdpsGNy1PCTM8UzQ5xg/bS56jSkHkt3P3IdwuSdx8/F8untoXFE 9HwGQtCXYa+eAfqgButSCLuNsNtHHTXqRzN1VRcn4n3AnwTnhSgZRHBUux6XTIb0Ie z37cExRSigygsnMtVLuNS8kspU4n1IkNHnyaMzUyshaMXjo9gqCmkne/XxMVribtOg 33tijMBHToGeJJV8zEmpINHDeWGWYWWwY1gDoKOXOC/fsBJ1Zz1KSlj2tfgGdJ5n7W XoYCKEd0bY09xm+ggteRPJ86HSU6D9dXYWfwRSvs12WWrv+rWLPOvtDbSF674AnIwK 9Ewq6ftX1WXEQ== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id 6D2E46A1DD; Tue, 24 Mar 2026 16:19:37 -0600 (MDT) From: Simon Glass To: U-Boot Concept Date: Tue, 24 Mar 2026 16:18:57 -0600 Message-ID: <20260324221911.3678307-4-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260324221911.3678307-1-sjg@u-boot.org> References: <20260324221911.3678307-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: YP774K65OR5MP77RS7RLH6ZDYCFXJZRH X-Message-ID-Hash: YP774K65OR5MP77RS7RLH6ZDYCFXJZRH X-MailFrom: sjg@u-boot.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: Simon Glass X-Mailman-Version: 3.3.10 Precedence: list Subject: [Concept] [PATCH 03/12] extlinux: Enable multi-entry bootflow scanning List-Id: Discussion and patches related to U-Boot Concept Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: Simon Glass Use the BOOTMETHF_MULTI flag to produce one bootflow per label in an extlinux configuration file. Adjust extlinux_fill_info() to walk to the Nth label based on bflow->entry, returning -ENOENT when the index exceeds the available labels. This allows bootflow scanning to discover all kernels defined in an extlinux config, rather than only exposing the first label. Signed-off-by: Simon Glass --- boot/bootmeth_extlinux.c | 29 ++++++++++++++++++++--------- test/boot/bootdev.c | 13 ++++++++++++- test/boot/bootflow.c | 33 ++++++++++++++++++++++++++------- 3 files changed, 58 insertions(+), 17 deletions(-) diff --git a/boot/bootmeth_extlinux.c b/boot/bootmeth_extlinux.c index 3ffe21d96a3..bfc816f3628 100644 --- a/boot/bootmeth_extlinux.c +++ b/boot/bootmeth_extlinux.c @@ -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; } diff --git a/test/boot/bootdev.c b/test/boot/bootdev.c index 81610563141..06ef695256e 100644 --- a/test/boot/bootdev.c +++ b/test/boot/bootdev.c @@ -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", diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c index 3bea1cc6634..2e0cf5d309e 100644 --- a/test/boot/bootflow.c +++ b/test/boot/bootflow.c @@ -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 */