[PATCH] bootstd: support scanning a single partition

Nam Cao namcao at linutronix.de
Wed Feb 21 13:41:44 CET 2024


The "bootflow" command currently doesn't support scanning a single
partition. This is inconvenient in setups with multiple bootable
partitions within a single disk, but only one is desired.

Support scanning a single disk partition. Specifically, support the
syntax:
	bootflow scan mmc1:4
which scans only mmc device 1, partition 4.

Signed-off-by: Nam Cao <namcao at linutronix.de>
---
 boot/bootdev-uclass.c   | 35 +++++++++++++++++++++++++++++++++--
 boot/bootflow.c         |  3 +++
 doc/develop/bootstd.rst |  4 ++++
 include/bootflow.h      |  3 +++
 4 files changed, 43 insertions(+), 2 deletions(-)

diff --git a/boot/bootdev-uclass.c b/boot/bootdev-uclass.c
index 35afb93c0e..64e09fa0d0 100644
--- a/boot/bootdev-uclass.c
+++ b/boot/bootdev-uclass.c
@@ -173,8 +173,10 @@ int bootdev_find_in_blk(struct udevice *dev, struct udevice *blk,
 	 */
 	iter->max_part = MAX_PART_PER_BOOTDEV;
 
-	/* If this is the whole disk, check if we have bootable partitions */
-	if (!iter->part) {
+	if (iter->flags & BOOTFLOWIF_SINGLE_PARTITION) {
+		/* a particular partition was specified, scan it without checking */
+	} else if (!iter->part) {
+		/* This is the whole disk, check if we have bootable partitions */
 		iter->first_bootable = part_get_bootable(desc);
 		log_debug("checking bootable=%d\n", iter->first_bootable);
 	} else if (allow_any_part) {
@@ -711,8 +713,37 @@ int bootdev_setup_iter(struct bootflow_iter *iter, const char *label,
 	struct udevice *bootstd, *dev = NULL;
 	bool show = iter->flags & BOOTFLOWIF_SHOW;
 	int method_flags;
+	char buf[32];
 	int ret;
 
+	if (label) {
+		const char *end = strchr(label, ':');
+
+		if (end) {
+			size_t len = (size_t)(end - label);
+			const char *part = end + 1;
+
+			if (len + 1 > sizeof(buf)) {
+				log_err("label \"%s\" is way too long\n", label);
+				return -EINVAL;
+			}
+
+			memcpy(buf, label, len);
+			buf[len] = '\0';
+			label = buf;
+
+			unsigned long tmp;
+
+			if (strict_strtoul(part, 0, &tmp)) {
+				log_err("Invalid partition number: %s\n", part);
+				return -EINVAL;
+			}
+
+			iter->flags |= BOOTFLOWIF_SINGLE_PARTITION;
+			iter->part = tmp;
+		}
+	}
+
 	ret = uclass_first_device_err(UCLASS_BOOTSTD, &bootstd);
 	if (ret) {
 		log_err("Missing bootstd device\n");
diff --git a/boot/bootflow.c b/boot/bootflow.c
index 05484fd5b1..68bf99329a 100644
--- a/boot/bootflow.c
+++ b/boot/bootflow.c
@@ -217,6 +217,9 @@ static int iter_incr(struct bootflow_iter *iter)
 		}
 	}
 
+	if (iter->flags & BOOTFLOWIF_SINGLE_PARTITION)
+		return BF_NO_MORE_DEVICES;
+
 	/* No more bootmeths; start at the first one, and... */
 	iter->cur_method = 0;
 	iter->method = iter->method_order[iter->cur_method];
diff --git a/doc/develop/bootstd.rst b/doc/develop/bootstd.rst
index 496e24bc7a..a07a72581e 100644
--- a/doc/develop/bootstd.rst
+++ b/doc/develop/bootstd.rst
@@ -531,6 +531,10 @@ Then the iterator is set up to according to the parameters given:
     `BOOTFLOWIF_SINGLE_MEDIA` is set. In this case, moving to the next bootdev
     processes just the children of the media device. Hunters are used, in this
     example just the "mmc" hunter.
+  - If `label` indicates a particular partition in a particular media device
+    (e.g. "mmc1:3") then `BOOTFLOWIF_SINGLE_PARTITION` is set. In this case,
+    only a single partition within a bootdev is processed. Hunters are used, in
+    this example just the "mmc" hunter.
   - If `label` indicates a media uclass (e.g. "mmc") then
     `BOOTFLOWIF_SINGLE_UCLASS` is set. In this case, all bootdevs in that uclass
     are used. Hunters are used, in this example just the "mmc" hunter
diff --git a/include/bootflow.h b/include/bootflow.h
index 42112874f6..080ee85012 100644
--- a/include/bootflow.h
+++ b/include/bootflow.h
@@ -133,6 +133,8 @@ struct bootflow {
  * this uclass (used with things like "mmc")
  * @BOOTFLOWIF_SINGLE_MEDIA: (internal) Scan one media device in the uclass (used
  * with things like "mmc1")
+ * @BOOTFLOWIF_SINGLE_PARTITION: (internal) Scan one partition in media device
+ * (used with things like "mmc1:3")
  */
 enum bootflow_iter_flags_t {
 	BOOTFLOWIF_FIXED		= 1 << 0,
@@ -148,6 +150,7 @@ enum bootflow_iter_flags_t {
 	BOOTFLOWIF_SKIP_GLOBAL		= 1 << 17,
 	BOOTFLOWIF_SINGLE_UCLASS	= 1 << 18,
 	BOOTFLOWIF_SINGLE_MEDIA		= 1 << 19,
+	BOOTFLOWIF_SINGLE_PARTITION	= 1 << 20,
 };
 
 /**
-- 
2.39.2



More information about the U-Boot mailing list