[PATCH v2 3/5] cdev-alias: add support for storage{.removable,.builtin}

Ahmad Fatoum a.fatoum at pengutronix.de
Fri Dec 12 08:12:51 PST 2025


Our current of global.boot.default expanding to bootsource doesn't work
when booting from flash that only contains the bootloader.

Improve upon this by adding cdev aliases for removable and builtin
storage devices.

Reviewed-by: Sascha Hauer <s.hauer at pengutronix.de>
Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
v1 -> v2:
  - add Sascha's R-b
  - fix typo in docs and mention slotted SD-card specially (Sascha)
  - extend help text for boot command (Sascha)
  - replace "boot-only flash" in commit message (Sascha)
---
 Documentation/user/booting-linux.rst | 26 +++++++++
 commands/boot.c                      |  3 +
 common/cdev-alias.c                  | 86 ++++++++++++++++++++++++++++
 include/driver.h                     |  5 ++
 4 files changed, 120 insertions(+)

diff --git a/Documentation/user/booting-linux.rst b/Documentation/user/booting-linux.rst
index b164c538c62a..6a41de6712ea 100644
--- a/Documentation/user/booting-linux.rst
+++ b/Documentation/user/booting-linux.rst
@@ -182,6 +182,32 @@ and configure the overrides as arguments to the ``boot`` command:
 
   boot -o bootm.image=/mnt/tftp/oftree mmc
 
+Generic Boot Targets
+^^^^^^^^^^^^^^^^^^^^
+
+A single boot target can yield multiple entries, e.g., one for each
+bootloader spec file detected at runtime as described in the next section.
+
+There is also a number of generic default boot targets available, when
+``CONFIG_BOOT_DEFAULTS`` is enabled. These expands to a single device at most:
+
+* ``bootsource``: expands to the device barebox booted from
+* ``diskuuid.*``: expands to the device with specified ``*`` diskuuid
+
+For these targets that expand to a single device, a partition can also be specified,
+e.g., ``bootsource.esp`` to reference the partition with the ``esp`` partition
+label within the bootsource.
+
+Following target can expand to multiple devices:
+
+* ``storage.removable``: expands to removable storage devices,
+  like USB flash drives or SD-Cards in slots
+* ``storage.builtin``: expands to built-in storage devices, like eMMC
+* ``storage``: expands to all of the above ``storage.*``
+
+If the bootsource exists within any of these targets, it will be the first
+device in the returned list.
+
 .. _bootloader_spec:
 
 Boot Loader Specification
diff --git a/commands/boot.c b/commands/boot.c
index 97c574b4a0a3..9cfb7c6b0d5e 100644
--- a/commands/boot.c
+++ b/commands/boot.c
@@ -185,6 +185,9 @@ BAREBOX_CMD_HELP_TEXT("- \"bootchooser\": boot with barebox bootchooser")
 #ifdef CONFIG_BOOT_DEFAULTS
 BAREBOX_CMD_HELP_TEXT("- \"bootsource\": boot from the device barebox has been started from")
 BAREBOX_CMD_HELP_TEXT("- \"diskuuid.*\": boot from disk with specified diskuuid")
+BAREBOX_CMD_HELP_TEXT("- \"storage.removable\": boot from removable media")
+BAREBOX_CMD_HELP_TEXT("- \"storage.builtin\": boot from non-removable media")
+BAREBOX_CMD_HELP_TEXT("- \"storage\": boot from any available media")
 #endif
 BAREBOX_CMD_HELP_TEXT("")
 BAREBOX_CMD_HELP_TEXT("Multiple bootsources may be given which are probed in order until")
diff --git a/common/cdev-alias.c b/common/cdev-alias.c
index 3732fd90525f..82b91108c1fc 100644
--- a/common/cdev-alias.c
+++ b/common/cdev-alias.c
@@ -9,7 +9,9 @@
 #include <stringlist.h>
 #include <bootsource.h>
 #include <driver.h>
+#include <block.h>
 #include <init.h>
+#include <linux/bits.h>
 
 struct cdev_alias_res {
 	const char *name;
@@ -77,9 +79,93 @@ static int cdev_alias_resolve_diskuuid(struct cdev_alias_res *cdev_alias_res,
 	return ret;
 }
 
+#define STORAGE_REMOVABLE	BIT(0)
+#define STORAGE_BUILTIN		BIT(1)
+
+/**
+ * call_for_each_storage() - invoke callback for each storage medium
+ *
+ * @fn:			callback to invoke
+ * @data:		callback-specific data
+ * @filter:		OR-ed types of STORAGE_* to filter for
+ * @only_bootsource:	If true, include only bootsource if available,
+ *			otherwise omit always
+ * Return:		number of successful callback invocations or a negative error
+ */
+static int call_for_each_storage(cdev_alias_processor_t fn,
+				 void *data,
+				 unsigned filter,
+				 bool only_bootsource)
+{
+	struct cdev *cdev, *bootcdev;
+	int ret, nmatches = 0;
+
+	bootcdev = bootsource_of_cdev_find();
+
+	for_each_cdev(cdev) {
+		struct block_device *bdev;
+
+		if (!cdev_is_storage(cdev) || cdev_is_partition(cdev))
+			continue;
+
+		bdev = cdev_get_block_device(cdev);
+
+		if (((filter & STORAGE_REMOVABLE) && bdev && bdev->removable) ||
+		    ((filter & STORAGE_BUILTIN) && (!bdev || !bdev->removable))) {
+			if (only_bootsource && cdev != bootcdev)
+				continue;
+			if (!only_bootsource && cdev == bootcdev)
+				continue;
+
+			ret = fn(cdev, data);
+			if (ret < 0)
+				return ret;
+			nmatches++;
+
+			/* Got our bootsource, no need to continue iteration */
+			if (only_bootsource)
+				break;
+		}
+	}
+
+	return nmatches;
+}
+
+static int cdev_alias_resolve_storage(struct cdev_alias_res *cdev_alias_res,
+				      const char *class,
+				      cdev_alias_processor_t fn,
+				      void *data)
+{
+	struct cdev *bootcdev;
+	unsigned filter = 0;
+	int bootsource, nmatches;
+
+	if (!class)
+		filter = ~0;
+	else if (streq_ptr(class, "removable"))
+		filter |= STORAGE_REMOVABLE;
+	else if (streq_ptr(class, "builtin"))
+		filter |= STORAGE_BUILTIN;
+	else
+		return -EINVAL;
+
+	bootcdev = bootsource_of_cdev_find();
+
+	bootsource = call_for_each_storage(fn, data, filter, true);
+	if (bootsource < 0)
+		return bootsource;
+
+	nmatches = call_for_each_storage(fn, data, filter, false);
+	if (nmatches < 0)
+		return nmatches;
+
+	return bootsource + nmatches;
+}
+
 static struct cdev_alias_res cdev_alias_aliases[] = {
 	{ "bootsource", cdev_alias_resolve_bootsource },
 	{ "diskuuid", cdev_alias_resolve_diskuuid },
+	{ "storage", cdev_alias_resolve_storage },
 	{ /* sentinel */}
 };
 
diff --git a/include/driver.h b/include/driver.h
index a941ca6127e6..de5a63c379eb 100644
--- a/include/driver.h
+++ b/include/driver.h
@@ -597,6 +597,11 @@ get_inheritable_devfs_flags(const struct cdev *parent_cdev)
 	return parent_cdev->flags & DEVFS_INHERITABLE_FLAGS;
 }
 
+static inline bool cdev_is_storage(const struct cdev *cdev)
+{
+	return (cdev->flags & DEVFS_IS_BLOCK_DEV) || cdev->mtd;
+}
+
 struct cdev *
 cdev_find_child_by_gpt_typeuuid(struct cdev *cdev, const guid_t *typeuuid);
 
-- 
2.47.3




More information about the barebox mailing list