Hi Alexander, On 2026-05-29 08:13, Alexander Shiyan wrote: > This adds support for the extlinux.conf configuration format, commonly > used by Syslinux and many Linux distributions. The configuration file > is typically located at /boot/extlinux/extlinux.conf or > /extlinux/extlinux.conf and defines boot entries with kernel, initrd, > device tree, and command line options. > > The implementation integrates with the existing boot entry framework: > - The extlinux scanner discovers entries on mounted filesystems. > - The default LABEL is turned into a boot entry. > - Bootm is used to load and start the kernel. > --- > barebox@Diasom DS-RK3568-SOM-EVB:/ global.bootm.appendroot=true > barebox@Diasom DS-RK3568-SOM-EVB:/ global.boot.default=mmc1.2 > barebox@Diasom DS-RK3568-SOM-EVB:/ boot > ext4 ext40: EXT2 rev 1, inode_size 256, descriptor size 64 > Booting entry 'extlinux: linux' > extlinux: Booting extlinux label 'linux' > Adding "root=/dev/mmcblk1p3" to Kernel commandline > Loading ARM aarch64 Linux/EFI image '/mnt/mmc1.2/boot/extlinux/../vmlinuz' > commandline: root=/dev/mmcblk1p3 console=ttyS2,1500000n8 ro > systemd.unit=setup.target quiet splash > systemd.machine_id=181af2816b4c6b0aef77068e0ccc69ad > Loaded kernel to 0x0a400000, devicetree at 0x000000000fb49000 > > Signed-off-by: Alexander Shiyan <[email protected]> > --- > common/Kconfig | 19 ++++ > common/Makefile | 1 + > common/extlinux.c | 243 ++++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 263 insertions(+) > create mode 100644 common/extlinux.c > > diff --git a/common/Kconfig b/common/Kconfig > index 047dd5390b..6f1eabdf8b 100644 > --- a/common/Kconfig > +++ b/common/Kconfig > @@ -776,6 +776,25 @@ config BLSPEC > on a device and it allows the Operating System to install / update > kernels. > > +config EXTLINUX > + bool > + prompt "Support extlinux.conf" > + depends on FLEXIBLE_BOOTARGS > + depends on !SHELL_NONE > + select BOOT > + select BOOTM > + select MMCBLKDEV_ROOTARG if MCI > + help > + Enable this to let barebox parse extlinux.conf configuration files, > + commonly used by the Syslinux bootloader and many Linux distributions > + (e.g., on SD cards or USB drives). > + extlinux.conf is typically located at /boot/extlinux/extlinux.conf or > + /extlinux/extlinux.conf. It defines boot entries with kernel, initrd, > + device tree, and command line options. > + This option allows barebox to discover and boot operating systems > + that follow the extlinux configuration format, providing a simple > + and portable way to manage multiple boot options. > + > config FLEXIBLE_BOOTARGS > bool > prompt "flexible Linux bootargs generation" > diff --git a/common/Makefile b/common/Makefile > index 21b6cecb3b..6b97edc2c3 100644 > --- a/common/Makefile > +++ b/common/Makefile > @@ -9,6 +9,7 @@ obj-y += clock.o > pbl-$(CONFIG_PBL_CLOCKSOURCE) += clock.o > obj-y += console_common.o > obj-$(CONFIG_OFDEVICE) += deep-probe.o > +obj-$(CONFIG_EXTLINUX) += extlinux.o > obj-y += startup.o > obj-y += misc.o > obj-pbl-y += memsize.o > diff --git a/common/extlinux.c b/common/extlinux.c > new file mode 100644 > index 0000000000..6ad01cc652 > --- /dev/null > +++ b/common/extlinux.c > @@ -0,0 +1,243 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +/* SPDX-FileCopyrightText: Alexander Shiyan <[email protected]> */ > + > +#define pr_fmt(fmt) "extlinux: " fmt > + > +#include <boot.h> > +#include <bootm.h> > +#include <bootscan.h> > +#include <common.h> > +#include <environment.h> > +#include <fs.h> > +#include <globalvar.h> > +#include <libfile.h> > +#include <libgen.h> > +#include <string.h> > + > +struct extlinux_entry { > + struct bootentry entry; > + char *rootpath; > + char *label; > + char *kernel; > + char *initrd; > + char *fdtdir; > + char *fdt; > + char *append; > +}; > + > +static int extlinux_boot(struct bootentry *entry, int verbose, int dryrun) > +{ > + struct extlinux_entry *e = > + container_of(entry, struct extlinux_entry, entry); > + char *kernel_abs, *initrd_abs = NULL, *fdt_abs = NULL; > + struct bootm_data data = {}; > + int ret; > + > + bootm_data_init_defaults(&data); > + > + data.dryrun = max_t(int, dryrun, data.dryrun); > + data.verbose = max(verbose, data.verbose); > + > + kernel_abs = basprintf("%s/%s", e->rootpath, e->kernel); > + data.os_file = kernel_abs; > + > + if (e->initrd) { > + initrd_abs = basprintf("%s/%s", e->rootpath, e->initrd); > + data.initrd_file = initrd_abs; > + } > + > + if (e->fdt) { > + char *fdtdir = e->fdtdir ? : e->rootpath; > + > + fdt_abs = basprintf("%s/%s", fdtdir, e->fdt); > + data.oftree_file = fdt_abs; > + } > + > + if (e->append) > + globalvar_add_simple("linux.bootargs.dyn.bootentries", > + e->append); > + > + pr_info("Booting extlinux label '%s'\n", e->label); > + > + ret = bootm_entry(entry, &data); > + if (ret) > + pr_err("bootm failed: %pe\n", ERR_PTR(ret)); > + > + free(kernel_abs); > + free(initrd_abs); > + free(fdt_abs); > + > + return ret; > +} > + > +static void extlinux_entry_free(struct bootentry *entry) > +{ > + struct extlinux_entry *e = > + container_of(entry, struct extlinux_entry, entry); > + > + free(e->rootpath); > + free(e->label); > + free(e->kernel); > + free(e->initrd); > + free(e->fdtdir); > + free(e->fdt); > + free(e->append); > + free(e); > +} > + > +static struct extlinux_entry *parse_extlinux_conf(const char *abspath, > + const char *rootpath) > +{ > + char *buf, *bufptr, *line, *default_label = NULL; > + struct extlinux_entry *entry = NULL; > + > + bufptr = read_file(abspath, NULL); > + if (!bufptr) > + return ERR_PTR(-errno); > + > + buf = bufptr; > + while ((line = strsep(&buf, "\n\r")) != NULL) { > + char *key, *val; > + > + line = skip_spaces(line); > + > + if (*line == '#' || *line == '\0') > + continue; > + > + key = strsep(&line, " \t"); > + val = isempty(line) ? NULL : skip_spaces(line); > + if (!key || !val) > + continue; > + > + if (!default_label) { > + if (!strcasecmp(key, "DEFAULT")) > + default_label = xstrdup(val); > + > + continue; > + } > + > + if (!strcasecmp(key, "LABEL")) { > + if (!strcmp(val, default_label)) { > + entry = xzalloc(sizeof(*entry)); > + entry->label = xstrdup(val); > + entry->rootpath = dirname(xstrdup(abspath)); > + } else if (entry) { > + break; > + }
The extlinux format supports multiple entries, but you return here after the first entry parsed. We should either document that we only support a single entry or implement multiple entries. Unless I am overlooking something it should be quite straight forward to implement multiple entries, just move the call to bootentries_add_entry() into this loop. Sascha -- Pengutronix e.K. | | Steuerwalder Str. 21 | http://www.pengutronix.de/ | 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
