[PATCH 14/16] common: bootdef: add new boot entry provider
Ahmad Fatoum
a.fatoum at pengutronix.de
Tue Apr 1 03:48:04 PDT 2025
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 at 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
More information about the barebox
mailing list