mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH 00/16] boot: implement generic bootsource target
@ 2025-04-01 10:47 Ahmad Fatoum
  2025-04-01 10:47 ` [PATCH 01/16] boot: change bootentry_register_provider to take struct argument Ahmad Fatoum
                   ` (15 more replies)
  0 siblings, 16 replies; 17+ messages in thread
From: Ahmad Fatoum @ 2025-04-01 10:47 UTC (permalink / raw)
  To: barebox

The default net boot target is suboptimal in that it usually fails for
a new board. A better default would be to try booting from the same boot
medium, barebox itself was booted from, which so far was only possible
via scripts.

This series adds a new way to achieve this through a bootsource alias.

`boot bootsource` will then be resolved to e.g. `boot mmc0`, which will
walk all partitions in search of bootloader spec entries.
In that system, `boot bootsource.1` would be resolved to `boot mmc0.1`.

A key aspect of the cdev resolution is that it happens at use time.
This makes it easier for dynamic aliases and even allows for having
aliases that resolve to multiple cdevs.

In the future with EFI support, this same mechanism can be used to
identify the correct ESP by its partition type and boot the EFI payload
contained within. To make that future easier, the blspec code is
reworked for better reuse in future before adding support to boot a
specific cdev by name without expecting that device name and cdev name
are identical.

In addition, I have patches that would follow to make cdev aliases
usable from the device tree as well: A barebox,bootsource node for
example would resolve to the correct cdev and can thus be used together
with barebox state to allow for images that behave identically on SD and
eMMC without having to resort to scripting or board code.

Ahmad Fatoum (16):
  boot: change bootentry_register_provider to take struct argument
  boot: move nfs:// parsing out of bootloader spec code
  blspec: remove unused blspec_scan_devices
  blspec: don't export blspec functions
  blspec: factor out generic parts into bootscan helper
  common: bootscan: add scan_disk callback
  blspec: support boot /dev/virtioblkX
  bootm: associate bootm overrides with struct bootentry
  boot: split off bootarg API into new bootargs.h header
  block: add get_rootarg block op into block_device_ops
  block: fixup rootwait argument when needed by default
  of: implement stub for of_cdev_find
  bootsource: implement bootsource_of_cdev_find
  common: bootdef: add new boot entry provider
  kconfig: implement IF_ENABLED helper
  boot: make bootsource the default boot target if enabled

 arch/arm/boards/protonic-imx6/board.c |  10 +-
 commands/boot.c                       |  11 +-
 common/Kconfig                        |  25 ++
 common/Makefile                       |   4 +-
 common/block.c                        |  27 ++
 common/blspec.c                       | 403 ++++++--------------------
 common/boot.c                         | 144 ++++++++-
 common/bootargs.c                     |  12 +
 common/bootchooser.c                  |   6 +-
 common/bootdef.c                      |  40 +++
 common/bootm.c                        |   9 +-
 common/bootscan.c                     | 187 ++++++++++++
 common/bootsource.c                   |  17 ++
 common/cdev-alias.c                   |  79 +++++
 drivers/block/efi-block-io.c          |  10 +-
 drivers/mci/mci-core.c                |  46 ++-
 drivers/usb/storage/usb.c             |   1 +
 fs/fs.c                               |  56 ----
 fs/nfs.c                              |   4 +
 include/block.h                       |   7 +
 include/blspec.h                      |  29 --
 include/boot.h                        |  26 +-
 include/bootargs.h                    |  29 ++
 include/bootm-overrides.h             |  30 ++
 include/bootm.h                       |  18 --
 include/bootscan.h                    |  34 +++
 include/bootsource.h                  |   1 +
 include/driver.h                      |  19 +-
 include/fs.h                          |   1 -
 include/linux/kconfig.h               |   6 +
 include/of.h                          |   5 +
 31 files changed, 814 insertions(+), 482 deletions(-)
 create mode 100644 common/bootdef.c
 create mode 100644 common/bootscan.c
 create mode 100644 common/cdev-alias.c
 delete mode 100644 include/blspec.h
 create mode 100644 include/bootargs.h
 create mode 100644 include/bootm-overrides.h
 create mode 100644 include/bootscan.h

-- 
2.39.5




^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 01/16] boot: change bootentry_register_provider to take struct argument
  2025-04-01 10:47 [PATCH 00/16] boot: implement generic bootsource target Ahmad Fatoum
@ 2025-04-01 10:47 ` Ahmad Fatoum
  2025-04-01 10:47 ` [PATCH 02/16] boot: move nfs:// parsing out of bootloader spec code Ahmad Fatoum
                   ` (14 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Ahmad Fatoum @ 2025-04-01 10:47 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum

bootentry_register_provider currently takes a single argument only:
The callback. To allow for an easier future extension, have it take a
struct instead.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 arch/arm/boards/protonic-imx6/board.c | 10 +++++++---
 common/blspec.c                       |  8 ++++++--
 common/boot.c                         | 17 +++--------------
 common/bootchooser.c                  |  6 +++++-
 include/boot.h                        |  8 +++++++-
 5 files changed, 28 insertions(+), 21 deletions(-)

diff --git a/arch/arm/boards/protonic-imx6/board.c b/arch/arm/boards/protonic-imx6/board.c
index 0bbabbb8c734..7aa026594cc7 100644
--- a/arch/arm/boards/protonic-imx6/board.c
+++ b/arch/arm/boards/protonic-imx6/board.c
@@ -440,8 +440,8 @@ static int prt_imx6_bootentry_create(struct bootentries *bootentries, const char
 	return 0;
 }
 
-static int prt_imx6_bootentry_provider(struct bootentries *bootentries,
-				     const char *name)
+static int prt_imx6_bootentry_generate(struct bootentries *bootentries,
+				       const char *name)
 {
 	int found = 0;
 	unsigned int v;
@@ -459,6 +459,10 @@ static int prt_imx6_bootentry_provider(struct bootentries *bootentries,
 	return found;
 }
 
+static struct bootentry_provider prt_imx6_bootentry_provider = {
+	.generate = prt_imx6_bootentry_generate,
+};
+
 static int prt_imx6_env_init(struct prt_imx6_priv *priv)
 {
 	const struct prt_machine_data *dcfg = priv->dcfg;
@@ -568,7 +572,7 @@ static int prt_imx6_devices_init(void)
 	if (prt_imx6_read_ocotp_serial(priv) != 0)
 		prt_imx6_read_i2c_mac_serial(priv);
 
-	bootentry_register_provider(prt_imx6_bootentry_provider);
+	bootentry_register_provider(&prt_imx6_bootentry_provider);
 
 	prt_imx6_env_init(priv);
 
diff --git a/common/blspec.c b/common/blspec.c
index 77ae3dc21951..27ac6560b97b 100644
--- a/common/blspec.c
+++ b/common/blspec.c
@@ -788,7 +788,7 @@ int blspec_scan_devicename(struct bootentries *bootentries, const char *devname)
 	return blspec_scan_device(bootentries, dev);
 }
 
-static int blspec_bootentry_provider(struct bootentries *bootentries,
+static int blspec_bootentry_generate(struct bootentries *bootentries,
 				     const char *name)
 {
 	struct stat s;
@@ -822,8 +822,12 @@ static int blspec_bootentry_provider(struct bootentries *bootentries,
 	return found;
 }
 
+static struct bootentry_provider blspec_bootentry_provider = {
+	.generate = blspec_bootentry_generate,
+};
+
 static int blspec_init(void)
 {
-	return bootentry_register_provider(blspec_bootentry_provider);
+	return bootentry_register_provider(&blspec_bootentry_provider);
 }
 device_initcall(blspec_init);
diff --git a/common/boot.c b/common/boot.c
index 2530a5bbeeac..e3bdfec581c1 100644
--- a/common/boot.c
+++ b/common/boot.c
@@ -267,20 +267,9 @@ static int bootscript_scan_path(struct bootentries *bootentries, const char *pat
 
 static LIST_HEAD(bootentry_providers);
 
-struct bootentry_provider {
-	int (*fn)(struct bootentries *bootentries, const char *name);
-	struct list_head list;
-};
-
-int bootentry_register_provider(int (*fn)(struct bootentries *bootentries, const char *name))
+int bootentry_register_provider(struct bootentry_provider *p)
 {
-	struct bootentry_provider *p;
-
-	p = xzalloc(sizeof(*p));
-	p->fn = fn;
-
-	list_add_tail(&p->list, &bootentry_providers);
-
+	list_add(&p->list, &bootentry_providers);
 	return 0;
 }
 
@@ -306,7 +295,7 @@ int bootentry_create_from_name(struct bootentries *bootentries,
 	int found = 0, ret;
 
 	list_for_each_entry(p, &bootentry_providers, list) {
-		ret = p->fn(bootentries, name);
+		ret = p->generate(bootentries, name);
 		if (ret > 0)
 			found += ret;
 	}
diff --git a/common/bootchooser.c b/common/bootchooser.c
index 6c324fb155e4..bc7c47ec87ae 100644
--- a/common/bootchooser.c
+++ b/common/bootchooser.c
@@ -927,6 +927,10 @@ static int bootchooser_add_entry(struct bootentries *entries, const char *name)
 	return 1;
 }
 
+static struct bootentry_provider bootchooser_entry_provider = {
+	.generate = bootchooser_add_entry,
+};
+
 static const char * const reset_attempts_names[] = {
 	[RESET_ATTEMPTS_POWER_ON] = "power-on",
 	[RESET_ATTEMPTS_ALL_ZERO] = "all-zero",
@@ -953,7 +957,7 @@ static int bootchooser_init(void)
 	globalvar_add_simple_bitmask("bootchooser.reset_priorities", &reset_priorities,
 				  reset_priorities_names, ARRAY_SIZE(reset_priorities_names));
 
-	bootentry_register_provider(bootchooser_add_entry);
+	bootentry_register_provider(&bootchooser_entry_provider);
 
 	return 0;
 }
diff --git a/include/boot.h b/include/boot.h
index 53ad1360a5f3..8afbee6549c6 100644
--- a/include/boot.h
+++ b/include/boot.h
@@ -37,7 +37,13 @@ struct bootentry {
 
 int bootentries_add_entry(struct bootentries *entries, struct bootentry *entry);
 
-int bootentry_register_provider(int (*fn)(struct bootentries *bootentries, const char *name));
+struct bootentry_provider {
+	int (*generate)(struct bootentries *bootentries, const char *name);
+	/* internal fields */
+	struct list_head list;
+};
+
+int bootentry_register_provider(struct bootentry_provider *provider);
 
 #define bootentries_for_each_entry(bootentries, entry) \
 	list_for_each_entry(entry, &bootentries->entries, list)
-- 
2.39.5




^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 02/16] boot: move nfs:// parsing out of bootloader spec code
  2025-04-01 10:47 [PATCH 00/16] boot: implement generic bootsource target Ahmad Fatoum
  2025-04-01 10:47 ` [PATCH 01/16] boot: change bootentry_register_provider to take struct argument Ahmad Fatoum
@ 2025-04-01 10:47 ` Ahmad Fatoum
  2025-04-01 10:47 ` [PATCH 03/16] blspec: remove unused blspec_scan_devices Ahmad Fatoum
                   ` (13 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Ahmad Fatoum @ 2025-04-01 10:47 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum

There's nothing bootloader spec specific about the current handling of
nfs:// URIs. Move it out of blspec to simplify it and allow its reuse by
other bootentry providers as well.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 common/blspec.c | 118 +-----------------------------------------------
 common/boot.c   | 116 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 118 insertions(+), 116 deletions(-)

diff --git a/common/blspec.c b/common/blspec.c
index 27ac6560b97b..740726a571d2 100644
--- a/common/blspec.c
+++ b/common/blspec.c
@@ -16,7 +16,6 @@
 #include <init.h>
 #include <bootm.h>
 #include <glob.h>
-#include <net.h>
 #include <fs.h>
 #include <of.h>
 #include <linux/stat.h>
@@ -298,111 +297,6 @@ static int blspec_have_entry(struct bootentries *bootentries, const char *path)
 	return 0;
 }
 
-/*
- * nfs_find_mountpath - Check if a given url is already mounted
- */
-static const char *nfs_find_mountpath(const char *nfshostpath)
-{
-	struct fs_device *fsdev;
-
-	for_each_fs_device(fsdev) {
-		if (fsdev->backingstore && !strcmp(fsdev->backingstore, nfshostpath))
-			return fsdev->path;
-	}
-
-	return NULL;
-}
-
-/*
- * parse_nfs_url - check for nfs:// style url
- *
- * Check if the passed string is a NFS url and if yes, mount the
- * NFS and return the path we have mounted to.
- */
-static char *parse_nfs_url(const char *url)
-{
-	char *sep, *str, *host, *port, *path;
-	char *mountpath = NULL, *hostpath = NULL, *options = NULL;
-	const char *prevpath;
-	IPaddr_t ip;
-	int ret;
-
-	if (!IS_ENABLED(CONFIG_FS_NFS))
-		return NULL;
-
-	if (strncmp(url, "nfs://", 6))
-		return NULL;
-
-	url += 6;
-
-	str = xstrdup(url);
-
-	host = str;
-
-	sep = strchr(str, '/');
-	if (!sep) {
-		ret = -EINVAL;
-		goto out;
-	}
-
-	*sep++ = 0;
-
-	path = sep;
-
-	port = strchr(host, ':');
-	if (port)
-		*port++ = 0;
-
-	ret = ifup_all(0);
-	if (ret) {
-		pr_err("Failed to bring up networking\n");
-		goto out;
-	}
-
-	ret = resolv(host, &ip);
-	if (ret) {
-		pr_err("Cannot resolve \"%s\": %s\n", host, strerror(-ret));
-		goto out;
-	}
-
-	hostpath = basprintf("%pI4:%s", &ip, path);
-
-	prevpath = nfs_find_mountpath(hostpath);
-
-	if (prevpath) {
-		mountpath = xstrdup(prevpath);
-	} else {
-		mountpath = basprintf("/mnt/nfs-%s-bootentries-%08x", host,
-					rand());
-		if (port)
-			options = basprintf("mountport=%s,port=%s", port,
-					      port);
-
-		ret = make_directory(mountpath);
-		if (ret)
-			goto out;
-
-		pr_debug("host: %s port: %s path: %s\n", host, port, path);
-		pr_debug("hostpath: %s mountpath: %s options: %s\n", hostpath, mountpath, options);
-
-		ret = mount(hostpath, "nfs", mountpath, options);
-		if (ret)
-			goto out;
-	}
-
-	ret = 0;
-
-out:
-	free(str);
-	free(hostpath);
-	free(options);
-
-	if (ret)
-		free(mountpath);
-
-	return ret ? NULL : mountpath;
-}
-
 /*
  * entry_is_of_compatible - check if a bootspec entry is compatible with
  *                          the current machine.
@@ -798,15 +692,10 @@ static int blspec_bootentry_generate(struct bootentries *bootentries,
 	if (ret > 0)
 		found += ret;
 
-	if (*name == '/' || !strncmp(name, "nfs://", 6)) {
-		char *nfspath = parse_nfs_url(name);
-
-		if (nfspath)
-			name = nfspath;
-
+	if (*name == '/') {
 		ret = stat(name, &s);
 		if (ret)
-			goto out;
+			return found;
 
 		if (S_ISDIR(s.st_mode))
 			ret = blspec_scan_directory(bootentries, name);
@@ -814,9 +703,6 @@ static int blspec_bootentry_generate(struct bootentries *bootentries,
 			ret = blspec_scan_file(bootentries, NULL, name);
 		if (ret > 0)
 			found += ret;
-
-out:
-		free(nfspath);
 	}
 
 	return found;
diff --git a/common/boot.c b/common/boot.c
index e3bdfec581c1..bfb2eb13f67f 100644
--- a/common/boot.c
+++ b/common/boot.c
@@ -13,6 +13,9 @@
 #include <init.h>
 #include <menu.h>
 #include <unistd.h>
+#include <libfile.h>
+#include <net.h>
+#include <fs.h>
 
 #include <linux/stat.h>
 
@@ -273,6 +276,112 @@ int bootentry_register_provider(struct bootentry_provider *p)
 	return 0;
 }
 
+/*
+ * nfs_find_mountpath - Check if a given url is already mounted
+ */
+static const char *nfs_find_mountpath(const char *nfshostpath)
+{
+	struct fs_device *fsdev;
+
+	for_each_fs_device(fsdev) {
+		if (fsdev->backingstore && !strcmp(fsdev->backingstore, nfshostpath))
+			return fsdev->path;
+	}
+
+	return NULL;
+}
+
+/*
+ * parse_nfs_url - check for nfs:// style url
+ *
+ * Check if the passed string is a NFS url and if yes, mount the
+ * NFS and return the path we have mounted to.
+ */
+static char *parse_nfs_url(const char *url)
+{
+	char *sep, *str, *host, *port, *path;
+	char *mountpath = NULL, *hostpath = NULL, *options = NULL;
+	const char *prevpath;
+	IPaddr_t ip;
+	int ret;
+
+	if (!IS_ENABLED(CONFIG_FS_NFS))
+		return NULL;
+
+	if (strncmp(url, "nfs://", 6))
+		return NULL;
+
+	url += 6;
+
+	str = xstrdup(url);
+
+	host = str;
+
+	sep = strchr(str, '/');
+	if (!sep) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	*sep++ = 0;
+
+	path = sep;
+
+	port = strchr(host, ':');
+	if (port)
+		*port++ = 0;
+
+	ret = ifup_all(0);
+	if (ret) {
+		pr_err("Failed to bring up networking\n");
+		goto out;
+	}
+
+	ret = resolv(host, &ip);
+	if (ret) {
+		pr_err("Cannot resolve \"%s\": %s\n", host, strerror(-ret));
+		goto out;
+	}
+
+	hostpath = basprintf("%pI4:%s", &ip, path);
+
+	prevpath = nfs_find_mountpath(hostpath);
+
+	if (prevpath) {
+		mountpath = xstrdup(prevpath);
+	} else {
+		mountpath = basprintf("/mnt/nfs-%s-bootentries-%08x", host,
+					rand());
+		if (port)
+			options = basprintf("mountport=%s,port=%s", port,
+					      port);
+
+		ret = make_directory(mountpath);
+		if (ret)
+			goto out;
+
+		pr_debug("host: %s port: %s path: %s\n", host, port, path);
+		pr_debug("hostpath: %s mountpath: %s options: %s\n", hostpath, mountpath, options);
+
+		ret = mount(hostpath, "nfs", mountpath, options);
+		if (ret)
+			goto out;
+	}
+
+	ret = 0;
+
+out:
+	free(str);
+	free(hostpath);
+	free(options);
+
+	if (ret)
+		free(mountpath);
+
+	return ret ? NULL : mountpath;
+}
+
+
 /*
  * bootentry_create_from_name - create boot entries from a name
  *
@@ -293,6 +402,11 @@ int bootentry_create_from_name(struct bootentries *bootentries,
 {
 	struct bootentry_provider *p;
 	int found = 0, ret;
+	char *nfspath;
+
+	nfspath = parse_nfs_url(name);
+	if (nfspath)
+		name = nfspath;
 
 	list_for_each_entry(p, &bootentry_providers, list) {
 		ret = p->generate(bootentries, name);
@@ -300,6 +414,8 @@ int bootentry_create_from_name(struct bootentries *bootentries,
 			found += ret;
 	}
 
+	free(nfspath);
+
 	if (IS_ENABLED(CONFIG_COMMAND_SUPPORT) && !found) {
 		const char *path;
 
-- 
2.39.5




^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 03/16] blspec: remove unused blspec_scan_devices
  2025-04-01 10:47 [PATCH 00/16] boot: implement generic bootsource target Ahmad Fatoum
  2025-04-01 10:47 ` [PATCH 01/16] boot: change bootentry_register_provider to take struct argument Ahmad Fatoum
  2025-04-01 10:47 ` [PATCH 02/16] boot: move nfs:// parsing out of bootloader spec code Ahmad Fatoum
@ 2025-04-01 10:47 ` Ahmad Fatoum
  2025-04-01 10:47 ` [PATCH 04/16] blspec: don't export blspec functions Ahmad Fatoum
                   ` (12 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Ahmad Fatoum @ 2025-04-01 10:47 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum

The function is called nowhere and removing it simplifies the
incoming refactoring of the blspec code.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 common/blspec.c  | 29 -----------------------------
 include/blspec.h |  2 --
 2 files changed, 31 deletions(-)

diff --git a/common/blspec.c b/common/blspec.c
index 740726a571d2..c4e65906ad9f 100644
--- a/common/blspec.c
+++ b/common/blspec.c
@@ -557,35 +557,6 @@ static int blspec_scan_cdev(struct bootentries *bootentries, struct cdev *cdev)
 	return found;
 }
 
-/*
- * blspec_scan_devices - scan all devices for child cdevs
- *
- * Iterate over all devices and collect child their cdevs.
- * Returns the number of entries found or a negative error code if some unexpected
- * error occurred.
- */
-int blspec_scan_devices(struct bootentries *bootentries)
-{
-	struct device *dev;
-	struct block_device *bdev;
-	int ret, found = 0;
-
-	for_each_device(dev)
-		device_detect(dev);
-
-	for_each_block_device(bdev) {
-		struct cdev *cdev;
-
-		list_for_each_entry(cdev, &bdev->dev->cdevs, devices_list) {
-			ret = blspec_scan_cdev(bootentries, cdev);
-			if (ret > 0)
-				found += ret;
-		}
-	}
-
-	return found;
-}
-
 /*
  * blspec_scan_device - scan a device for child cdevs
  *
diff --git a/include/blspec.h b/include/blspec.h
index affcea9a0ad5..cebc7a648703 100644
--- a/include/blspec.h
+++ b/include/blspec.h
@@ -18,8 +18,6 @@ int blspec_entry_var_set(struct blspec_entry *entry, const char *name,
 		const char *val);
 const char *blspec_entry_var_get(struct blspec_entry *entry, const char *name);
 
-int blspec_scan_devices(struct bootentries *bootentries);
-
 int blspec_scan_device(struct bootentries *bootentries, struct device *dev);
 int blspec_scan_devicename(struct bootentries *bootentries, const char *devname);
 int blspec_scan_directory(struct bootentries *bootentries, const char *root);
-- 
2.39.5




^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 04/16] blspec: don't export blspec functions
  2025-04-01 10:47 [PATCH 00/16] boot: implement generic bootsource target Ahmad Fatoum
                   ` (2 preceding siblings ...)
  2025-04-01 10:47 ` [PATCH 03/16] blspec: remove unused blspec_scan_devices Ahmad Fatoum
@ 2025-04-01 10:47 ` Ahmad Fatoum
  2025-04-01 10:47 ` [PATCH 05/16] blspec: factor out generic parts into bootscan helper Ahmad Fatoum
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Ahmad Fatoum @ 2025-04-01 10:47 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum

All of these functions are used only internally and need not be visible
externally.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 common/blspec.c  | 52 +++++++++++++++++++++++++++++-------------------
 include/blspec.h | 27 -------------------------
 2 files changed, 32 insertions(+), 47 deletions(-)
 delete mode 100644 include/blspec.h

diff --git a/common/blspec.c b/common/blspec.c
index c4e65906ad9f..d2db9f0db9fa 100644
--- a/common/blspec.c
+++ b/common/blspec.c
@@ -7,7 +7,6 @@
 #include <readkey.h>
 #include <common.h>
 #include <driver.h>
-#include <blspec.h>
 #include <malloc.h>
 #include <block.h>
 #include <fcntl.h>
@@ -19,13 +18,39 @@
 #include <fs.h>
 #include <of.h>
 #include <linux/stat.h>
+#include <linux/list.h>
 #include <linux/err.h>
 #include <mtd/ubi-user.h>
+#include <boot.h>
+
+struct blspec_entry {
+	struct bootentry entry;
+
+	struct device_node *node;
+	struct cdev *cdev;
+	const char *rootpath;
+	const char *configpath;
+};
+
+static int blspec_scan_device(struct bootentries *bootentries, struct device *dev);
+
+/*
+ * blspec_entry_var_get - get the value of a variable
+ */
+static const char *blspec_entry_var_get(struct blspec_entry *entry, const char *name)
+{
+	const char *str;
+	int ret;
+
+	ret = of_property_read_string(entry->node, name, &str);
+
+	return ret ? NULL : str;
+}
 
 /*
  * blspec_entry_var_set - set a variable to a value
  */
-int blspec_entry_var_set(struct blspec_entry *entry, const char *name,
+static int blspec_entry_var_set(struct blspec_entry *entry, const char *name,
 		const char *val)
 {
 	return of_set_property(entry->node, name, val,
@@ -154,19 +179,6 @@ static int blspec_boot(struct bootentry *be, int verbose, int dryrun)
 	return ret;
 }
 
-/*
- * blspec_entry_var_get - get the value of a variable
- */
-const char *blspec_entry_var_get(struct blspec_entry *entry, const char *name)
-{
-	const char *str;
-	int ret;
-
-	ret = of_property_read_string(entry->node, name, &str);
-
-	return ret ? NULL : str;
-}
-
 static void blspec_entry_free(struct bootentry *be)
 {
 	struct blspec_entry *entry = container_of(be, struct blspec_entry, entry);
@@ -384,8 +396,8 @@ static bool entry_is_match_machine_id(struct blspec_entry *entry)
 	return ret;
 }
 
-int blspec_scan_file(struct bootentries *bootentries, const char *root,
-		     const char *configname)
+static int blspec_scan_file(struct bootentries *bootentries, const char *root,
+			    const char *configname)
 {
 	char *devname = NULL, *hwdevname = NULL;
 	struct blspec_entry *entry;
@@ -440,7 +452,7 @@ int blspec_scan_file(struct bootentries *bootentries, const char *root,
  *
  * returns the number of entries found or a negative error value otherwise.
  */
-int blspec_scan_directory(struct bootentries *bootentries, const char *root)
+static int blspec_scan_directory(struct bootentries *bootentries, const char *root)
 {
 	glob_t globb;
 	char *abspath;
@@ -565,7 +577,7 @@ static int blspec_scan_cdev(struct bootentries *bootentries, struct cdev *cdev)
  * Returns the number of entries found or a negative error code if some unexpected
  * error occurred.
  */
-int blspec_scan_device(struct bootentries *bootentries, struct device *dev)
+static int blspec_scan_device(struct bootentries *bootentries, struct device *dev)
 {
 	struct device *child;
 	struct cdev *cdev;
@@ -627,7 +639,7 @@ int blspec_scan_device(struct bootentries *bootentries, struct device *dev)
  * Returns the number of entries found or a negative error code if some unexpected
  * error occurred.
  */
-int blspec_scan_devicename(struct bootentries *bootentries, const char *devname)
+static int blspec_scan_devicename(struct bootentries *bootentries, const char *devname)
 {
 	struct device *dev;
 	struct cdev *cdev;
diff --git a/include/blspec.h b/include/blspec.h
deleted file mode 100644
index cebc7a648703..000000000000
--- a/include/blspec.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-#ifndef __LOADER_H__
-#define __LOADER_H__
-
-#include <linux/list.h>
-#include <boot.h>
-
-struct blspec_entry {
-	struct bootentry entry;
-
-	struct device_node *node;
-	struct cdev *cdev;
-	const char *rootpath;
-	const char *configpath;
-};
-
-int blspec_entry_var_set(struct blspec_entry *entry, const char *name,
-		const char *val);
-const char *blspec_entry_var_get(struct blspec_entry *entry, const char *name);
-
-int blspec_scan_device(struct bootentries *bootentries, struct device *dev);
-int blspec_scan_devicename(struct bootentries *bootentries, const char *devname);
-int blspec_scan_directory(struct bootentries *bootentries, const char *root);
-int blspec_scan_file(struct bootentries *bootentries, const char *root,
-		     const char *configname);
-
-#endif /* __LOADER_H__ */
-- 
2.39.5




^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 05/16] blspec: factor out generic parts into bootscan helper
  2025-04-01 10:47 [PATCH 00/16] boot: implement generic bootsource target Ahmad Fatoum
                   ` (3 preceding siblings ...)
  2025-04-01 10:47 ` [PATCH 04/16] blspec: don't export blspec functions Ahmad Fatoum
@ 2025-04-01 10:47 ` Ahmad Fatoum
  2025-04-01 10:47 ` [PATCH 06/16] common: bootscan: add scan_disk callback Ahmad Fatoum
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Ahmad Fatoum @ 2025-04-01 10:47 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum

Other boot entry providers (like incoming ESP provider) would share much
code with the blspec driver. Factor out the common parts into a separate
bootscannr functionality, so bootspec need only implement a couple of
callbacks.

No functional change.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 common/Makefile    |   2 +-
 common/blspec.c    | 222 +++++++++++++--------------------------------
 common/bootscan.c  | 168 ++++++++++++++++++++++++++++++++++
 include/bootscan.h |  31 +++++++
 4 files changed, 261 insertions(+), 162 deletions(-)
 create mode 100644 common/bootscan.c
 create mode 100644 include/bootscan.h

diff --git a/common/Makefile b/common/Makefile
index 4a8dc1ff0613..0e9648378d8c 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -78,7 +78,7 @@ obj-y				+= file-list.o
 obj-$(CONFIG_FIRMWARE)		+= firmware.o
 obj-$(CONFIG_UBIFORMAT)		+= ubiformat.o
 obj-$(CONFIG_BAREBOX_UPDATE_IMX_NAND_FCB) += imx-bbu-nand-fcb.o
-obj-$(CONFIG_BOOT)		+= boot.o
+obj-$(CONFIG_BOOT)		+= boot.o bootscan.o
 obj-$(CONFIG_SERIAL_DEV_BUS)	+= serdev.o
 obj-$(CONFIG_USB_GADGET)	+= usbgadget.o
 obj-pbl-$(CONFIG_HAVE_OPTEE)	+= optee.o
diff --git a/common/blspec.c b/common/blspec.c
index d2db9f0db9fa..b58efc06338b 100644
--- a/common/blspec.c
+++ b/common/blspec.c
@@ -4,11 +4,7 @@
 #include <environment.h>
 #include <globalvar.h>
 #include <firmware.h>
-#include <readkey.h>
-#include <common.h>
-#include <driver.h>
 #include <malloc.h>
-#include <block.h>
 #include <fcntl.h>
 #include <libfile.h>
 #include <libbb.h>
@@ -20,9 +16,10 @@
 #include <linux/stat.h>
 #include <linux/list.h>
 #include <linux/err.h>
-#include <mtd/ubi-user.h>
 #include <boot.h>
 
+#include <bootscan.h>
+
 struct blspec_entry {
 	struct bootentry entry;
 
@@ -32,8 +29,6 @@ struct blspec_entry {
 	const char *configpath;
 };
 
-static int blspec_scan_device(struct bootentries *bootentries, struct device *dev);
-
 /*
  * blspec_entry_var_get - get the value of a variable
  */
@@ -396,8 +391,8 @@ static bool entry_is_match_machine_id(struct blspec_entry *entry)
 	return ret;
 }
 
-static int blspec_scan_file(struct bootentries *bootentries, const char *root,
-			    const char *configname)
+static int __blspec_scan_file(struct bootentries *bootentries, const char *root,
+			      const char *configname)
 {
 	char *devname = NULL, *hwdevname = NULL;
 	struct blspec_entry *entry;
@@ -445,6 +440,16 @@ static int blspec_scan_file(struct bootentries *bootentries, const char *root,
 	return 1;
 }
 
+static int blspec_scan_file(struct bootscanner *scanner,
+			    struct bootentries *bootentries,
+			    const char *configname)
+{
+	if (!strends(configname, ".conf"))
+		return 0;
+
+	return __blspec_scan_file(bootentries, NULL, configname);
+}
+
 /*
  * blspec_scan_directory - scan over a directory
  *
@@ -452,7 +457,8 @@ static int blspec_scan_file(struct bootentries *bootentries, const char *root,
  *
  * returns the number of entries found or a negative error value otherwise.
  */
-static int blspec_scan_directory(struct bootentries *bootentries, const char *root)
+static int blspec_scan_directory(struct bootscanner *bootscanner,
+				 struct bootentries *bootentries, const char *root)
 {
 	glob_t globb;
 	char *abspath;
@@ -479,7 +485,7 @@ static int blspec_scan_directory(struct bootentries *bootentries, const char *ro
 		if (ret || !S_ISREG(s.st_mode))
 			continue;
 
-		ret = blspec_scan_file(bootentries, root, configname);
+		ret = __blspec_scan_file(bootentries, root, configname);
 		if (ret > 0)
 			found += ret;
 	}
@@ -493,108 +499,20 @@ static int blspec_scan_directory(struct bootentries *bootentries, const char *ro
 	return ret;
 }
 
-/*
- * blspec_scan_ubi - scan over a cdev containing UBI volumes
- *
- * This function attaches a cdev as UBI devices and collects all bootentries
- * entries found in the UBI volumes
- *
- * returns the number of entries found or a negative error code if some unexpected
- * error occurred.
- */
-static int blspec_scan_ubi(struct bootentries *bootentries, struct cdev *cdev)
+static int blspec_scan_disk(struct bootscanner *scanner,
+			    struct bootentries *bootentries, struct cdev *cdev)
 {
-	struct device *child;
-	int ret, found = 0;
+	struct cdev *partcdev;
+	int ret;
 
-	pr_debug("%s: %s\n", __func__, cdev->name);
-
-	ret = ubi_attach_mtd_dev(cdev->mtd, UBI_DEV_NUM_AUTO, 0, 20);
-	if (ret && ret != -EEXIST)
-		return 0;
-
-	device_for_each_child(cdev->dev, child) {
-		ret = blspec_scan_device(bootentries, child);
-		if (ret > 0)
-			found += ret;
-	}
-
-	return found;
-}
-
-/*
- * blspec_scan_cdev - scan over a cdev
- *
- * Given a cdev this function mounts the filesystem and collects all bootentries
- * entries found under /bootentries/entries/.
- *
- * returns the number of entries found or a negative error code if some unexpected
- * error occurred.
- */
-static int blspec_scan_cdev(struct bootentries *bootentries, struct cdev *cdev)
-{
-	int ret, found = 0;
-	void *buf = xzalloc(512);
-	enum filetype type, filetype;
-	const char *rootpath;
-
-	pr_debug("%s: %s\n", __func__, cdev->name);
-
-	ret = cdev_read(cdev, buf, 512, 0, 0);
-	if (ret < 0) {
-		free(buf);
-		return ret;
-	}
-
-	type = file_detect_partition_table(buf, 512);
-	filetype = file_detect_type(buf, 512);
-	free(buf);
-
-	if (type == filetype_mbr || type == filetype_gpt)
-		return -EINVAL;
-
-	if (filetype == filetype_ubi && IS_ENABLED(CONFIG_MTD_UBI)) {
-		ret = blspec_scan_ubi(bootentries, cdev);
-		if (ret > 0)
-			found += ret;
-	}
-
-	rootpath = cdev_mount(cdev);
-	if (!IS_ERR(rootpath)) {
-		ret = blspec_scan_directory(bootentries, rootpath);
-		if (ret > 0)
-			found += ret;
-	}
-
-	return found;
-}
-
-/*
- * blspec_scan_device - scan a device for child cdevs
- *
- * Given a device this functions scans over all child cdevs looking
- * for bootentries entries.
- * Returns the number of entries found or a negative error code if some unexpected
- * error occurred.
- */
-static int blspec_scan_device(struct bootentries *bootentries, struct device *dev)
-{
-	struct device *child;
-	struct cdev *cdev;
-	int ret, found = 0;
-
-	pr_debug("%s: %s\n", __func__, dev_name(dev));
-
-	device_detect(dev);
-
-	list_for_each_entry(cdev, &dev->cdevs, devices_list) {
+	for_each_cdev_partition(partcdev, cdev) {
 		/*
 		 * If the OS is installed on a disk with MBR disk label, and a
 		 * partition with the MBR type id of 0xEA already exists it
 		 * should be used as $BOOT
 		 */
 		if (cdev_is_mbr_partitioned(cdev->master) && cdev->dos_partition_type == 0xea) {
-			ret = blspec_scan_cdev(bootentries, cdev);
+			ret = boot_scan_cdev(scanner, bootentries, cdev);
 			if (ret == 0)
 				ret = -ENOENT;
 
@@ -611,9 +529,38 @@ static int blspec_scan_device(struct bootentries *bootentries, struct device *de
 		 */
 	}
 
+	return 0;
+}
+
+/*
+ * blspec_scan_device - scan a device for child cdevs
+ *
+ * Given a device this functions scans over all child cdevs looking
+ * for bootentries entries.
+ * Returns the number of entries found or a negative error code if some unexpected
+ * error occurred.
+ */
+static int blspec_scan_device(struct bootscanner *scanner,
+			      struct bootentries *bootentries, struct device *dev)
+{
+	struct device *child;
+	struct cdev *cdev;
+	int ret, found = 0;
+
+	pr_debug("%s: %s\n", __func__, dev_name(dev));
+
+	list_for_each_entry(cdev, &dev->cdevs, devices_list) {
+		if (cdev_is_partition(cdev))
+			continue;
+
+		ret = blspec_scan_disk(scanner, bootentries, cdev);
+		if (ret)
+			return ret;
+	}
+
 	/* Try child devices */
 	device_for_each_child(dev, child) {
-		ret = blspec_scan_device(bootentries, child);
+		ret = blspec_scan_device(scanner, bootentries, child);
 		if (ret > 0)
 			return ret;
 	}
@@ -623,7 +570,7 @@ static int blspec_scan_device(struct bootentries *bootentries, struct device *de
 	 * by the bootblspec spec).
 	 */
 	list_for_each_entry(cdev, &dev->cdevs, devices_list) {
-		ret = blspec_scan_cdev(bootentries, cdev);
+		ret = boot_scan_cdev(scanner, bootentries, cdev);
 		if (ret > 0)
 			found += ret;
 	}
@@ -631,64 +578,17 @@ static int blspec_scan_device(struct bootentries *bootentries, struct device *de
 	return found;
 }
 
-/*
- * blspec_scan_devicename - scan a hardware device for child cdevs
- *
- * Given a name of a hardware device this functions scans over all child
- * cdevs looking for bootentries entries.
- * Returns the number of entries found or a negative error code if some unexpected
- * error occurred.
- */
-static int blspec_scan_devicename(struct bootentries *bootentries, const char *devname)
-{
-	struct device *dev;
-	struct cdev *cdev;
-
-	pr_debug("%s: %s\n", __func__, devname);
-
-	/* Support both boot /dev/disk0.rootfs and boot disk0.rootfs */
-	devname += str_has_prefix(devname, "/dev/");
-
-	device_detect_by_name(devname);
-
-	cdev = cdev_by_name(devname);
-	if (cdev) {
-		int ret = blspec_scan_cdev(bootentries, cdev);
-		if (ret > 0)
-			return ret;
-	}
-
-	dev = get_device_by_name(devname);
-	if (!dev)
-		return -ENODEV;
-
-	return blspec_scan_device(bootentries, dev);
-}
+static struct bootscanner blspec_scanner = {
+	.name		= "blspec",
+	.scan_file	= blspec_scan_file,
+	.scan_directory	= blspec_scan_directory,
+	.scan_device	= blspec_scan_device,
+};
 
 static int blspec_bootentry_generate(struct bootentries *bootentries,
 				     const char *name)
 {
-	struct stat s;
-	int ret, found = 0;
-
-	ret = blspec_scan_devicename(bootentries, name);
-	if (ret > 0)
-		found += ret;
-
-	if (*name == '/') {
-		ret = stat(name, &s);
-		if (ret)
-			return found;
-
-		if (S_ISDIR(s.st_mode))
-			ret = blspec_scan_directory(bootentries, name);
-		else if (S_ISREG(s.st_mode) && strends(name, ".conf"))
-			ret = blspec_scan_file(bootentries, NULL, name);
-		if (ret > 0)
-			found += ret;
-	}
-
-	return found;
+	return bootentry_scan_generate(&blspec_scanner, bootentries, name);
 }
 
 static struct bootentry_provider blspec_bootentry_provider = {
diff --git a/common/bootscan.c b/common/bootscan.c
new file mode 100644
index 000000000000..cc25f070508a
--- /dev/null
+++ b/common/bootscan.c
@@ -0,0 +1,168 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+#define pr_fmt(fmt)  "bootscan: " fmt
+
+#include <driver.h>
+#include <xfuncs.h>
+#include <block.h>
+#include <fs.h>
+#include <linux/stat.h>
+#include <linux/err.h>
+#include <mtd/ubi-user.h>
+
+#include <bootscan.h>
+
+static int boot_scan_device(struct bootscanner *scanner,
+			    struct bootentries *bootentries, struct device *dev)
+{
+
+	pr_debug("%s(%s): %s\n", __func__, scanner->name, dev_name(dev));
+
+	device_detect(dev);
+	return scanner->scan_device(scanner, bootentries, dev);
+}
+
+/*
+ * boot_scan_ubi - scan over a cdev containing UBI volumes
+ *
+ * This function attaches a cdev as UBI devices and collects all bootentries
+ * entries found in the UBI volumes
+ *
+ * returns the number of entries found or a negative error code if some unexpected
+ * error occurred.
+ */
+static int boot_scan_ubi(struct bootscanner *scanner,
+			 struct bootentries *bootentries, struct cdev *cdev)
+{
+	struct device *child;
+	int ret, found = 0;
+
+	pr_debug("%s(%s): %s\n", __func__, scanner->name, cdev->name);
+
+	if (!scanner->scan_device)
+		return 0;
+
+	ret = ubi_attach_mtd_dev(cdev->mtd, UBI_DEV_NUM_AUTO, 0, 20);
+	if (ret && ret != -EEXIST)
+		return 0;
+
+	device_for_each_child(cdev->dev, child) {
+		ret = boot_scan_device(scanner, bootentries, child);
+		if (ret > 0)
+			found += ret;
+	}
+
+	return found;
+}
+
+/*
+ * boot_scan_cdev - scan over a cdev
+ *
+ * Given a cdev this function mounts the filesystem and collects all bootentries
+ * entries found in it.
+ *
+ * returns the number of entries found or a negative error code if some unexpected
+ * error occurred.
+ */
+int boot_scan_cdev(struct bootscanner *scanner,
+		   struct bootentries *bootentries, struct cdev *cdev)
+{
+	int ret, found = 0;
+	void *buf = xzalloc(512);
+	enum filetype type, filetype;
+	const char *rootpath;
+
+	pr_debug("%s(%s): %s\n", __func__, scanner->name, cdev->name);
+
+	ret = cdev_read(cdev, buf, 512, 0, 0);
+	if (ret < 0) {
+		free(buf);
+		return ret;
+	}
+
+	type = file_detect_partition_table(buf, 512);
+	filetype = file_detect_type(buf, 512);
+	free(buf);
+
+	if (type == filetype_mbr || type == filetype_gpt)
+		return -EINVAL;
+
+	if (filetype == filetype_ubi && IS_ENABLED(CONFIG_MTD_UBI)) {
+		ret = boot_scan_ubi(scanner, bootentries, cdev);
+		if (ret > 0)
+			found += ret;
+	}
+
+	rootpath = cdev_mount(cdev);
+	if (!IS_ERR(rootpath) && scanner->scan_directory) {
+		ret = scanner->scan_directory(scanner, bootentries, rootpath);
+		if (ret > 0)
+			found += ret;
+	}
+
+	return found;
+}
+
+/*
+ * boot_scan_devicename - scan a hardware device for child cdevs
+ *
+ * Given a name of a hardware device this functions scans over all child
+ * cdevs looking for bootentries entries.
+ * Returns the number of entries found or a negative error code if some unexpected
+ * error occurred.
+ */
+static int boot_scan_devicename(struct bootscanner *scanner,
+				struct bootentries *bootentries, const char *devname)
+{
+	struct device *dev;
+	struct cdev *cdev;
+
+	pr_debug("%s(%s): %s\n", __func__, scanner->name, devname);
+
+	/* Support both boot /dev/disk0.rootfs and boot disk0.rootfs */
+	devname += str_has_prefix(devname, "/dev/");
+
+	device_detect_by_name(devname);
+
+	cdev = cdev_by_name(devname);
+	if (cdev) {
+		int ret = boot_scan_cdev(scanner, bootentries, cdev);
+		if (ret > 0)
+			return ret;
+	}
+
+	if (!scanner->scan_device)
+		return 0;
+
+	dev = get_device_by_name(devname);
+	if (!dev)
+		return -ENODEV;
+
+	return boot_scan_device(scanner, bootentries, dev);
+}
+
+int bootentry_scan_generate(struct bootscanner *scanner,
+			    struct bootentries *bootentries,
+			    const char *name)
+{
+	struct stat s;
+	int ret, found = 0;
+
+	ret = boot_scan_devicename(scanner, bootentries, name);
+	if (ret > 0)
+		found += ret;
+
+	if (*name == '/') {
+		ret = stat(name, &s);
+		if (ret)
+			return found;
+
+		if (S_ISDIR(s.st_mode) && scanner->scan_directory)
+			ret = scanner->scan_directory(scanner, bootentries, name);
+		else if (S_ISREG(s.st_mode) && scanner->scan_file)
+			ret = scanner->scan_file(scanner, bootentries, name);
+		if (ret > 0)
+			found += ret;
+	}
+
+	return found;
+}
diff --git a/include/bootscan.h b/include/bootscan.h
new file mode 100644
index 000000000000..3161896faf07
--- /dev/null
+++ b/include/bootscan.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef __BOOTSCAN_H
+#define __BOOTSCAN_H
+
+struct bootentries;
+struct device;
+struct cdev;
+
+struct bootscanner {
+	/** For debugging output */
+	const char *name;
+
+	/** Invoked for when scanning a file */
+	int (*scan_file)(struct bootscanner *,
+			 struct bootentries *, const char *);
+	/** Invoked for when scanning a directory */
+	int (*scan_directory)(struct bootscanner *,
+			      struct bootentries *, const char *);
+	/** Fallback: Invoked only when none of the above returned results */
+	int (*scan_device)(struct bootscanner *,
+			   struct bootentries *, struct device *);
+};
+
+int boot_scan_cdev(struct bootscanner *scanner,
+		   struct bootentries *bootentries, struct cdev *cdev);
+
+int bootentry_scan_generate(struct bootscanner *scanner,
+			    struct bootentries *bootentries,
+			    const char *name);
+
+#endif
-- 
2.39.5




^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 06/16] common: bootscan: add scan_disk callback
  2025-04-01 10:47 [PATCH 00/16] boot: implement generic bootsource target Ahmad Fatoum
                   ` (4 preceding siblings ...)
  2025-04-01 10:47 ` [PATCH 05/16] blspec: factor out generic parts into bootscan helper Ahmad Fatoum
@ 2025-04-01 10:47 ` Ahmad Fatoum
  2025-04-01 10:47 ` [PATCH 07/16] blspec: support boot /dev/virtioblkX Ahmad Fatoum
                   ` (9 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Ahmad Fatoum @ 2025-04-01 10:47 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum

The scan_disk callback will be invoked for every disk and makes
implementing logic easier, where a bootscanner wants to process specific
partitions by type for example.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 common/bootscan.c  | 25 ++++++++++++++++++++++---
 include/bootscan.h |  3 +++
 2 files changed, 25 insertions(+), 3 deletions(-)

diff --git a/common/bootscan.c b/common/bootscan.c
index cc25f070508a..222498c609a4 100644
--- a/common/bootscan.c
+++ b/common/bootscan.c
@@ -14,10 +14,26 @@
 static int boot_scan_device(struct bootscanner *scanner,
 			    struct bootentries *bootentries, struct device *dev)
 {
+	struct cdev *cdev;
+	int ret;
 
 	pr_debug("%s(%s): %s\n", __func__, scanner->name, dev_name(dev));
 
 	device_detect(dev);
+
+	if (!scanner->scan_disk)
+		goto scan_device;
+
+	list_for_each_entry(cdev, &dev->cdevs, devices_list) {
+		if (cdev_is_partition(cdev))
+			continue;
+
+		ret = scanner->scan_disk(scanner, bootentries, cdev);
+		if (ret)
+			return ret;
+	}
+
+scan_device:
 	return scanner->scan_device(scanner, bootentries, dev);
 }
 
@@ -38,7 +54,7 @@ static int boot_scan_ubi(struct bootscanner *scanner,
 
 	pr_debug("%s(%s): %s\n", __func__, scanner->name, cdev->name);
 
-	if (!scanner->scan_device)
+	if (!scanner->scan_disk && !scanner->scan_device)
 		return 0;
 
 	ret = ubi_attach_mtd_dev(cdev->mtd, UBI_DEV_NUM_AUTO, 0, 20);
@@ -83,8 +99,11 @@ int boot_scan_cdev(struct bootscanner *scanner,
 	filetype = file_detect_type(buf, 512);
 	free(buf);
 
-	if (type == filetype_mbr || type == filetype_gpt)
-		return -EINVAL;
+	if (type == filetype_mbr || type == filetype_gpt) {
+		if (!scanner->scan_disk || cdev_is_partition(cdev))
+			return -EINVAL;
+		return scanner->scan_disk(scanner, bootentries, cdev);
+	}
 
 	if (filetype == filetype_ubi && IS_ENABLED(CONFIG_MTD_UBI)) {
 		ret = boot_scan_ubi(scanner, bootentries, cdev);
diff --git a/include/bootscan.h b/include/bootscan.h
index 3161896faf07..99094dc09320 100644
--- a/include/bootscan.h
+++ b/include/bootscan.h
@@ -16,6 +16,9 @@ struct bootscanner {
 	/** Invoked for when scanning a directory */
 	int (*scan_directory)(struct bootscanner *,
 			      struct bootentries *, const char *);
+	/** Invoked for when scanning a disk */
+	int (*scan_disk)(struct bootscanner *,
+			 struct bootentries *, struct cdev *);
 	/** Fallback: Invoked only when none of the above returned results */
 	int (*scan_device)(struct bootscanner *,
 			   struct bootentries *, struct device *);
-- 
2.39.5




^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 07/16] blspec: support boot /dev/virtioblkX
  2025-04-01 10:47 [PATCH 00/16] boot: implement generic bootsource target Ahmad Fatoum
                   ` (5 preceding siblings ...)
  2025-04-01 10:47 ` [PATCH 06/16] common: bootscan: add scan_disk callback Ahmad Fatoum
@ 2025-04-01 10:47 ` Ahmad Fatoum
  2025-04-01 10:47 ` [PATCH 08/16] bootm: associate bootm overrides with struct bootentry Ahmad Fatoum
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Ahmad Fatoum @ 2025-04-01 10:47 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum

The device backing /dev/virtioblkX is called virtioY. The way the
bootloader spec code was written this results in the following working:

 - boot -l /dev/virtioblk0.1
 - boot -l virtio0
 - boot -l /mnt/virtioblk0.1

But not:

 - boot -l /dev/virtioblk0

Fix this by implementing the new .scan_disk callback. As scan_device is
just the fallback, remove the blspec_scan_disk call from it.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 common/blspec.c | 10 +---------
 1 file changed, 1 insertion(+), 9 deletions(-)

diff --git a/common/blspec.c b/common/blspec.c
index b58efc06338b..9f25fa63c8e7 100644
--- a/common/blspec.c
+++ b/common/blspec.c
@@ -549,15 +549,6 @@ static int blspec_scan_device(struct bootscanner *scanner,
 
 	pr_debug("%s: %s\n", __func__, dev_name(dev));
 
-	list_for_each_entry(cdev, &dev->cdevs, devices_list) {
-		if (cdev_is_partition(cdev))
-			continue;
-
-		ret = blspec_scan_disk(scanner, bootentries, cdev);
-		if (ret)
-			return ret;
-	}
-
 	/* Try child devices */
 	device_for_each_child(dev, child) {
 		ret = blspec_scan_device(scanner, bootentries, child);
@@ -582,6 +573,7 @@ static struct bootscanner blspec_scanner = {
 	.name		= "blspec",
 	.scan_file	= blspec_scan_file,
 	.scan_directory	= blspec_scan_directory,
+	.scan_disk	= blspec_scan_disk,
 	.scan_device	= blspec_scan_device,
 };
 
-- 
2.39.5




^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 08/16] bootm: associate bootm overrides with struct bootentry
  2025-04-01 10:47 [PATCH 00/16] boot: implement generic bootsource target Ahmad Fatoum
                   ` (6 preceding siblings ...)
  2025-04-01 10:47 ` [PATCH 07/16] blspec: support boot /dev/virtioblkX Ahmad Fatoum
@ 2025-04-01 10:47 ` Ahmad Fatoum
  2025-04-01 10:47 ` [PATCH 09/16] boot: split off bootarg API into new bootargs.h header Ahmad Fatoum
                   ` (7 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Ahmad Fatoum @ 2025-04-01 10:47 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum

The boot override logic is currently controlled by the boot command,
which makes it cumbersome to exercise from custom bootentry providers.

A more natural place would be associating it with the boot entry logic,
so move it there.

No functional change.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 commands/boot.c           | 11 ++---------
 common/boot.c             |  4 ++++
 common/bootm.c            |  3 ++-
 include/boot.h            |  2 ++
 include/bootm-overrides.h | 30 ++++++++++++++++++++++++++++++
 include/bootm.h           | 18 ------------------
 6 files changed, 40 insertions(+), 28 deletions(-)
 create mode 100644 include/bootm-overrides.h

diff --git a/commands/boot.c b/commands/boot.c
index 820708380191..aad01fdc6c95 100644
--- a/commands/boot.c
+++ b/commands/boot.c
@@ -55,11 +55,6 @@ static int boot_add_override(struct bootm_overrides *overrides, char *var)
 	return 0;
 }
 
-static inline bool boot_has_overrides(const struct bootm_overrides *overrides)
-{
-	return overrides->os_file || overrides->oftree_file || overrides->initrd_file;
-}
-
 static int do_boot(int argc, char *argv[])
 {
 	char *freep = NULL;
@@ -128,8 +123,6 @@ static int do_boot(int argc, char *argv[])
 	}
 
 	entries = bootentries_alloc();
-	if (boot_has_overrides(&overrides))
-		bootm_set_overrides(&overrides);
 
 	while ((name = next(&handle)) != NULL) {
 		if (!*name)
@@ -142,6 +135,8 @@ static int do_boot(int argc, char *argv[])
 			continue;
 
 		bootentries_for_each_entry(entries, entry) {
+			bootm_merge_overrides(&entry->overrides, &overrides);
+
 			ret = boot_entry(entry, verbose, dryrun);
 			if (!ret)
 				goto out;
@@ -164,8 +159,6 @@ static int do_boot(int argc, char *argv[])
 
 	ret = 0;
 out:
-	if (boot_has_overrides(&overrides))
-		bootm_unset_overrides();
 	bootentries_free(entries);
 	free(freep);
 
diff --git a/common/boot.c b/common/boot.c
index bfb2eb13f67f..cb16a9a2b508 100644
--- a/common/boot.c
+++ b/common/boot.c
@@ -165,10 +165,14 @@ int boot_entry(struct bootentry *be, int verbose, int dryrun)
 		}
 	}
 
+	bootm_set_overrides(&be->overrides);
+
 	ret = be->boot(be, verbose, dryrun);
 	if (ret && ret != -ENOMEDIUM)
 		pr_err("Booting entry '%s' failed: %pe\n", be->title, ERR_PTR(ret));
 
+	bootm_set_overrides(NULL);
+
 	globalvar_set_match("linux.bootargs.dyn.", "");
 
 	return ret;
diff --git a/common/bootm.c b/common/bootm.c
index fe4d51681d73..6b63987f0900 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -2,6 +2,7 @@
 
 #include <common.h>
 #include <bootm.h>
+#include <bootm-overrides.h>
 #include <fs.h>
 #include <malloc.h>
 #include <memory.h>
@@ -1004,7 +1005,7 @@ int bootm_boot(struct bootm_data *bootm_data)
 #ifdef CONFIG_BOOT_OVERRIDE
 void bootm_set_overrides(const struct bootm_overrides *overrides)
 {
-	bootm_overrides = *overrides;
+	bootm_overrides = overrides ? *overrides : (struct bootm_overrides){};
 }
 #endif
 
diff --git a/include/boot.h b/include/boot.h
index 8afbee6549c6..71da2e2baba8 100644
--- a/include/boot.h
+++ b/include/boot.h
@@ -5,6 +5,7 @@
 #include <of.h>
 #include <menu.h>
 #include <environment.h>
+#include <bootm-overrides.h>
 
 #ifdef CONFIG_FLEXIBLE_BOOTARGS
 const char *linux_bootargs_get(void);
@@ -33,6 +34,7 @@ struct bootentry {
 	char *description;
 	int (*boot)(struct bootentry *entry, int verbose, int dryrun);
 	void (*release)(struct bootentry *entry);
+	struct bootm_overrides overrides;
 };
 
 int bootentries_add_entry(struct bootentries *entries, struct bootentry *entry);
diff --git a/include/bootm-overrides.h b/include/bootm-overrides.h
new file mode 100644
index 000000000000..231c913709e2
--- /dev/null
+++ b/include/bootm-overrides.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef __BOOTM_OVERRIDES_H
+#define __BOOTM_OVERRIDES_H
+
+struct bootm_overrides {
+	const char *os_file;
+	const char *oftree_file;
+	const char *initrd_file;
+};
+
+#ifdef CONFIG_BOOT_OVERRIDE
+void bootm_set_overrides(const struct bootm_overrides *overrides);
+#else
+static inline void bootm_set_overrides(const struct bootm_overrides *overrides) {}
+#endif
+
+static inline void bootm_merge_overrides(struct bootm_overrides *dst,
+					 const struct bootm_overrides *src)
+{
+	if (!IS_ENABLED(CONFIG_BOOT_OVERRIDE))
+		return;
+	if (src->os_file)
+		dst->os_file = src->os_file;
+	if (src->oftree_file)
+		dst->oftree_file = src->oftree_file;
+	if (src->initrd_file)
+		dst->initrd_file = src->initrd_file;
+}
+
+#endif
diff --git a/include/bootm.h b/include/bootm.h
index 0e5e99773a26..b86d06b0f55d 100644
--- a/include/bootm.h
+++ b/include/bootm.h
@@ -160,22 +160,4 @@ void bootm_force_signed_images(void);
 
 void *booti_load_image(struct image_data *data, phys_addr_t *oftree);
 
-struct bootm_overrides {
-	const char *os_file;
-	const char *oftree_file;
-	const char *initrd_file;
-};
-
-#ifdef CONFIG_BOOT_OVERRIDE
-void bootm_set_overrides(const struct bootm_overrides *overrides);
-#else
-static inline void bootm_set_overrides(const struct bootm_overrides *overrides) {}
-#endif
-
-static inline void bootm_unset_overrides(void)
-{
-	struct bootm_overrides overrides = {};
-	bootm_set_overrides(&overrides);
-}
-
 #endif /* __BOOTM_H */
-- 
2.39.5




^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 09/16] boot: split off bootarg API into new bootargs.h header
  2025-04-01 10:47 [PATCH 00/16] boot: implement generic bootsource target Ahmad Fatoum
                   ` (7 preceding siblings ...)
  2025-04-01 10:47 ` [PATCH 08/16] bootm: associate bootm overrides with struct bootentry Ahmad Fatoum
@ 2025-04-01 10:47 ` Ahmad Fatoum
  2025-04-01 10:48 ` [PATCH 10/16] block: add get_rootarg block op into block_device_ops Ahmad Fatoum
                   ` (6 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Ahmad Fatoum @ 2025-04-01 10:47 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum

In preparation for adding new functions to the flexible bootarg support
that are not used at boot-time, factor out the bootargs support,
so new code need not include the whole boot.h header.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 include/boot.h     | 16 +---------------
 include/bootargs.h | 22 ++++++++++++++++++++++
 2 files changed, 23 insertions(+), 15 deletions(-)
 create mode 100644 include/bootargs.h

diff --git a/include/boot.h b/include/boot.h
index 71da2e2baba8..c1676364cadc 100644
--- a/include/boot.h
+++ b/include/boot.h
@@ -6,21 +6,7 @@
 #include <menu.h>
 #include <environment.h>
 #include <bootm-overrides.h>
-
-#ifdef CONFIG_FLEXIBLE_BOOTARGS
-const char *linux_bootargs_get(void);
-int linux_bootargs_overwrite(const char *bootargs);
-#else
-static inline const char *linux_bootargs_get(void)
-{
-	return getenv("bootargs");
-}
-
-static inline int linux_bootargs_overwrite(const char *bootargs)
-{
-	return setenv("bootargs", bootargs);
-}
-#endif
+#include <bootargs.h>
 
 struct bootentries {
 	struct list_head entries;
diff --git a/include/bootargs.h b/include/bootargs.h
new file mode 100644
index 000000000000..c85fd4c4a797
--- /dev/null
+++ b/include/bootargs.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef __BOOTARGS_H
+#define __BOOTARGS_H
+
+#include <environment.h>
+
+#ifdef CONFIG_FLEXIBLE_BOOTARGS
+const char *linux_bootargs_get(void);
+int linux_bootargs_overwrite(const char *bootargs);
+#else
+static inline const char *linux_bootargs_get(void)
+{
+	return getenv("bootargs");
+}
+
+static inline int linux_bootargs_overwrite(const char *bootargs)
+{
+	return setenv("bootargs", bootargs);
+}
+#endif
+
+#endif /* __BOOTARGS_H */
-- 
2.39.5




^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 10/16] block: add get_rootarg block op into block_device_ops
  2025-04-01 10:47 [PATCH 00/16] boot: implement generic bootsource target Ahmad Fatoum
                   ` (8 preceding siblings ...)
  2025-04-01 10:47 ` [PATCH 09/16] boot: split off bootarg API into new bootargs.h header Ahmad Fatoum
@ 2025-04-01 10:48 ` Ahmad Fatoum
  2025-04-01 10:48 ` [PATCH 11/16] block: fixup rootwait argument when needed by default Ahmad Fatoum
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Ahmad Fatoum @ 2025-04-01 10:48 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum

The root argument from cdev generation only succeeds for partitions of
block devices anyway, so it makes sense to move the logic to the block
device support.

Further, the code can be simplified a bit by moving the MCI-specific
logic into the MCI core.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 common/block.c         | 22 +++++++++++++++++
 common/bootm.c         |  1 +
 drivers/mci/mci-core.c | 45 ++++++++++++++++++++++++++++++---
 fs/fs.c                | 56 ------------------------------------------
 include/block.h        |  6 +++++
 include/driver.h       |  6 -----
 include/fs.h           |  1 -
 7 files changed, 70 insertions(+), 67 deletions(-)

diff --git a/common/block.c b/common/block.c
index 3ee33f2bf071..7066abc5f404 100644
--- a/common/block.c
+++ b/common/block.c
@@ -589,3 +589,25 @@ const char *blk_type_str(enum blk_type type)
 		return "unknown";
 	}
 }
+
+char *cdev_get_linux_rootarg(const struct cdev *partcdev)
+{
+	const struct cdev *cdevm;
+	struct block_device *blk;
+	char *rootarg = NULL;
+
+	if (!partcdev)
+		return NULL;
+
+	cdevm = partcdev->master ?: partcdev;
+	blk = cdev_get_block_device(cdevm);
+	if (!blk)
+		return NULL;
+
+	if (blk->ops->get_rootarg)
+		rootarg = blk->ops->get_rootarg(blk, partcdev);
+	if (!rootarg && partcdev->partuuid[0] != 0)
+		rootarg = basprintf("root=PARTUUID=%s", partcdev->partuuid);
+
+	return rootarg;
+}
diff --git a/common/bootm.c b/common/bootm.c
index 6b63987f0900..e781b48b0e7d 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -6,6 +6,7 @@
 #include <fs.h>
 #include <malloc.h>
 #include <memory.h>
+#include <block.h>
 #include <libfile.h>
 #include <image-fit.h>
 #include <globalvar.h>
diff --git a/drivers/mci/mci-core.c b/drivers/mci/mci-core.c
index 947fe44c088f..aae63484a09b 100644
--- a/drivers/mci/mci-core.c
+++ b/drivers/mci/mci-core.c
@@ -676,11 +676,8 @@ static void mci_part_add(struct mci *mci, uint64_t size,
 
 	if (area_type == MMC_BLK_DATA_AREA_RPMB)
 		mci->rpmb_part = part;
-
-	if (area_type == MMC_BLK_DATA_AREA_MAIN) {
+	else if (area_type == MMC_BLK_DATA_AREA_MAIN)
 		cdev_set_of_node(&part->blk.cdev, mci->host->hw_dev->of_node);
-		part->blk.cdev.flags |= DEVFS_IS_MCI_MAIN_PART_DEV;
-	}
 
 	mci->nr_parts++;
 }
@@ -2530,10 +2527,50 @@ static void mci_parse_cid(struct mci *mci)
 	dev_add_param_uint32_fixed(dev, "cid_month", mci->cid.month, "%0u");
 }
 
+static bool cdev_partname_equal(const struct cdev *a,
+				const struct cdev *b)
+{
+	return a->partname && b->partname &&
+		!strcmp(a->partname, b->partname);
+}
+
+static char *mci_get_linux_mmcblkdev(struct block_device *blk,
+				     const struct cdev *partcdev)
+
+{
+	struct mci_part *mci_part = container_of(blk, struct mci_part, blk);
+	struct cdev *cdevm = partcdev->master, *cdev;
+	int id, partnum;
+
+	if (mci_part->area_type != MMC_BLK_DATA_AREA_MAIN)
+		return NULL;
+
+	id = of_alias_get_id(cdev_of_node(cdevm), "mmc");
+	if (id < 0)
+		return NULL;
+
+	partnum = 1; /* linux partitions are 1 based */
+	list_for_each_entry(cdev, &cdevm->partitions, partition_entry) {
+
+		/*
+		 * Partname is not guaranteed but this partition cdev is listed
+		 * in the partitions list so we need to count it instead of
+		 * skipping it.
+		 */
+		if (cdev_partname_equal(partcdev, cdev))
+			return basprintf("root=/dev/mmcblk%dp%d", id, partnum);
+		partnum++;
+	}
+
+	return NULL;
+}
+
 static struct block_device_ops mci_ops = {
 	.read = mci_sd_read,
 	.write = IS_ENABLED(CONFIG_MCI_WRITE) ? mci_sd_write : NULL,
 	.erase = IS_ENABLED(CONFIG_MCI_ERASE) ? mci_sd_erase : NULL,
+	.get_rootarg = IS_ENABLED(CONFIG_MMCBLKDEV_ROOTARG) ?
+		mci_get_linux_mmcblkdev : NULL,
 };
 
 static int mci_set_boot(struct param_d *param, void *priv)
diff --git a/fs/fs.c b/fs/fs.c
index 48a6e960e812..98e2b9b73663 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -95,8 +95,6 @@ void cdev_print(const struct cdev *cdev)
 			printf(" table-partition");
 		if (cdev->flags & DEVFS_PARTITION_FOR_FIXUP)
 			printf(" fixup");
-		if (cdev->flags & DEVFS_IS_MCI_MAIN_PART_DEV)
-			printf(" mci-main-partition");
 		if (cdev->flags & DEVFS_IS_MBR_PARTITIONED)
 			printf(" mbr-partitioned");
 		if (cdev->flags & DEVFS_IS_GPT_PARTITIONED)
@@ -3060,60 +3058,6 @@ int popd(char *oldcwd)
 	return ret;
 }
 
-static bool cdev_partname_equal(const struct cdev *a,
-				const struct cdev *b)
-{
-	return a->partname && b->partname &&
-		!strcmp(a->partname, b->partname);
-}
-
-static char *get_linux_mmcblkdev(const struct cdev *root_cdev)
-{
-	struct cdev *cdevm = root_cdev->master, *cdev;
-	int id, partnum;
-
-	if (!IS_ENABLED(CONFIG_MMCBLKDEV_ROOTARG))
-		return NULL;
-	if (!cdevm || !cdev_is_mci_main_part_dev(cdevm))
-		return NULL;
-
-	id = of_alias_get_id(cdev_of_node(cdevm), "mmc");
-	if (id < 0)
-		return NULL;
-
-	partnum = 1; /* linux partitions are 1 based */
-	list_for_each_entry(cdev, &cdevm->partitions, partition_entry) {
-
-		/*
-		 * Partname is not guaranteed but this partition cdev is listed
-		 * in the partitions list so we need to count it instead of
-		 * skipping it.
-		 */
-		if (cdev_partname_equal(root_cdev, cdev))
-			return basprintf("root=/dev/mmcblk%dp%d", id, partnum);
-		partnum++;
-	}
-
-	return NULL;
-}
-
-char *cdev_get_linux_rootarg(const struct cdev *cdev)
-{
-	char *str;
-
-	if (!cdev)
-		return NULL;
-
-	str = get_linux_mmcblkdev(cdev);
-	if (str)
-		return str;
-
-	if (cdev->partuuid[0] != 0)
-		return basprintf("root=PARTUUID=%s", cdev->partuuid);
-
-	return NULL;
-}
-
 /*
  * Mount a device to a directory.
  * We do this by registering a new device on which the filesystem
diff --git a/include/block.h b/include/block.h
index b57d99a3fc08..a992eba43191 100644
--- a/include/block.h
+++ b/include/block.h
@@ -14,6 +14,7 @@ struct block_device_ops {
 	int (*write)(struct block_device *, const void *buf, sector_t block, blkcnt_t num_blocks);
 	int (*erase)(struct block_device *blk, sector_t block, blkcnt_t num_blocks);
 	int (*flush)(struct block_device *);
+	char *(*get_rootarg)(struct block_device *blk, const struct cdev *partcdev);
 };
 
 struct chunk;
@@ -82,6 +83,7 @@ static inline int block_flush(struct block_device *blk)
 #ifdef CONFIG_BLOCK
 struct block_device *cdev_get_block_device(const struct cdev *cdev);
 unsigned file_list_add_blockdevs(struct file_list *files);
+char *cdev_get_linux_rootarg(const struct cdev *partcdev);
 #else
 static inline struct block_device *cdev_get_block_device(const struct cdev *cdev)
 {
@@ -91,6 +93,10 @@ static inline unsigned file_list_add_blockdevs(struct file_list *files)
 {
 	return 0;
 }
+static inline char *cdev_get_linux_rootarg(const struct cdev *partcdev)
+{
+	return NULL;
+}
 #endif
 
 static inline bool cdev_is_block_device(const struct cdev *cdev)
diff --git a/include/driver.h b/include/driver.h
index 60bcfc5e2f7d..c055e7b47b47 100644
--- a/include/driver.h
+++ b/include/driver.h
@@ -561,7 +561,6 @@ extern struct list_head cdev_list;
 #define DEVFS_PARTITION_FIXED		(1U << 0)
 #define DEVFS_PARTITION_READONLY	(1U << 1)
 #define DEVFS_IS_CHARACTER_DEV		(1U << 3)
-#define DEVFS_IS_MCI_MAIN_PART_DEV	(1U << 4)
 #define DEVFS_PARTITION_FROM_OF		(1U << 5)
 #define DEVFS_PARTITION_FROM_TABLE	(1U << 6)
 #define DEVFS_IS_MBR_PARTITIONED	(1U << 7)
@@ -620,11 +619,6 @@ static inline void cdev_create_default_automount(struct cdev *cdev)
 }
 #endif
 
-static inline bool cdev_is_mci_main_part_dev(struct cdev *cdev)
-{
-	return cdev->flags & DEVFS_IS_MCI_MAIN_PART_DEV;
-}
-
 #define DEVFS_PARTITION_APPEND		0
 
 /**
diff --git a/include/fs.h b/include/fs.h
index fafd91343b5c..bf927da4207e 100644
--- a/include/fs.h
+++ b/include/fs.h
@@ -175,7 +175,6 @@ void mount_all(void);
 
 void fsdev_set_linux_rootarg(struct fs_device *fsdev, const char *str);
 char *path_get_linux_rootarg(const char *path);
-char *cdev_get_linux_rootarg(const struct cdev *cdev);
 
 static inline const char *devpath_to_name(const char *devpath)
 {
-- 
2.39.5




^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 11/16] block: fixup rootwait argument when needed by default
  2025-04-01 10:47 [PATCH 00/16] boot: implement generic bootsource target Ahmad Fatoum
                   ` (9 preceding siblings ...)
  2025-04-01 10:48 ` [PATCH 10/16] block: add get_rootarg block op into block_device_ops Ahmad Fatoum
@ 2025-04-01 10:48 ` Ahmad Fatoum
  2025-04-01 10:48 ` [PATCH 12/16] of: implement stub for of_cdev_find Ahmad Fatoum
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Ahmad Fatoum @ 2025-04-01 10:48 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum

The rootwait command-line option is usually added to the bootloader spec
options line, which is a bit out-of-place in combination with
linux-appendroot as it hardcodes an assumption about what device the
bootloader spec entries are installed to.

Instead, allow barebox to fix it up on demand, when booting from SD/MMC,
USB or NFS.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 common/Kconfig               | 11 +++++++++++
 common/block.c               |  5 +++++
 common/bootargs.c            | 12 ++++++++++++
 common/bootm.c               |  5 +++++
 drivers/block/efi-block-io.c | 10 +++++++---
 drivers/mci/mci-core.c       |  1 +
 drivers/usb/storage/usb.c    |  1 +
 fs/nfs.c                     |  4 ++++
 include/block.h              |  1 +
 include/bootargs.h           |  7 +++++++
 10 files changed, 54 insertions(+), 3 deletions(-)

diff --git a/common/Kconfig b/common/Kconfig
index f0cd2f0729a4..4d2a2a73f39b 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -781,6 +781,17 @@ config FLEXIBLE_BOOTARGS
 	  to replace parts of the bootargs string without reconstructing it
 	  completely.
 
+config ROOTWAIT_BOOTARG
+	def_bool y
+	prompt "fixup 'rootwait' into kernel command-line when needed"
+	depends on FLEXIBLE_BOOTARGS
+	help
+	  Adds a rootwait= argument into the kernel command-line argument
+	  for boot media that requires it, like USB, SD/MMC or NFS.
+	  The duration chosen is controlled by the linux.rootwait
+	  parameter and defaults to 10 seconds. Setting the variable
+	  to 0 will wait indefinitely.
+
 config MMCBLKDEV_ROOTARG
 	bool
 	prompt "Support 'root=mmcblkXpN' cmdline appending"
diff --git a/common/block.c b/common/block.c
index 7066abc5f404..d401e979abff 100644
--- a/common/block.c
+++ b/common/block.c
@@ -12,6 +12,7 @@
 #include <linux/list.h>
 #include <dma.h>
 #include <range.h>
+#include <bootargs.h>
 #include <file-list.h>
 
 LIST_HEAD(block_device_list);
@@ -609,5 +610,9 @@ char *cdev_get_linux_rootarg(const struct cdev *partcdev)
 	if (!rootarg && partcdev->partuuid[0] != 0)
 		rootarg = basprintf("root=PARTUUID=%s", partcdev->partuuid);
 
+	if (IS_ENABLED(CONFIG_ROOTWAIT_BOOTARG) && blk->rootwait)
+		rootarg = linux_bootargs_append_rootwait(rootarg);
+
 	return rootarg;
 }
+
diff --git a/common/bootargs.c b/common/bootargs.c
index c49136609f48..ad8007d32a42 100644
--- a/common/bootargs.c
+++ b/common/bootargs.c
@@ -75,6 +75,18 @@ int linux_bootargs_overwrite(const char *bootargs)
 	return 0;
 }
 
+char *linux_bootargs_append_rootwait(char *rootarg_old)
+{
+	char *rootarg = xasprintf("%s rootwait=%d",
+				  rootarg_old, linux_rootwait_secs);
+	free(rootarg_old);
+	return rootarg;
+}
+
+
 BAREBOX_MAGICVAR(global.linux.bootargs.*, "Linux bootargs variables");
 BAREBOX_MAGICVAR(global.linux.mtdparts.*, "Linux mtdparts variables");
 BAREBOX_MAGICVAR(global.linux.blkdevparts.*, "Linux blkdevparts variables");
+#ifdef CONFIG_ROOTWAIT_BOOTARG
+BAREBOX_MAGICVAR(global.linux.rootwait, "Argument (in seconds) for Linux rootwait= option if it's fixed up. A negative value waits indefinitely");
+#endif
diff --git a/common/bootm.c b/common/bootm.c
index e781b48b0e7d..db79e145c9f3 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -1096,6 +1096,8 @@ static struct image_handler zstd_bootm_handler = {
 	.filetype = filetype_zstd_compressed,
 };
 
+int linux_rootwait_secs = 10;
+
 static int bootm_init(void)
 {
 	globalvar_add_simple("bootm.image", NULL);
@@ -1121,6 +1123,9 @@ static int bootm_init(void)
 	globalvar_add_simple_enum("bootm.verify", (unsigned int *)&bootm_verify_mode,
 				  bootm_verify_names, ARRAY_SIZE(bootm_verify_names));
 
+	if (IS_ENABLED(CONFIG_ROOTWAIT_BOOTARG))
+		globalvar_add_simple_int("linux.rootwait",
+					 &linux_rootwait_secs, "%d");
 
 	if (IS_ENABLED(CONFIG_BZLIB))
 		register_image_handler(&bzip2_bootm_handler);
diff --git a/drivers/block/efi-block-io.c b/drivers/block/efi-block-io.c
index 2f439d89419e..1c2d801a42ef 100644
--- a/drivers/block/efi-block-io.c
+++ b/drivers/block/efi-block-io.c
@@ -108,12 +108,12 @@ static void efi_bio_print_info(struct device *dev)
 
 static bool is_bio_usbdev(struct efi_device *efidev)
 {
-	return IS_ENABLED(CONFIG_EFI_BLK_SEPARATE_USBDISK) &&
-		efi_device_has_guid(efidev, EFI_USB_IO_PROTOCOL_GUID);
+	return efi_device_has_guid(efidev, EFI_USB_IO_PROTOCOL_GUID);
 }
 
 static int efi_bio_probe(struct efi_device *efidev)
 {
+	bool is_usbdev;
 	int instance;
 	struct efi_bio_priv *priv;
 	struct efi_block_io_media *media;
@@ -134,7 +134,11 @@ static int efi_bio_probe(struct efi_device *efidev)
 		efi_bio_print_info(dev);
 	priv->dev = &efidev->dev;
 
-	if (is_bio_usbdev(efidev)) {
+	is_usbdev = is_bio_usbdev(efidev);
+	if (is_usbdev)
+		priv->blk.rootwait = true;
+
+	if (IS_ENABLED(CONFIG_EFI_BLK_SEPARATE_USBDISK) && is_usbdev) {
 		instance = cdev_find_free_index("usbdisk");
 		priv->blk.cdev.name = xasprintf("usbdisk%d", instance);
 	} else {
diff --git a/drivers/mci/mci-core.c b/drivers/mci/mci-core.c
index aae63484a09b..2c82379b0d73 100644
--- a/drivers/mci/mci-core.c
+++ b/drivers/mci/mci-core.c
@@ -2659,6 +2659,7 @@ static int mci_register_partition(struct mci_part *part)
 	part->blk.dev = &mci->dev;
 	part->blk.ops = &mci_ops;
 	part->blk.type = IS_SD(mci) ? BLK_TYPE_SD : BLK_TYPE_MMC;
+	part->blk.rootwait = true;
 
 	if (part->area_type == MMC_BLK_DATA_AREA_RPMB)
 		return 0;
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index cc241e69be1b..e106174f37d8 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -422,6 +422,7 @@ static int usb_stor_add_blkdev(struct us_data *us, unsigned char lun)
 	pblk_dev->blk.cdev.name = basprintf("disk%d", result);
 	pblk_dev->blk.blockbits = SECTOR_SHIFT;
 	pblk_dev->blk.type = BLK_TYPE_USB;
+	pblk_dev->blk.rootwait = true;
 
 	result = blockdevice_register(&pblk_dev->blk);
 	if (result != 0) {
diff --git a/fs/nfs.c b/fs/nfs.c
index bc3ab3aa8e87..4311971c479d 100644
--- a/fs/nfs.c
+++ b/fs/nfs.c
@@ -34,6 +34,7 @@
 #include <byteorder.h>
 #include <globalvar.h>
 #include <parseopt.h>
+#include <bootargs.h>
 #include <magicvar.h>
 
 #define SUNRPC_PORT     111
@@ -1423,6 +1424,9 @@ static void nfs_set_rootarg(struct nfs_priv *npriv, struct fs_device *fsdev)
 		str = tmp;
 	}
 
+	if (IS_ENABLED(CONFIG_ROOTWAIT_BOOTARG))
+		str = linux_bootargs_append_rootwait(str);
+
 	fsdev_set_linux_rootarg(fsdev, str);
 
 	free(str);
diff --git a/include/block.h b/include/block.h
index a992eba43191..0ca6c6aff6e9 100644
--- a/include/block.h
+++ b/include/block.h
@@ -44,6 +44,7 @@ struct block_device {
 	struct block_device_ops *ops;
 	u8 blockbits;
 	u8 type; /* holds enum blk_type */
+	u8 rootwait:1;
 	blkcnt_t num_blocks;
 	int rdbufsize;
 	int blkmask;
diff --git a/include/bootargs.h b/include/bootargs.h
index c85fd4c4a797..1cf88bd38056 100644
--- a/include/bootargs.h
+++ b/include/bootargs.h
@@ -4,9 +4,12 @@
 
 #include <environment.h>
 
+extern int linux_rootwait_secs;
+
 #ifdef CONFIG_FLEXIBLE_BOOTARGS
 const char *linux_bootargs_get(void);
 int linux_bootargs_overwrite(const char *bootargs);
+char *linux_bootargs_append_rootwait(char *rootarg_old);
 #else
 static inline const char *linux_bootargs_get(void)
 {
@@ -17,6 +20,10 @@ static inline int linux_bootargs_overwrite(const char *bootargs)
 {
 	return setenv("bootargs", bootargs);
 }
+static inline char *linux_bootargs_append_rootwait(char *rootarg)
+{
+	return rootarg;
+}
 #endif
 
 #endif /* __BOOTARGS_H */
-- 
2.39.5




^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 12/16] of: implement stub for of_cdev_find
  2025-04-01 10:47 [PATCH 00/16] boot: implement generic bootsource target Ahmad Fatoum
                   ` (10 preceding siblings ...)
  2025-04-01 10:48 ` [PATCH 11/16] block: fixup rootwait argument when needed by default Ahmad Fatoum
@ 2025-04-01 10:48 ` Ahmad Fatoum
  2025-04-01 10:48 ` [PATCH 13/16] bootsource: implement bootsource_of_cdev_find Ahmad Fatoum
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Ahmad Fatoum @ 2025-04-01 10:48 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum

For systems without CONFIG_OFTREE, provide a stub definition of
of_cdev_find, so code can compile without error.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 include/of.h | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/include/of.h b/include/of.h
index 985f0195b2aa..5829d9d1ace0 100644
--- a/include/of.h
+++ b/include/of.h
@@ -1007,6 +1007,11 @@ static inline struct device *of_device_enable_and_register_by_alias(
 	return NULL;
 }
 
+static inline struct cdev *of_cdev_find(struct device_node *node)
+{
+	return ERR_PTR(-ENOSYS);
+}
+
 static inline int of_register_fixup(int (*fixup)(struct device_node *, void *),
 				void *context)
 {
-- 
2.39.5




^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 13/16] bootsource: implement bootsource_of_cdev_find
  2025-04-01 10:47 [PATCH 00/16] boot: implement generic bootsource target Ahmad Fatoum
                   ` (11 preceding siblings ...)
  2025-04-01 10:48 ` [PATCH 12/16] of: implement stub for of_cdev_find Ahmad Fatoum
@ 2025-04-01 10:48 ` Ahmad Fatoum
  2025-04-01 10:48 ` [PATCH 14/16] common: bootdef: add new boot entry provider Ahmad Fatoum
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Ahmad Fatoum @ 2025-04-01 10:48 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum

For use on device tree systems that especially boot from SD/eMMC,
introduce a new helper function that returns the cdev of the boot medium.

Calling this function for unknown boot media will return NULL and
callers will have to handle that gracefully.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 common/bootsource.c  | 17 +++++++++++++++++
 include/bootsource.h |  1 +
 2 files changed, 18 insertions(+)

diff --git a/common/bootsource.c b/common/bootsource.c
index d054427c6e78..e78237ff36b8 100644
--- a/common/bootsource.c
+++ b/common/bootsource.c
@@ -5,6 +5,7 @@
  */
 
 #include <common.h>
+#include <of.h>
 #include <bootsource.h>
 #include <environment.h>
 #include <magicvar.h>
@@ -123,6 +124,22 @@ struct device_node *bootsource_of_node_get(struct device_node *root)
 	return np;
 }
 
+struct cdev *bootsource_of_cdev_find(void)
+{
+	struct device_node *np;
+	struct cdev *cdev;
+
+	np = bootsource_of_node_get(NULL);
+	if (!np)
+		return NULL;
+
+	cdev = of_cdev_find(np);
+	if (IS_ERR(cdev))
+		return NULL;
+
+	return cdev;
+}
+
 void bootsource_set_alias_name(const char *name)
 {
 	bootsource_alias_name = name;
diff --git a/include/bootsource.h b/include/bootsource.h
index 9fb77a0bb0a9..c9c58daf096c 100644
--- a/include/bootsource.h
+++ b/include/bootsource.h
@@ -34,6 +34,7 @@ const char *bootsource_to_string(enum bootsource src);
 const char *bootsource_get_alias_stem(enum bootsource bs);
 int bootsource_of_alias_xlate(enum bootsource bs, int instance);
 struct device_node *bootsource_of_node_get(struct device_node *root);
+struct cdev *bootsource_of_cdev_find(void);
 
 /**
  * bootsource_set - set bootsource with optional DT mapping table
-- 
2.39.5




^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 14/16] common: bootdef: add new boot entry provider
  2025-04-01 10:47 [PATCH 00/16] boot: implement generic bootsource target Ahmad Fatoum
                   ` (12 preceding siblings ...)
  2025-04-01 10:48 ` [PATCH 13/16] bootsource: implement bootsource_of_cdev_find Ahmad Fatoum
@ 2025-04-01 10:48 ` Ahmad Fatoum
  2025-04-01 10:48 ` [PATCH 15/16] kconfig: implement IF_ENABLED helper Ahmad Fatoum
  2025-04-01 10:48 ` [PATCH 16/16] boot: make bootsource the default boot target if enabled Ahmad Fatoum
  15 siblings, 0 replies; 17+ messages in thread
From: Ahmad Fatoum @ 2025-04-01 10:48 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum

It's common to configure barebox to continue boot from the same boot
medium that barebox itself was loaded from.

This can be implemented by adding a script that checks $bootsource and
$bootsource_instance and pointing global.boot.default at it, but this is
a useful enough default that it should not need any extra scripting.

Therefore, add a default boot entries provider that resolves an alias at
runtime and then returns the actual boot entries. The code is
intentionally kept generic as we may want to add more targets along
these lines:

  - bootsource:        expands to the boot medium
  - storage:           expands to all storage devices
  - storage.builtin:   expands to unremovable storage (e.g. eMMC)
  - storage.removable: expands to removable storage (e.g. USB)
  - storage.debugger:  expands to debugger/emulator storage
                       (e.g. semihosting)

The storage family of targets still need some thinking through, so
add only bootsource for now.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 common/Kconfig      | 14 ++++++++
 common/Makefile     |  2 ++
 common/bootdef.c    | 40 +++++++++++++++++++++++
 common/cdev-alias.c | 79 +++++++++++++++++++++++++++++++++++++++++++++
 include/driver.h    | 13 ++++++++
 5 files changed, 148 insertions(+)
 create mode 100644 common/bootdef.c
 create mode 100644 common/cdev-alias.c

diff --git a/common/Kconfig b/common/Kconfig
index 4d2a2a73f39b..a3df70b4dbb7 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -74,6 +74,9 @@ config LOGBUF
 config STDDEV
 	bool
 
+config CDEV_ALIAS
+	bool
+
 config MENUTREE
 	bool
 	select GLOB
@@ -1204,6 +1207,17 @@ config BOOTCHOOSER
 	select OFTREE
 	select PARAMETER
 
+config BOOT_DEFAULTS
+	bool "default boot targets"
+	select BOOT
+	select CDEV_ALIAS
+	default BLSPEC && OFDEVICE
+	help
+	  Say y here to enable a number of default boot targets that
+	  determine at runtime what to do. An example is the bootsource
+	  target, which will expand to the device that barebox has
+	  booted from if that could be determined.
+
 config RESET_SOURCE
 	bool "detect Reset cause"
 	depends on GLOBALVAR
diff --git a/common/Makefile b/common/Makefile
index 0e9648378d8c..9b67187561bf 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -79,10 +79,12 @@ obj-$(CONFIG_FIRMWARE)		+= firmware.o
 obj-$(CONFIG_UBIFORMAT)		+= ubiformat.o
 obj-$(CONFIG_BAREBOX_UPDATE_IMX_NAND_FCB) += imx-bbu-nand-fcb.o
 obj-$(CONFIG_BOOT)		+= boot.o bootscan.o
+obj-$(CONFIG_BOOT_DEFAULTS)	+= bootdef.o
 obj-$(CONFIG_SERIAL_DEV_BUS)	+= serdev.o
 obj-$(CONFIG_USB_GADGET)	+= usbgadget.o
 obj-pbl-$(CONFIG_HAVE_OPTEE)	+= optee.o
 obj-$(CONFIG_FASTBOOT_BASE)	+= fastboot.o
+obj-$(CONFIG_CDEV_ALIAS)	+= cdev-alias.o
 
 ifdef CONFIG_PASSWORD
 
diff --git a/common/bootdef.c b/common/bootdef.c
new file mode 100644
index 000000000000..254228580191
--- /dev/null
+++ b/common/bootdef.c
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2025 Ahmad Fatoum
+ */
+#define pr_fmt(fmt)	"bootdef: " fmt
+
+#include <boot.h>
+#include <xfuncs.h>
+#include <string.h>
+#include <bootsource.h>
+#include <driver.h>
+#include <init.h>
+
+static int bootdev_process(struct cdev *cdev, void *entries)
+{
+	return bootentry_create_from_name(entries, cdev->name);
+}
+
+static int bootdef_add_entry(struct bootentries *entries, const char *name)
+{
+	int ret;
+
+	ret = cdev_alias_resolve_for_each(name, bootdev_process, entries);
+	if (ret == -ENODEV) {
+		pr_info("Could not autodetect bootsource device\n");
+		return 0;
+	}
+
+	return ret;
+}
+
+static struct bootentry_provider bootdef_entry_provider = {
+	.generate = bootdef_add_entry,
+};
+
+static int bootdef_entry_init(void)
+{
+	return bootentry_register_provider(&bootdef_entry_provider);
+}
+device_initcall(bootdef_entry_init);
diff --git a/common/cdev-alias.c b/common/cdev-alias.c
new file mode 100644
index 000000000000..5c37c2e58bf3
--- /dev/null
+++ b/common/cdev-alias.c
@@ -0,0 +1,79 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2025 Ahmad Fatoum
+ */
+#define pr_fmt(fmt)	"cdev-alias: " fmt
+
+#include <xfuncs.h>
+#include <string.h>
+#include <stringlist.h>
+#include <bootsource.h>
+#include <driver.h>
+#include <init.h>
+
+struct cdev_alias {
+	const char *name;
+	int (*resolve)(struct cdev_alias *, const char *arg,
+		       cdev_alias_processor_t fn, void *data);
+};
+
+static struct cdev *resolve_partition(struct cdev *cdev,
+				      const char *partname)
+{
+	struct cdev *partcdev;
+
+	if (!partname)
+		return cdev;
+
+	for_each_cdev_partition(partcdev, cdev) {
+		if (streq_ptr(partcdev->partname, partname))
+			return partcdev;
+	}
+
+	return ERR_PTR(-ENODEV);
+}
+
+static int cdev_alias_resolve_bootsource(struct cdev_alias *cdev_alias,
+					 const char *partname,
+					 cdev_alias_processor_t fn,
+					 void *data)
+{
+	struct cdev *cdev;
+
+	cdev = bootsource_of_cdev_find();
+	if (!cdev)
+		return -ENODEV;
+
+	cdev = resolve_partition(cdev, partname);
+	if (IS_ERR(cdev))
+		return PTR_ERR(cdev);
+
+	return fn(cdev, data);
+}
+
+static struct cdev_alias cdev_alias_aliases[] = {
+	{ "bootsource", cdev_alias_resolve_bootsource },
+	{ /* sentinel */}
+};
+
+int cdev_alias_resolve_for_each(const char *name,
+				cdev_alias_processor_t fn, void *data)
+{
+	struct cdev_alias *alias;
+	int ret = 0;
+	char *buf, *arg;
+
+	arg = buf = xstrdup(name);
+	name = strsep(&arg, ".");
+
+	for (alias = cdev_alias_aliases; alias->name; alias++) {
+		if (!streq_ptr(name, alias->name))
+			continue;
+
+		ret = alias->resolve(alias, arg, fn, data);
+		break;
+	}
+
+	free(buf);
+	return ret;
+}
diff --git a/include/driver.h b/include/driver.h
index c055e7b47b47..094347d4577e 100644
--- a/include/driver.h
+++ b/include/driver.h
@@ -515,6 +515,19 @@ int cdev_open(struct cdev *, unsigned long flags);
 int cdev_fdopen(struct cdev *cdev, unsigned long flags);
 int cdev_close(struct cdev *cdev);
 int cdev_flush(struct cdev *cdev);
+
+typedef int (*cdev_alias_processor_t)(struct cdev *, void *data);
+
+#ifdef CONFIG_CDEV_ALIAS
+int cdev_alias_resolve_for_each(const char *name,
+				cdev_alias_processor_t, void *data);
+#else
+static inline int cdev_alias_resolve_for_each(const char *name,
+				cdev_alias_processor_t fn, void *data)
+{
+	return 0;
+}
+#endif
 #if IN_PROPER
 ssize_t cdev_read(struct cdev *cdev, void *buf, size_t count, loff_t offset, ulong flags);
 ssize_t cdev_write(struct cdev *cdev, const void *buf, size_t count, loff_t offset, ulong flags);
-- 
2.39.5




^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 15/16] kconfig: implement IF_ENABLED helper
  2025-04-01 10:47 [PATCH 00/16] boot: implement generic bootsource target Ahmad Fatoum
                   ` (13 preceding siblings ...)
  2025-04-01 10:48 ` [PATCH 14/16] common: bootdef: add new boot entry provider Ahmad Fatoum
@ 2025-04-01 10:48 ` Ahmad Fatoum
  2025-04-01 10:48 ` [PATCH 16/16] boot: make bootsource the default boot target if enabled Ahmad Fatoum
  15 siblings, 0 replies; 17+ messages in thread
From: Ahmad Fatoum @ 2025-04-01 10:48 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum

For situations where ternary operations are not allowed like
compile-time string concatenation, introduce a helper that checks if the
first argument is enabled and expands to the rest of the arguments only
if it is.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 include/linux/kconfig.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/include/linux/kconfig.h b/include/linux/kconfig.h
index 4e9c77b964a7..971f4260725c 100644
--- a/include/linux/kconfig.h
+++ b/include/linux/kconfig.h
@@ -33,6 +33,12 @@
  */
 #define IS_ENABLED(option) __or(IS_BUILTIN(option), IS_MODULE(option))
 
+#define IF_ENABLED__0(args...)
+#define IF_ENABLED__1(args...)		args
+#define IF_ENABLED__(optval, args...)	IF_ENABLED__##optval(args)
+#define IF_ENABLED_(optval, args...)	IF_ENABLED__(optval, args)
+#define IF_ENABLED(option, args...)	IF_ENABLED_(IS_ENABLED(option), args)
+
 #ifdef __PBL__
 #define IN_PBL		1
 #define IN_PROPER	0
-- 
2.39.5




^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 16/16] boot: make bootsource the default boot target if enabled
  2025-04-01 10:47 [PATCH 00/16] boot: implement generic bootsource target Ahmad Fatoum
                   ` (14 preceding siblings ...)
  2025-04-01 10:48 ` [PATCH 15/16] kconfig: implement IF_ENABLED helper Ahmad Fatoum
@ 2025-04-01 10:48 ` Ahmad Fatoum
  15 siblings, 0 replies; 17+ messages in thread
From: Ahmad Fatoum @ 2025-04-01 10:48 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum

bootsource now expands to the cdev that barebox booted from if
that could be determined.

This makes it a useful default for $global.boot.default.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 common/boot.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/common/boot.c b/common/boot.c
index cb16a9a2b508..6aa2b1394961 100644
--- a/common/boot.c
+++ b/common/boot.c
@@ -134,7 +134,12 @@ static char *global_user;
 
 static int init_boot(void)
 {
-	global_boot_default = global_boot_default ? : xstrdup("net");
+	if (!global_boot_default)
+		global_boot_default = xstrdup(
+			IF_ENABLED(CONFIG_BOOT_DEFAULTS, "bootsource ")
+			"net"
+		);
+
 	globalvar_add_simple_string("boot.default", &global_boot_default);
 	globalvar_add_simple_int("boot.watchdog_timeout",
 				 &boot_watchdog_timeout, "%u");
-- 
2.39.5




^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2025-04-01 11:09 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-04-01 10:47 [PATCH 00/16] boot: implement generic bootsource target Ahmad Fatoum
2025-04-01 10:47 ` [PATCH 01/16] boot: change bootentry_register_provider to take struct argument Ahmad Fatoum
2025-04-01 10:47 ` [PATCH 02/16] boot: move nfs:// parsing out of bootloader spec code Ahmad Fatoum
2025-04-01 10:47 ` [PATCH 03/16] blspec: remove unused blspec_scan_devices Ahmad Fatoum
2025-04-01 10:47 ` [PATCH 04/16] blspec: don't export blspec functions Ahmad Fatoum
2025-04-01 10:47 ` [PATCH 05/16] blspec: factor out generic parts into bootscan helper Ahmad Fatoum
2025-04-01 10:47 ` [PATCH 06/16] common: bootscan: add scan_disk callback Ahmad Fatoum
2025-04-01 10:47 ` [PATCH 07/16] blspec: support boot /dev/virtioblkX Ahmad Fatoum
2025-04-01 10:47 ` [PATCH 08/16] bootm: associate bootm overrides with struct bootentry Ahmad Fatoum
2025-04-01 10:47 ` [PATCH 09/16] boot: split off bootarg API into new bootargs.h header Ahmad Fatoum
2025-04-01 10:48 ` [PATCH 10/16] block: add get_rootarg block op into block_device_ops Ahmad Fatoum
2025-04-01 10:48 ` [PATCH 11/16] block: fixup rootwait argument when needed by default Ahmad Fatoum
2025-04-01 10:48 ` [PATCH 12/16] of: implement stub for of_cdev_find Ahmad Fatoum
2025-04-01 10:48 ` [PATCH 13/16] bootsource: implement bootsource_of_cdev_find Ahmad Fatoum
2025-04-01 10:48 ` [PATCH 14/16] common: bootdef: add new boot entry provider Ahmad Fatoum
2025-04-01 10:48 ` [PATCH 15/16] kconfig: implement IF_ENABLED helper Ahmad Fatoum
2025-04-01 10:48 ` [PATCH 16/16] boot: make bootsource the default boot target if enabled Ahmad Fatoum

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox