It is useful to be able to inspect things before the OS is actually booted, perhaps to check that all is well or to adjust the kernel command-line. Implement the 'read_all()' method to allow this.
Provide a simple test to check that the images are found. For now it is not possible to actually continue the uninterrupted boot, without re-reading all the images. Signed-off-by: Simon Glass <[email protected]> --- Changes in v3: - Pass through the bootfile since extlinux and PXE are different boot/bootmeth_extlinux.c | 11 ++++++++++ boot/bootmeth_pxe.c | 11 ++++++++++ boot/ext_pxe_common.c | 29 ++++++++++++++++++++++++--- include/extlinux.h | 15 ++++++++++++++ test/boot/bootflow.c | 43 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 106 insertions(+), 3 deletions(-) diff --git a/boot/bootmeth_extlinux.c b/boot/bootmeth_extlinux.c index e7277ccdaa9..bd9026d448b 100644 --- a/boot/bootmeth_extlinux.c +++ b/boot/bootmeth_extlinux.c @@ -145,6 +145,14 @@ static int extlinux_local_boot(struct udevice *dev, struct bootflow *bflow) return extlinux_boot(dev, bflow, extlinux_getfile, true, bflow->fname); } +#if CONFIG_IS_ENABLED(BOOTSTD_FULL) +static int extlinux_local_read_all(struct udevice *dev, struct bootflow *bflow) +{ + return extlinux_read_all(dev, bflow, extlinux_getfile, true, + bflow->fname); +} +#endif + static int extlinux_bootmeth_bind(struct udevice *dev) { struct bootmeth_uc_plat *plat = dev_get_uclass_plat(dev); @@ -162,6 +170,9 @@ static struct bootmeth_ops extlinux_bootmeth_ops = { .read_file = bootmeth_common_read_file, .boot = extlinux_local_boot, .set_property = extlinux_set_property, +#if CONFIG_IS_ENABLED(BOOTSTD_FULL) + .read_all = extlinux_local_read_all, +#endif }; static const struct udevice_id extlinux_bootmeth_ids[] = { diff --git a/boot/bootmeth_pxe.c b/boot/bootmeth_pxe.c index 5f3d595628c..4b5b88bae52 100644 --- a/boot/bootmeth_pxe.c +++ b/boot/bootmeth_pxe.c @@ -143,6 +143,14 @@ static int extlinux_pxe_boot(struct udevice *dev, struct bootflow *bflow) bflow->subdir); } +#if CONFIG_IS_ENABLED(BOOTSTD_FULL) +static int extlinux_pxe_read_all(struct udevice *dev, struct bootflow *bflow) +{ + return extlinux_read_all(dev, bflow, extlinux_pxe_getfile, false, + bflow->subdir); +} +#endif + static int extlinux_bootmeth_pxe_bind(struct udevice *dev) { struct bootmeth_uc_plat *plat = dev_get_uclass_plat(dev); @@ -159,6 +167,9 @@ static struct bootmeth_ops extlinux_bootmeth_pxe_ops = { .read_file = extlinux_pxe_read_file, .boot = extlinux_pxe_boot, .set_property = extlinux_set_property, +#if CONFIG_IS_ENABLED(BOOTSTD_FULL) + .read_all = extlinux_pxe_read_all, +#endif }; static const struct udevice_id extlinux_bootmeth_pxe_ids[] = { diff --git a/boot/ext_pxe_common.c b/boot/ext_pxe_common.c index 0d808048289..6e999af5fca 100644 --- a/boot/ext_pxe_common.c +++ b/boot/ext_pxe_common.c @@ -75,9 +75,9 @@ int extlinux_set_property(struct udevice *dev, const char *property, return 0; } -int extlinux_boot(struct udevice *dev, struct bootflow *bflow, - pxe_getfile_func getfile, bool allow_abs_path, - const char *bootfile) +static int extlinux_process(struct udevice *dev, struct bootflow *bflow, + pxe_getfile_func getfile, bool allow_abs_path, + const char *bootfile, bool no_boot) { struct extlinux_plat *plat = dev_get_plat(dev); ulong addr; @@ -92,6 +92,7 @@ int extlinux_boot(struct udevice *dev, struct bootflow *bflow, bootfile, false, plat->use_fallback, bflow); if (ret) return log_msg_ret("ctx", -EINVAL); + plat->ctx.no_boot = no_boot; ret = pxe_process(&plat->ctx, addr, false); if (ret) @@ -99,3 +100,25 @@ int extlinux_boot(struct udevice *dev, struct bootflow *bflow, return 0; } + +int extlinux_boot(struct udevice *dev, struct bootflow *bflow, + pxe_getfile_func getfile, bool allow_abs_path, + const char *bootfile) +{ + return extlinux_process(dev, bflow, getfile, allow_abs_path, bootfile, + false); +} + +int extlinux_read_all(struct udevice *dev, struct bootflow *bflow, + pxe_getfile_func getfile, bool allow_abs_path, + const char *bootfile) +{ + int ret; + + ret = extlinux_process(dev, bflow, getfile, allow_abs_path, bootfile, + true); + if (ret) + return log_msg_ret("era", -EINVAL); + + return 0; +} diff --git a/include/extlinux.h b/include/extlinux.h index 5baa2440b53..f64597ebdef 100644 --- a/include/extlinux.h +++ b/include/extlinux.h @@ -64,4 +64,19 @@ int extlinux_boot(struct udevice *dev, struct bootflow *bflow, pxe_getfile_func getfile, bool allow_abs_path, const char *bootfile); +/** + * extlinux_read_all() - read all files for a bootflow + * + * @dev: Bootmethod device to boot + * @bflow: Bootflow to read + * @getfile: Function to use to read files + * @allow_abs_path: true to allow absolute paths + * @bootfile: Bootfile whose directory loaded files are relative to, NULL if + * none + * Return: 0 if OK, -EIO on I/O error, other -ve on other error + */ +int extlinux_read_all(struct udevice *dev, struct bootflow *bflow, + pxe_getfile_func getfile, bool allow_abs_path, + const char *bootfile); + #endif diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c index f7d12765928..ef8c0c1bbaa 100644 --- a/test/boot/bootflow.c +++ b/test/boot/bootflow.c @@ -1433,3 +1433,46 @@ static int bootstd_adhoc(struct unit_test_state *uts) return 0; } BOOTSTD_TEST(bootstd_adhoc, UTF_CONSOLE); + +/* Check scanning extlinux, adjusting cmdline and booting */ +static int bootflow_scan_extlinux(struct unit_test_state *uts) +{ + const struct bootflow_img *img; + struct bootstd_priv *std; + struct bootflow *bflow; + + ut_assertok(run_command("bootflow scan", 0)); + ut_assert_console_end(); + ut_assertok(bootstd_get_priv(&std)); + + ut_asserteq(1, std->bootflows.count); + + bflow = alist_getw(&std->bootflows, 0, struct bootflow); + std->cur_bootflow = bflow; + + /* read all the images, but don't actually boot */ + ut_assertok(inject_response(uts)); + ut_assertok(bootflow_read_all(bflow)); + + /* check that the command line is now present */ + ut_asserteq_str( + "ro root=UUID=9732b35b-4cd5-458b-9b91-80f7047e0b8a rhgb quiet LANG=en_US.UTF-8 cma=192MB cma=256MB", + bflow->cmdline); + + ut_asserteq(3, bflow->images.count); + + /* check each image */ + img = alist_get(&bflow->images, 0, struct bootflow_img); + ut_asserteq_strn("# extlinux.conf", map_sysmem(img->addr, 0)); + + img = alist_get(&bflow->images, 1, struct bootflow_img); + ut_asserteq(IH_TYPE_KERNEL, img->type); + ut_asserteq(0x1000000, img->addr); /* kernel_addr_r */ + + img = alist_get(&bflow->images, 2, struct bootflow_img); + ut_asserteq(IH_TYPE_RAMDISK, img->type); + ut_asserteq(0x2000000, img->addr); /* ramdisk_addr_r */ + + return 0; +} +BOOTSTD_TEST(bootflow_scan_extlinux, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE); -- 2.34.1

