[PATCH 35/39] bootstd: Update extlinux and pxe to allow boot interruption

Simon Glass sjg at chromium.org
Tue Nov 19 14:18:40 CET 2024


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 at chromium.org>
---

 boot/bootmeth_extlinux.c | 10 ++++++++++
 boot/bootmeth_pxe.c      | 10 ++++++++++
 boot/ext_pxe_common.c    | 23 +++++++++++++++++++--
 include/extlinux.h       | 11 ++++++++++
 test/boot/bootflow.c     | 43 ++++++++++++++++++++++++++++++++++++++++
 5 files changed, 95 insertions(+), 2 deletions(-)

diff --git a/boot/bootmeth_extlinux.c b/boot/bootmeth_extlinux.c
index df5b5ea7bf4..14c13971852 100644
--- a/boot/bootmeth_extlinux.c
+++ b/boot/bootmeth_extlinux.c
@@ -143,6 +143,13 @@ static int extlinux_local_boot(struct udevice *dev, struct bootflow *bflow)
 	return extlinux_boot(dev, bflow, extlinux_getfile);
 }
 
+#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);
+}
+#endif
+
 static int extlinux_bootmeth_bind(struct udevice *dev)
 {
 	struct bootmeth_uc_plat *plat = dev_get_uclass_plat(dev);
@@ -160,6 +167,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 6ecf81d7878..a4dd48a7010 100644
--- a/boot/bootmeth_pxe.c
+++ b/boot/bootmeth_pxe.c
@@ -142,6 +142,13 @@ static int extlinux_pxe_boot(struct udevice *dev, struct bootflow *bflow)
 	return extlinux_boot(dev, bflow, extlinux_pxe_getfile);
 }
 
+#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);
+}
+#endif
+
 static int extlinux_bootmeth_pxe_bind(struct udevice *dev)
 {
 	struct bootmeth_uc_plat *plat = dev_get_uclass_plat(dev);
@@ -158,6 +165,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 7b9c41b5f77..c7f690dee17 100644
--- a/boot/ext_pxe_common.c
+++ b/boot/ext_pxe_common.c
@@ -75,8 +75,8 @@ 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)
+static int extlinux_process(struct udevice *dev, struct bootflow *bflow,
+			    pxe_getfile_func getfile, bool no_boot)
 {
 	struct extlinux_plat *plat = dev_get_plat(dev);
 	ulong addr;
@@ -91,6 +91,7 @@ int extlinux_boot(struct udevice *dev, struct bootflow *bflow,
 			    bflow->fname, 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)
@@ -98,3 +99,21 @@ int extlinux_boot(struct udevice *dev, struct bootflow *bflow,
 
 	return 0;
 }
+
+int extlinux_boot(struct udevice *dev, struct bootflow *bflow,
+		  pxe_getfile_func getfile)
+{
+	return extlinux_process(dev, bflow, getfile, false);
+}
+
+int extlinux_read_all(struct udevice *dev, struct bootflow *bflow,
+		      pxe_getfile_func getfile)
+{
+	int ret;
+
+	ret = extlinux_process(dev, bflow, getfile, true);
+	if (ret)
+		return log_msg_ret("era", -EINVAL);
+
+	return 0;
+}
diff --git a/include/extlinux.h b/include/extlinux.h
index 69781e666c3..ab93761c54c 100644
--- a/include/extlinux.h
+++ b/include/extlinux.h
@@ -60,4 +60,15 @@ int extlinux_set_property(struct udevice *dev, const char *property,
 int extlinux_boot(struct udevice *dev, struct bootflow *bflow,
 		  pxe_getfile_func getfile);
 
+/**
+ * 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
+ * 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);
+
 #endif
diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c
index 749d79d3295..4671bd7ab1f 100644
--- a/test/boot/bootflow.c
+++ b/test/boot/bootflow.c
@@ -1410,3 +1410,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



More information about the U-Boot mailing list