bootstd: Update extlinux and pxe to allow boot interruption
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 <sjg@chromium.org>
This commit is contained in:
@@ -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[] = {
|
||||
|
||||
@@ -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[] = {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user