[PATCH v3 18/19] bootstd: Add the concept of an ad-hoc bootflow

Simon Glass sjg at chromium.org
Mon Nov 4 18:51:09 CET 2024


The normal situation with bootstd is that a bootflow is created from a
bootmeth. In some cases, a script or user-command may cause an image to
be loaded. To deal with this, add the concept of an ad-hoc bootflow.
This can be used to record information about manually loaded images.

Signed-off-by: Simon Glass <sjg at chromium.org>
---

Changes in v3:
- Add a new patch supporting ad-hoc bootflows

 boot/bootstd-uclass.c | 44 +++++++++++++++++++++++++++++++++++++++++++
 cmd/bootflow.c        |  5 +++--
 include/bootflow.h    |  3 ++-
 include/bootstd.h     | 19 +++++++++++++++++++
 4 files changed, 68 insertions(+), 3 deletions(-)

diff --git a/boot/bootstd-uclass.c b/boot/bootstd-uclass.c
index 8c0fd4e63c3..9bee73ead58 100644
--- a/boot/bootstd-uclass.c
+++ b/boot/bootstd-uclass.c
@@ -7,6 +7,8 @@
  */
 
 #include <alist.h>
+#include <blk.h>
+#include <bootdev.h>
 #include <bootflow.h>
 #include <bootstd.h>
 #include <dm.h>
@@ -161,11 +163,53 @@ int bootstd_get_priv(struct bootstd_priv **stdp)
 	return 0;
 }
 
+int bootstd_img_add(struct blk_desc *desc, int part, const char *fname,
+		    enum bootflow_img_t type, ulong addr, ulong size)
+{
+	struct udevice *bootdev = NULL;
+	struct bootstd_priv *std;
+	struct bootflow *bflow, bflow_s;
+	int ret;
+
+	ret = bootstd_get_priv(&std);
+	if (ret)
+		return ret;
+
+	if (desc) {
+		ret = bootdev_get_from_blk(desc->bdev, &bootdev);
+		if (ret)
+			return log_msg_ret("iad", ret);
+	}
+
+	bflow = alist_getw(&std->bootflows, std->adhoc_bflow, struct bootflow);
+	if (!bflow) {
+		bflow = &bflow_s;
+
+		bootflow_init(bflow, bootdev, NULL);
+		bflow->name = strdup("ad-hoc");
+		if (!bflow->name)
+			return log_msg_ret("ian", -ENOMEM);
+	}
+
+	if (!bootflow_img_add(bflow, fname, type, addr, size))
+		return log_msg_ret("iaf", -ENOMEM);
+
+	if (bflow == &bflow_s) {
+		ret = bootstd_add_bootflow(bflow);
+		if (ret < 0)
+			return log_msg_ret("iab", ret);
+		std->adhoc_bflow = ret;
+	}
+
+	return 0;
+}
+
 static int bootstd_probe(struct udevice *dev)
 {
 	struct bootstd_priv *std = dev_get_priv(dev);
 
 	alist_init_struct(&std->bootflows, struct bootflow);
+	std->adhoc_bflow = -1;
 
 	return 0;
 }
diff --git a/cmd/bootflow.c b/cmd/bootflow.c
index f88995a478f..5668a0c9b19 100644
--- a/cmd/bootflow.c
+++ b/cmd/bootflow.c
@@ -68,7 +68,8 @@ static void report_bootflow_err(struct bootflow *bflow, int err)
 static void show_bootflow(int index, struct bootflow *bflow, bool errors)
 {
 	printf("%3x  %-11s  %-6s  %-9.9s %4x  %-25.25s %s\n", index,
-	       bflow->method->name, bootflow_state_get_name(bflow->state),
+	       bflow->method ? bflow->method->name : "(none)",
+	       bootflow_state_get_name(bflow->state),
 	       bflow->dev ? dev_get_uclass_name(dev_get_parent(bflow->dev)) :
 	       "(none)", bflow->part, bflow->name, bflow->fname ?: "");
 	if (errors)
@@ -388,7 +389,7 @@ static int do_bootflow_info(struct cmd_tbl *cmdtp, int flag, int argc,
 	printf("Name:      %s\n", bflow->name);
 	printf("Device:    %s\n", bflow->dev->name);
 	printf("Block dev: %s\n", bflow->blk ? bflow->blk->name : "(none)");
-	printf("Method:    %s\n", bflow->method->name);
+	printf("Method:    %s\n", bflow->method ? bflow->method->name : "(none)");
 	printf("State:     %s\n", bootflow_state_get_name(bflow->state));
 	printf("Partition: %d\n", bflow->part);
 	printf("Subdir:    %s\n", bflow->subdir ? bflow->subdir : "(none)");
diff --git a/include/bootflow.h b/include/bootflow.h
index 480cf8a5af1..d9045bc3dae 100644
--- a/include/bootflow.h
+++ b/include/bootflow.h
@@ -68,7 +68,8 @@ enum bootflow_flags_t {
  * @fs_type: Filesystem type (FS_TYPE...) if this is fixed by the media, else 0.
  *	For example, the sandbox host-filesystem bootdev sets this to
  *	FS_TYPE_SANDBOX
- * @method: Bootmethod device used to perform the boot and read files
+ * @method: Bootmethod device used to perform the boot and read files; NULL for
+ *	ad-hoc bootflows
  * @name: Name of bootflow (allocated)
  * @state: Current state (enum bootflow_state_t)
  * @subdir: Subdirectory to fetch files from (with trailing /), or NULL if none
diff --git a/include/bootstd.h b/include/bootstd.h
index 3398e48e88b..c39058c0787 100644
--- a/include/bootstd.h
+++ b/include/bootstd.h
@@ -10,10 +10,12 @@
 #define __bootstd_h
 
 #include <alist.h>
+#include <bootflow.h>
 #include <dm/ofnode_decl.h>
 #include <linux/list.h>
 #include <linux/types.h>
 
+struct blk_desc;
 struct udevice;
 
 /**
@@ -33,6 +35,7 @@ struct udevice;
  * @cur_bootflow: Currently selected bootflow (for commands)
  * @bootflows: (struct bootflow) Global list of all bootflows across all
  *	bootdevs
+ * @adhoc_bflow: Index of ad-hoc bootflow in bootflows (-1 if none)
  * @bootmeth_count: Number of bootmeth devices in @bootmeth_order
  * @bootmeth_order: List of bootmeth devices to use, in order, NULL-terminated
  * @vbe_bootmeth: Currently selected VBE bootmeth, NULL if none
@@ -47,6 +50,7 @@ struct bootstd_priv {
 	struct udevice *cur_bootdev;
 	struct bootflow *cur_bootflow;
 	struct alist bootflows;
+	int adhoc_bflow;
 	int bootmeth_count;
 	struct udevice **bootmeth_order;
 	struct udevice *vbe_bootmeth;
@@ -151,4 +155,19 @@ int bootstd_add_bootflow(struct bootflow *bflow);
  */
 int bootstd_clear_bootflows_for_bootdev(struct udevice *dev);
 
+/**
+ * bootstd_img_add() - Add an image to the ad-hoc bootflow
+ *
+ * @desc: Block descriptor for the device from which the file was loaded, or
+ *	NULL if not a block device
+ * @part: Partition number within the block device
+ * @fname: Filename of loaded file
+ * @type: File type, IH_TYPE_INVALID if not known
+ * @addr: Address where the file was loaded
+ * @size: Size of the file
+ * Return: 0 if OK, or -ve error code
+ */
+int bootstd_img_add(struct blk_desc *desc, int fs_type, const char *fname,
+		    enum bootflow_img_t type, ulong addr, ulong size);
+
 #endif
-- 
2.34.1



More information about the U-Boot mailing list