From patchwork Tue Mar 24 22:19:05 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 2058 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=1774390797; bh=bB71b0GWJPExJG9CJbZ9cIL5yMe74oXtPp0FzDnwWQY=; 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=p9fdL6XeLl21MiAX6fJ4o0HE/dB9h7hZnfBXHdRW5upAasTeSRI7uXBSUZSobXFho jrw451JH0fOtY7QdGxgpdgTgRTvS8PIslMCLTga0qBrDe6ZXIF9ZKwA5rSAt9JuMOR pubm715HBHzDE+BV89KXfcfaIw5dsteGK6O2UTuk81SnJgPTdUFN3ClD0s74xwVA6I mPpRvCoL0uh805SWNF8GgVI3C1nV+GD3wsHVMpHzCjGB1EVJfebuutnN7ljpqgdJs/ M02k+1E5p+zefmgfzNl/Yw9MoY2PGPFr3AraIwKkcahUui4EhBM7XsDrk04PE1uu4M EVlRBfJfZUD5A== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id AF8BD6A242 for ; Tue, 24 Mar 2026 16:19:57 -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 xVavLcO3x4Jk for ; Tue, 24 Mar 2026 16:19:57 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1774390796; bh=bB71b0GWJPExJG9CJbZ9cIL5yMe74oXtPp0FzDnwWQY=; 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=qmsUAQBvNNWgl/9K7hn+80FvNpBZMm99ga/sywwn5LPaw5Yg8Z4m5Ffyt0m58+f8H 4e3rJ5GObUHTpAqN/MpnBUc4FzfOalmXiL/FQdJ/Pux03DhrJHrmbrOwAktr7NNt9E ZPQjORdDJLmCPDK95x3RH+7ap0puBG4UI5i9rwUaHdXvdjVooBMf6ysRpxP3uJKmpd y1YnYQwlK98owJvsDQ5rkqZfytUBAyuQH9Esp6Y6jCpIn+QkOyLgvi1GtWQsqkfNCa LM9WO41h5du6qVlf0dsn2OOQ4DSgoovYpDPISLJGsmksD9eaETygX3+YEh7vZlW7UF Szf7c+nDTNgyA== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id DA34E6A238 for ; Tue, 24 Mar 2026 16:19:56 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1774390794; bh=zJM3o9d5pN3gDpGWhqoj7oX4bQOZwXY6TpHfbYK+lqc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=dZ3FG1LQ9LR32FQFJfNSNijAMC8ZRMGwHi7ndIKuOhjolkuF61OecwqFdZG8tvDNH av4+577j8K0S9PoLOCGnybCAk0ugg4b47I8+QSt8Lz/7w4YX6XN6tyKEt3DVwN+jFi vNKmh7HSH6Q8cZLJEKOA2E/pehAF02oJIKPWnIvwRhHPtoUfQ7qr1MKd2RuYE4oXfl EB+PUB6H/jlGc8c1ugjgS0WQMUdxGOhYVg4gy60dLnG3/cHbtrg8uo17znYG16fDYa bRnB7NVn0a8xTbVFpHAemUEnbRhs4AMXgKZ3E57YYW+W97K+SGZol/ICwD7AZcAooG ww6fhN/7+hhIA== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 4DDE66A253; Tue, 24 Mar 2026 16:19:54 -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 REGW9TlEgk34; Tue, 24 Mar 2026 16:19:54 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1774390789; bh=SWLXIu2l5ek+GNOIaZqK73oS4CjgT8KesUHWt2hr/RU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=i85UAwUyNHycwuHXfG8D4reGPkf6PPubjeRRdyuh1W1XQ63xWEjyFszrQq5KVuw8w Mzoxv3/FD5Ht02kGrMv/71KIq3CKp5vLZJRjM9o/2IsO3LHMTqWTG387s4/+keYGCZ Nfdjm0MdXLiSoeROMeYjCEIfsaELdSrJ6MqeD0QNMK3kzTGQJrlc9V8c+Gs5b51HE9 kE+NBiKigUHi7SeSfGw1Bbuto7u3/ca2cC767DP71CCkBcsrHwmhKqUnX9JY7MiRc3 Fw7InGJfucC7l6TcDI904VliQMLgcKdtUKZEuHZ8z5bqFBM59UYUg+cOLbDfRQma7v BrO2bbAiyELTg== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id 9B5056A1DD; Tue, 24 Mar 2026 16:19:49 -0600 (MDT) From: Simon Glass To: U-Boot Concept Date: Tue, 24 Mar 2026 16:19:05 -0600 Message-ID: <20260324221911.3678307-12-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: JEA7IXEF6JF7SQK3O2ETPG2VFKTP65MW X-Message-ID-Hash: JEA7IXEF6JF7SQK3O2ETPG2VFKTP65MW 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 11/12] extlinux: Process and cache parsed config during 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 The extlinux scanning code uses pxe_parse() which has no file-loading callback, so include directives in extlinux.conf are silently ignored. Labels defined in included files are not discovered during scanning, but are present at boot time when pxe_boot_entry() calls pxe_prepare() with the full getfile callback. This mismatch means entry indices from scanning may not match the label order at boot time. Replace pxe_parse() with parse_pxefile() + pxe_process_includes() using a properly initialised PXE context with the extlinux_getfile callback. Cache the parsed result in the alist context so that entry 0 triggers the parse and subsequent entries reuse the cache. At boot time, if the config is cached, update the callback fields for file loading and reuse the parsed menu. For bootmeths that do not cache (e.g. PXE network boot), fall back to setting up the context from scratch. This avoids double parsing and ensures the label list is consistent between scan and boot. Update the Ubuntu test image to use an include file for the rescue label, exercising the include-processing code path. The BLS test detects the filesystem ordering of .conf files at runtime since FAT directory-order is not deterministic across platforms. Update the bootctl tests for the extra multi-entry bootflows. Signed-off-by: Simon Glass --- boot/bootmeth_extlinux.c | 90 ++++++++++++++++++++++++++++--------- boot/ext_pxe_common.c | 28 +++++++++--- boot/pxe_utils.c | 30 ++++++++----- test/boot/bootctl/bootctl.c | 8 ++++ test/boot/bootflow.c | 37 +++++++++++---- test/py/img/common.py | 11 ++++- test/py/img/ubuntu.py | 9 ++-- 7 files changed, 165 insertions(+), 48 deletions(-) diff --git a/boot/bootmeth_extlinux.c b/boot/bootmeth_extlinux.c index 542daf9ab41..6f22fe19f64 100644 --- a/boot/bootmeth_extlinux.c +++ b/boot/bootmeth_extlinux.c @@ -114,30 +114,88 @@ static int extlinux_check_luks(struct bootflow *bflow) return 0; } +/** + * extlinux_parse_config() - Parse the extlinux config and cache the result + * + * Parses the configuration file including any include directives, and caches + * the result in plat->ctx.cfg. The filesystem must still be accessible for + * loading includes. + * + * @dev: Bootmeth device (needed for file-loading callback) + * @bflow: Bootflow containing the config buffer + * Return: 0 if OK, -ve on error + */ +static int extlinux_parse_config(struct udevice *dev, struct bootflow *bflow, + struct pxe_context *ctx) +{ + struct extlinux_plat *plat = dev_get_plat(dev); + struct abuf buf; + ulong addr; + int ret; + + plat->info.dev = dev; + plat->info.bflow = bflow; + ret = pxe_setup_ctx(ctx, extlinux_getfile, &plat->info, true, + bflow->fname, false, plat->use_fallback, bflow); + if (ret) + return log_msg_ret("ctx", ret); + ctx->quiet = true; + ctx->pxe_file_size = bflow->size; + + addr = map_to_sysmem(bflow->buf); + abuf_init_addr(&buf, addr, bflow->size); + ctx->cfg = parse_pxefile(ctx, &buf); + if (!ctx->cfg) { + pxe_destroy_ctx(ctx); + return log_msg_ret("prs", -EINVAL); + } + + ret = pxe_process_includes(ctx, ctx->cfg, addr); + if (ret) { + pxe_menu_uninit(ctx->cfg); + ctx->cfg = NULL; + pxe_destroy_ctx(ctx); + return log_msg_ret("inc", ret); + } + + return 0; +} + /** * extlinux_fill_info() - Decode the extlinux file to find out its info * - * Uses pxe_parse() to parse the configuration file and extract the label - * selected by @bflow->entry to use as the bootflow OS name. + * On the first call (entry 0), calls extlinux_parse_config() to parse + * into a context from the alist. For entry > 0, reuses the cached + * context. * + * @dev: Bootmeth device (needed for file-loading callback) * @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) +static int extlinux_fill_info(struct udevice *dev, struct bootflow *bflow) { + struct extlinux_priv *priv = dev_get_priv(dev); struct pxe_context *ctx; struct pxe_label *label; const char *name; - ulong addr; int i; 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); + + ctx = extlinux_get_ctx(priv, bflow); if (!ctx) - return log_msg_ret("prs", -EINVAL); + return log_msg_ret("ctx", -ENOMEM); + + /* Parse the config on first entry; reuse the cached result after */ + if (!ctx->cfg) { + int ret; + + ret = extlinux_parse_config(dev, bflow, ctx); + if (ret) + return log_msg_ret("prs", ret); + } /* Walk to the requested label */ i = 0; @@ -147,29 +205,21 @@ static int extlinux_fill_info(struct bootflow *bflow) i++; } - /* 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); - if (!bflow->os_name) { - pxe_cleanup(ctx); - return log_msg_ret("os", -ENOMEM); - } + if (!bflow->os_name) + return log_msg_ret("osn", -ENOMEM); } if (label->name) { bflow->entry_name = strdup(label->name); - if (!bflow->entry_name) { - pxe_cleanup(ctx); - return log_msg_ret("xnt", -ENOMEM); - } + if (!bflow->entry_name) + return log_msg_ret("ent", -ENOMEM); } - pxe_cleanup(ctx); - return 0; } @@ -215,7 +265,7 @@ static int extlinux_read_bootflow(struct udevice *dev, struct bootflow *bflow) if (ret) return log_msg_ret("read", ret); - ret = extlinux_fill_info(bflow); + ret = extlinux_fill_info(dev, bflow); if (ret) return log_msg_ret("inf", ret); diff --git a/boot/ext_pxe_common.c b/boot/ext_pxe_common.c index 4ea7f8f455d..04b6566ef99 100644 --- a/boot/ext_pxe_common.c +++ b/boot/ext_pxe_common.c @@ -129,18 +129,36 @@ int extlinux_boot(struct udevice *dev, struct bootflow *bflow, if (ctx->label) { ctx->fake_go = bflow->flags & BOOTFLOWF_FAKE_GO; ret = pxe_boot(ctx); + if (ret) + return log_msg_ret("pxb", -EFAULT); + return 0; + } + + /* + * If the config was cached during scanning, update the callback fields + * for file loading. Otherwise set up the context from scratch. + */ + if (ctx->cfg) { + struct extlinux_plat *plat = dev_get_plat(dev); + + plat->info.dev = dev; + plat->info.bflow = bflow; + ctx->getfile = getfile; + ctx->userdata = &plat->info; + ctx->bflow = bflow; } else { ret = extlinux_setup(dev, bflow, getfile, allow_abs_path, bootfile, ctx); if (ret) return log_msg_ret("elb", ret); - ctx->restart = restart; - addr = map_to_sysmem(bflow->buf); - - ret = pxe_boot_entry(ctx, addr, bflow->entry); } + ctx->restart = restart; + ctx->fake_go = bflow->flags & BOOTFLOWF_FAKE_GO; + addr = map_to_sysmem(bflow->buf); + + ret = pxe_boot_entry(ctx, addr, bflow->entry); if (ret) - return log_msg_ret("elb", -EFAULT); + return log_msg_ret("ent", -EFAULT); return 0; } diff --git a/boot/pxe_utils.c b/boot/pxe_utils.c index a7c5e87bef0..727806e91b0 100644 --- a/boot/pxe_utils.c +++ b/boot/pxe_utils.c @@ -1513,30 +1513,40 @@ int pxe_boot(struct pxe_context *ctx) int pxe_boot_entry(struct pxe_context *ctx, ulong addr, int entry) { + bool free_cfg = false; struct pxe_label *label; struct pxe_menu *cfg; - int ret, i = 0; - void *ptr; + int i = 0; + int ret; - ptr = map_sysmem(addr, 0); - ctx->pxe_file_size = strnlen(ptr, SZ_64K); - unmap_sysmem(ptr); + /* Use cached config if available, otherwise parse */ + cfg = ctx->cfg; + if (!cfg) { + void *ptr; - cfg = pxe_prepare(ctx, addr, false); - if (!cfg) - return log_msg_ret("prp", -EINVAL); + ptr = map_sysmem(addr, 0); + ctx->pxe_file_size = strnlen(ptr, SZ_64K); + unmap_sysmem(ptr); + + cfg = pxe_prepare(ctx, addr, false); + if (!cfg) + return log_msg_ret("prp", -EINVAL); + free_cfg = true; + } list_for_each_entry(label, &cfg->labels, list) { if (i == entry) goto found; i++; } - pxe_menu_uninit(cfg); + if (free_cfg) + pxe_menu_uninit(cfg); return log_msg_ret("lab", -ENOENT); found: ret = label_boot(ctx, label); - pxe_menu_uninit(cfg); + if (free_cfg) + pxe_menu_uninit(cfg); return ret; } diff --git a/test/boot/bootctl/bootctl.c b/test/boot/bootctl/bootctl.c index ababe6f7b21..a3048a25489 100644 --- a/test/boot/bootctl/bootctl.c +++ b/test/boot/bootctl/bootctl.c @@ -101,6 +101,10 @@ static int bootctl_oslist_usb(struct unit_test_state *uts) ut_assertok(bc_oslist_next(dev, &iter, &info)); ut_asserteq_str("hub1.p4.usb_mass_storage.lun0.bootdev.part_1", bflow->name); + /* second entry from flash3 (Ubuntu has two extlinux labels) */ + ut_assertok(bc_oslist_next(dev, &iter, &info)); + ut_asserteq_str("hub1.p4.usb_mass_storage.lun0.bootdev.part_1", bflow->name); + ut_asserteq(-ENODEV, bc_oslist_next(dev, &iter, &info)); return 0; @@ -456,6 +460,10 @@ static int check_multiboot_ui(struct unit_test_state *uts, ut_assertok(bc_oslist_next(oslist_dev, &iter, &info[0])); ut_asserteq_str("mmc11.bootdev.part_1", info[0].bflow.name); + /* skip the second mmc11 entry (Ubuntu has two extlinux labels) */ + ut_assertok(bc_oslist_next(oslist_dev, &iter, &info[1])); + ut_asserteq_str("mmc11.bootdev.part_1", info[1].bflow.name); + ut_assertok(bc_oslist_next(oslist_dev, &iter, &info[1])); ut_asserteq_str("hub1.p4.usb_mass_storage.lun0.bootdev.part_1", info[1].bflow.name); diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c index 7a0e4f9acb7..59037f04ea3 100644 --- a/test/boot/bootflow.c +++ b/test/boot/bootflow.c @@ -292,7 +292,7 @@ static int bootflow_scan_boot(struct unit_test_state *uts) ut_assertok(run_command("bootflow scan -b", 0)); ut_assert_nextline( "** Booting bootflow 'mmc1.bootdev.part_1' with extlinux"); - ut_assert_nextline("Ignoring unknown command: ui"); + /* cached parse from scanning suppresses parser warnings */ /* * We expect it to get through to boot although sandbox always returns @@ -636,7 +636,7 @@ static int bootflow_cmd_boot(struct unit_test_state *uts) ut_asserteq(1, run_command("bootflow boot", 0)); ut_assert_nextline( "** Booting bootflow 'mmc1.bootdev.part_1' with extlinux"); - ut_assert_nextline("Ignoring unknown command: ui"); + /* cached parse from scanning suppresses parser warnings */ /* * We expect it to get through to boot although sandbox always returns @@ -1861,6 +1861,8 @@ static int bootflow_cmd_bls(struct unit_test_state *uts) { struct bootstd_priv *std; const char **old_order; + struct bootflow *bflow; + bool test_first; ut_assertok(prep_mmc_bootdev(uts, "mmc15", true, &old_order)); ut_assertok(run_command("bootflow scan", 0)); @@ -1871,13 +1873,25 @@ static int bootflow_cmd_bls(struct unit_test_state *uts) free(std->bootdev_order); std->bootdev_order = old_order; + /* + * BLS entry order depends on the filesystem, so detect which + * .conf file came first and check accordingly + */ + bflow = alist_getw(&std->bootflows, 1, struct bootflow); + test_first = !strcmp(bflow->os_name, "Test Boot"); + ut_assertok(run_command("bootflow list", 0)); ut_assert_nextline("Showing all bootflows"); ut_assert_nextline(HEADER); ut_assert_nextlinen("---"); ut_assert_nextlinen(" 0 extlinux"); - ut_assert_nextline(" 1 bls ready mmc 1 0 mmc15.bootdev.part_1 /loader/entries/6.8.0.conf"); - ut_assert_nextline(" 2 bls ready mmc 1 1 mmc15.bootdev.part_1 /loader/entries/6.8.0-rescue.conf"); + if (test_first) { + ut_assert_nextline(" 1 bls ready mmc 1 0 mmc15.bootdev.part_1 /loader/entries/6.8.0.conf"); + ut_assert_nextline(" 2 bls ready mmc 1 1 mmc15.bootdev.part_1 /loader/entries/6.8.0-rescue.conf"); + } else { + ut_assert_nextline(" 1 bls ready mmc 1 0 mmc15.bootdev.part_1 /loader/entries/6.8.0-rescue.conf"); + ut_assert_nextline(" 2 bls ready mmc 1 1 mmc15.bootdev.part_1 /loader/entries/6.8.0.conf"); + } ut_assert_nextlinen("---"); ut_assert_nextline("(3 bootflows, 3 valid)"); ut_assert_console_end(); @@ -1892,12 +1906,15 @@ static int bootflow_cmd_bls(struct unit_test_state *uts) ut_assert_nextline("Method: bls"); ut_assert_nextline("State: ready"); ut_assert_nextline("Partition: 1"); - ut_assert_nextline("Entry: 0: Test Boot"); + ut_assert_nextline("Entry: 0: %s", + test_first ? "Test Boot" : "Rescue Boot"); if (IS_ENABLED(CONFIG_BLK_LUKS)) ut_assert_nextline("Encrypted: no"); ut_assert_nextline("Subdir: (none)"); - ut_assert_nextline("Filename: /loader/entries/6.8.0.conf"); - ut_assert_skip_to_line("OS: Test Boot"); + ut_assert_nextline("Filename: /loader/entries/%s", + test_first ? "6.8.0.conf" : "6.8.0-rescue.conf"); + ut_assert_skip_to_line("OS: %s", + test_first ? "Test Boot" : "Rescue Boot"); ut_assert_skip_to_line("Error: 0"); ut_assert_console_end(); @@ -1906,8 +1923,10 @@ static int bootflow_cmd_bls(struct unit_test_state *uts) ut_assert_console_end(); ut_assertok(run_command("bootflow info", 0)); ut_assert_nextline("Name: mmc15.bootdev.part_1"); - ut_assert_skip_to_line("Filename: /loader/entries/6.8.0-rescue.conf"); - ut_assert_skip_to_line("OS: Rescue Boot"); + ut_assert_skip_to_line("Filename: /loader/entries/%s", + test_first ? "6.8.0-rescue.conf" : "6.8.0.conf"); + ut_assert_skip_to_line("OS: %s", + test_first ? "Rescue Boot" : "Test Boot"); ut_assert_skip_to_line("Error: 0"); ut_assert_console_end(); diff --git a/test/py/img/common.py b/test/py/img/common.py index 25edc84944e..6a1176e3dc5 100644 --- a/test/py/img/common.py +++ b/test/py/img/common.py @@ -34,7 +34,8 @@ def copy_partition(ubman, fsfile, outname): def setup_extlinux_image(config, log, devnum, basename, vmlinux, initrd, dtbdir, script, part2_size=1, use_fde=0, luks_kdf='pbkdf2', - encrypt_keyfile=None, master_keyfile=None): + encrypt_keyfile=None, master_keyfile=None, + extra_conf=None): """Create a 20MB disk image with a single FAT partition Args: @@ -54,6 +55,8 @@ def setup_extlinux_image(config, log, devnum, basename, vmlinux, initrd, dtbdir, If provided, takes precedence over passphrase. master_keyfile (str, optional): Path to file containing the raw master key. If provided, this exact key is used as the LUKS master key. + extra_conf (dict, optional): Extra files to create in the extlinux + directory, as {filename: content} pairs. """ fsh = FsHelper(config, 'vfat', 18, prefix=basename) fsh.setup() @@ -65,6 +68,12 @@ def setup_extlinux_image(config, log, devnum, basename, vmlinux, initrd, dtbdir, with open(conf, 'w', encoding='ascii') as fd: print(script, file=fd) + if extra_conf: + for fname, content in extra_conf.items(): + with open(os.path.join(ext, fname), 'w', + encoding='ascii') as fd: + print(content, file=fd) + inf = os.path.join(config.persistent_data_dir, 'inf') with open(inf, 'wb') as fd: fd.write(gzip.compress(b'vmlinux')) diff --git a/test/py/img/ubuntu.py b/test/py/img/ubuntu.py index 1f3016b79a6..3ef089da6b6 100644 --- a/test/py/img/ubuntu.py +++ b/test/py/img/ubuntu.py @@ -51,13 +51,16 @@ label l0 append root=/dev/disk/by-uuid/bcfdda4a-8249-4f40-9f0f-7c1a76b6cbe8 ro earlycon -label l0r +include rescue.conf +''' % (version, vmlinux, initrd) + rescue = '''label l0r menu label Ubuntu %s 6.8.0-53-generic (rescue target) linux /boot/%s initrd /boot/%s -''' % ((version, vmlinux, initrd) * 2) +''' % (version, vmlinux, initrd) setup_extlinux_image(config, log, devnum, basename, vmlinux, initrd, dtbdir, script, part2_size=60 if use_fde else 1, use_fde=use_fde, luks_kdf=luks_kdf, encrypt_keyfile=encrypt_keyfile, - master_keyfile=master_keyfile) + master_keyfile=master_keyfile, + extra_conf={'rescue.conf': rescue})