* [PATCH 1/2] Add support for extlinux.conf @ 2026-04-16 13:45 Alexander Shiyan 2026-04-16 13:45 ` [PATCH 2/2] Documentation: add extlinux.conf support description Alexander Shiyan 2026-04-22 9:10 ` [PATCH 1/2] Add support for extlinux.conf Ahmad Fatoum 0 siblings, 2 replies; 10+ messages in thread From: Alexander Shiyan @ 2026-04-16 13:45 UTC (permalink / raw) To: barebox; +Cc: Alexander Shiyan 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 - Default label is turned into a boot entry - The "root=" parameter is automatically stripped from the append line to allow barebox to inject the correct root device (via appendroot) - Bootm is used to load and start the kernel --- 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' Loaded initrd from GZIP compressed /mnt/mmc1.2/boot/extlinux/../initrd.img to 0x000000000d390000-0x000000000fb48ca6 commandline: mem=0xef600000 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 <eagle.alexander923@gmail.com> --- common/Kconfig | 19 ++++ common/Makefile | 1 + common/extlinux.c | 271 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 291 insertions(+) create mode 100644 common/extlinux.c diff --git a/common/Kconfig b/common/Kconfig index cd002865f7..bbffbfe92c 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -726,6 +726,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 ac39ee4e3e..dda42c099a 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..39d5191ecc --- /dev/null +++ b/common/extlinux.c @@ -0,0 +1,271 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-FileCopyrightText: Alexander Shiyan <shc_work@mail.ru> */ + +#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 <malloc.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 *be, int verbose, int dryrun) +{ + struct extlinux_entry *e = + container_of(be, 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); + data.appendroot = true; + + 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.extlinux", e->append); + + pr_info("Booting extlinux label '%s'\n", e->label); + + ret = bootm_boot(&data); + if (ret) + pr_err("bootm failed: %s\n", strerror(-ret)); + + free(kernel_abs); + free(initrd_abs); + free(fdt_abs); + + return ret; +} + +static void extlinux_entry_free(struct bootentry *be) +{ + struct extlinux_entry *e = + container_of(be, 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 char *remove_param(const char *params, const char *param) +{ + char *result, *dst; + const char *src; + + result = xmalloc(strlen(params) + 1); + + src = params; + dst = result; + + while (*src) { + if (!strncasecmp(src, param, strlen(param))) { + while (*src && *src != ' ') + src++; + + src = skip_spaces(src); + + continue; + } + + *dst++ = *src++; + } + + *dst = '\0'; + + return result; +} + +static struct extlinux_entry *parse_extlinux_conf(const char *abspath, + const char *rootpath) +{ + char *buf, *bufptr, *line, *p, *default_label = NULL; + struct extlinux_entry *entry = NULL; + + bufptr = read_file(abspath, NULL); + if (!bufptr) + return ERR_PTR(-errno); + + for (p = bufptr; *p; p++) + if (*p == '\r') + *p = '\n'; + + buf = bufptr; + while ((line = strsep(&buf, "\n")) != NULL) { + char *key, *val; + + line = skip_spaces(line); + + if (*line == '#' || *line == '\0') + continue; + + key = line; + val = strchr(line, ' '); + if (!val) + val = strchr(line, '\t'); + if (val) { + *val++ = '\0'; + val = skip_spaces(val); + } else + 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; + continue; + } + + /* + * The same rootfs image may be launched from eMMC or SD card. + * Remove any hardcoded root= parameter from "append" to avoid + * conflicts, then let barebox automatically add the correct + * root= (via appendroot) based on the boot device. + */ + if (entry) { + if (!strcasecmp(key, "KERNEL")) + entry->kernel = xstrdup(val); + else if (!strcasecmp(key, "INITRD")) + entry->initrd = xstrdup(val); + else if (!strcasecmp(key, "FDTDIR")) + entry->fdtdir = xstrdup(val); + else if (!strcasecmp(key, "FDT")) + entry->fdt = xstrdup(val); + else if (!strcasecmp(key, "APPEND")) + entry->append = remove_param(val, "ROOT="); + else + pr_debug("Unhandled key: %s\n", key); + } + } + + free(default_label); + free(bufptr); + + if (!entry || !entry->kernel) { + if (entry) + extlinux_entry_free(&entry->entry); + return ERR_PTR(-EINVAL); + } + + return entry; +} + +static int extlinux_scan_file(struct bootscanner *scanner, + struct bootentries *bootentries, + const char *configname) +{ + struct extlinux_entry *e; + const char *rootpath; + + if (!strends(configname, "extlinux.conf")) + return 0; + + rootpath = get_mounted_path(configname); + if (IS_ERR(rootpath)) + return PTR_ERR(rootpath); + + e = parse_extlinux_conf(configname, rootpath); + if (IS_ERR(e)) + return PTR_ERR(e); + + e->entry.boot = extlinux_boot; + e->entry.release = extlinux_entry_free; + e->entry.path = xstrdup(configname); + e->entry.title = basprintf("extlinux: %s", e->label); + e->entry.description = basprintf("extlinux entry \'%s\" on %s", + e->label, rootpath); + e->entry.me.type = MENU_ENTRY_NORMAL; + + bootentries_add_entry(bootentries, &e->entry); + + return 1; +} + +static int extlinux_scan_directory(struct bootscanner *scanner, + struct bootentries *bootentries, + const char *rootpath) +{ + char *path; + struct stat s; + int ret; + + path = basprintf("%s/boot/extlinux/extlinux.conf", rootpath); + + ret = stat(path, &s); + if (!ret && S_ISREG(s.st_mode)) + ret = extlinux_scan_file(scanner, bootentries, path); + + free(path); + + return ret < 1 ? ret : 1; +} + +static struct bootscanner extlinux_scanner = { + .name = "extlinux", + .scan_file = extlinux_scan_file, + .scan_directory = extlinux_scan_directory, +}; + +static int extlinux_generate(struct bootentries *bootentries, const char *name) +{ + return bootentry_scan_generate(&extlinux_scanner, bootentries, name); +} + +static struct bootentry_provider extlinux_provider = { + .name = "extlinux", + .generate = extlinux_generate, +}; + +static int extlinux_init(void) +{ + return bootentry_register_provider(&extlinux_provider); +} +device_initcall(extlinux_init); -- 2.52.0 ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 2/2] Documentation: add extlinux.conf support description 2026-04-16 13:45 [PATCH 1/2] Add support for extlinux.conf Alexander Shiyan @ 2026-04-16 13:45 ` Alexander Shiyan 2026-04-22 9:14 ` Ahmad Fatoum 2026-04-22 9:10 ` [PATCH 1/2] Add support for extlinux.conf Ahmad Fatoum 1 sibling, 1 reply; 10+ messages in thread From: Alexander Shiyan @ 2026-04-16 13:45 UTC (permalink / raw) To: barebox; +Cc: Alexander Shiyan Signed-off-by: Alexander Shiyan <eagle.alexander923@gmail.com> --- Documentation/user/booting-linux.rst | 38 ++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/Documentation/user/booting-linux.rst b/Documentation/user/booting-linux.rst index ed1ec3f68a..307f33bb22 100644 --- a/Documentation/user/booting-linux.rst +++ b/Documentation/user/booting-linux.rst @@ -306,6 +306,44 @@ Additional notes about keys in the bootloader spec entries: different devices without having to specify a different ``root=`` option each time. +.. _extlinux_conf: + +extlinux.conf Support +^^^^^^^^^^^^^^^^^^^^^ + +In addition to the Boot Loader Specification, barebox also supports the +extlinux configuration format, commonly used by the Syslinux bootloader and +many Linux distributions. This format is often found on SD cards, USB drives, +or disk partitions prepared with tools like ``extlinux --install``. + +The configuration file is named ``extlinux.conf`` and can be located at: +* ``/boot/extlinux/extlinux.conf`` + +The file uses a simple key-value syntax with sections labeled by ``LABEL``. +A typical example looks like: + +.. code-block:: none + + DEFAULT linux + LABEL linux + KERNEL /boot/vmlinuz + INITRD /boot/initrd.img + FDT /boot/board.dtb + APPEND console=ttyS0,115200 root=PARTUUID=deadbeef-01 + +When booting an extlinux entry, barebox automatically strips any ``root=`` +parameter from the ``APPEND`` line and injects the correct ``root=`` based on +the boot device (similar to the ``linux-appendroot`` feature in blspec). This +makes the same root filesystem image usable across different storage media. + +To use extlinux support, enable ``CONFIG_EXTLINUX`` in your barebox +configuration. Entries are automatically discovered by the :ref:`command_boot` +command when scanning a device or mount point. For example: + +.. code-block:: sh + + boot mmc1.2 + .. _booting_linux_net: Network boot -- 2.52.0 ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 2/2] Documentation: add extlinux.conf support description 2026-04-16 13:45 ` [PATCH 2/2] Documentation: add extlinux.conf support description Alexander Shiyan @ 2026-04-22 9:14 ` Ahmad Fatoum 2026-04-24 8:19 ` Alexander Shiyan 0 siblings, 1 reply; 10+ messages in thread From: Ahmad Fatoum @ 2026-04-22 9:14 UTC (permalink / raw) To: Alexander Shiyan, barebox Hi, On 4/16/26 3:45 PM, Alexander Shiyan wrote: > Signed-off-by: Alexander Shiyan <eagle.alexander923@gmail.com> Thanks for adding documentation. I have been wanting to add bootloader spec support to openembedded-core to barebox can be used to boot Beaglebone black images generated by it, but with extlinux support in barebox that should work as well. I will surely give this a try in the future. Could I motivate you to add a self test that exercises the parser? Doesn't have to be anything extensive, see test/self/blspec.c for an example. It's basically adding a few configs into the barebox environment, calling bootentry_create_from_name() on the directory and then running some assertions. Thanks, Ahmad > --- > Documentation/user/booting-linux.rst | 38 ++++++++++++++++++++++++++++ > 1 file changed, 38 insertions(+) > > diff --git a/Documentation/user/booting-linux.rst b/Documentation/user/booting-linux.rst > index ed1ec3f68a..307f33bb22 100644 > --- a/Documentation/user/booting-linux.rst > +++ b/Documentation/user/booting-linux.rst > @@ -306,6 +306,44 @@ Additional notes about keys in the bootloader spec entries: > different devices without having to specify a different ``root=`` option each > time. > > +.. _extlinux_conf: > + > +extlinux.conf Support > +^^^^^^^^^^^^^^^^^^^^^ > + > +In addition to the Boot Loader Specification, barebox also supports the > +extlinux configuration format, commonly used by the Syslinux bootloader and > +many Linux distributions. This format is often found on SD cards, USB drives, > +or disk partitions prepared with tools like ``extlinux --install``. > + > +The configuration file is named ``extlinux.conf`` and can be located at: > +* ``/boot/extlinux/extlinux.conf`` > + > +The file uses a simple key-value syntax with sections labeled by ``LABEL``. > +A typical example looks like: > + > +.. code-block:: none > + > + DEFAULT linux > + LABEL linux > + KERNEL /boot/vmlinuz > + INITRD /boot/initrd.img > + FDT /boot/board.dtb > + APPEND console=ttyS0,115200 root=PARTUUID=deadbeef-01 > + > +When booting an extlinux entry, barebox automatically strips any ``root=`` > +parameter from the ``APPEND`` line and injects the correct ``root=`` based on > +the boot device (similar to the ``linux-appendroot`` feature in blspec). This > +makes the same root filesystem image usable across different storage media. > + > +To use extlinux support, enable ``CONFIG_EXTLINUX`` in your barebox > +configuration. Entries are automatically discovered by the :ref:`command_boot` > +command when scanning a device or mount point. For example: > + > +.. code-block:: sh > + > + boot mmc1.2 > + > .. _booting_linux_net: > > Network boot -- 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 | ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 2/2] Documentation: add extlinux.conf support description 2026-04-22 9:14 ` Ahmad Fatoum @ 2026-04-24 8:19 ` Alexander Shiyan 0 siblings, 0 replies; 10+ messages in thread From: Alexander Shiyan @ 2026-04-24 8:19 UTC (permalink / raw) To: Ahmad Fatoum; +Cc: barebox Hello Ahmad. > On 4/16/26 3:45 PM, Alexander Shiyan wrote: > > Signed-off-by: Alexander Shiyan <eagle.alexander923@gmail.com> > > Thanks for adding documentation. > > I have been wanting to add bootloader spec support to openembedded-core > to barebox can be used to boot Beaglebone black images generated by it, > but with extlinux support in barebox that should work as well. > I will surely give this a try in the future. > > Could I motivate you to add a self test that exercises the parser? > > Doesn't have to be anything extensive, see test/self/blspec.c for an > example. It's basically adding a few configs into the barebox > environment, calling bootentry_create_from_name() on the directory and > then running some assertions. I think this can be done later, so as not to bloat the patch series... ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/2] Add support for extlinux.conf 2026-04-16 13:45 [PATCH 1/2] Add support for extlinux.conf Alexander Shiyan 2026-04-16 13:45 ` [PATCH 2/2] Documentation: add extlinux.conf support description Alexander Shiyan @ 2026-04-22 9:10 ` Ahmad Fatoum 2026-04-24 8:46 ` Alexander Shiyan 1 sibling, 1 reply; 10+ messages in thread From: Ahmad Fatoum @ 2026-04-22 9:10 UTC (permalink / raw) To: Alexander Shiyan, barebox Hi Alexander, Thanks for your patch! On 4/16/26 3:45 PM, 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 > - Default label is turned into a boot entry > - The "root=" parameter is automatically stripped from the append line > to allow barebox to inject the correct root device (via appendroot) > - Bootm is used to load and start the kernel > --- > 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' > Loaded initrd from GZIP compressed /mnt/mmc1.2/boot/extlinux/../initrd.img to 0x000000000d390000-0x000000000fb48ca6 > commandline: mem=0xef600000 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 <eagle.alexander923@gmail.com> > --- > common/Kconfig | 19 ++++ > common/Makefile | 1 + > common/extlinux.c | 271 ++++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 291 insertions(+) > create mode 100644 common/extlinux.c > > diff --git a/common/Kconfig b/common/Kconfig > index cd002865f7..bbffbfe92c 100644 > --- a/common/Kconfig > +++ b/common/Kconfig > @@ -726,6 +726,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 ac39ee4e3e..dda42c099a 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..39d5191ecc > --- /dev/null > +++ b/common/extlinux.c > @@ -0,0 +1,271 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +/* SPDX-FileCopyrightText: Alexander Shiyan <shc_work@mail.ru> */ > + > +#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 <malloc.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 *be, int verbose, int dryrun) > +{ > + struct extlinux_entry *e = > + container_of(be, 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); > + data.appendroot = true; Not sure this is a good idea because of potential of clashing with extlinux appended command line options. > + > + 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.extlinux", e->append); > + > + pr_info("Booting extlinux label '%s'\n", e->label); > + > + ret = bootm_boot(&data); Please make use of new bootm_entry instead, so it can be used with devboot: https://github.com/barebox/barebox/blob/next/Documentation/user/devboot.rst > + if (ret) > + pr_err("bootm failed: %s\n", strerror(-ret)); > + > + free(kernel_abs); > + free(initrd_abs); > + free(fdt_abs); > + > + return ret; > +} > + > +static void extlinux_entry_free(struct bootentry *be) > +{ > + struct extlinux_entry *e = > + container_of(be, 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 char *remove_param(const char *params, const char *param) > +{ > + char *result, *dst; > + const char *src; > + > + result = xmalloc(strlen(params) + 1); > + > + src = params; > + dst = result; > + > + while (*src) { > + if (!strncasecmp(src, param, strlen(param))) { > + while (*src && *src != ' ') > + src++; > + > + src = skip_spaces(src); > + > + continue; > + } > + > + *dst++ = *src++; > + } > + > + *dst = '\0'; > + > + return result; > +} > + > +static struct extlinux_entry *parse_extlinux_conf(const char *abspath, > + const char *rootpath) > +{ > + char *buf, *bufptr, *line, *p, *default_label = NULL; > + struct extlinux_entry *entry = NULL; > + > + bufptr = read_file(abspath, NULL); > + if (!bufptr) > + return ERR_PTR(-errno); > + > + for (p = bufptr; *p; p++) > + if (*p == '\r') > + *p = '\n'; I think this can be dropped. > + > + buf = bufptr; > + while ((line = strsep(&buf, "\n")) != NULL) { And then you replace the set searched here with "\r\n" > + char *key, *val; > + > + line = skip_spaces(line); > + > + if (*line == '#' || *line == '\0') > + continue; > + Nitpick: I think below can be simplified to: > + key = line; > + val = strchr(line, ' '); > + if (!val) > + val = strchr(line, '\t'); > + if (val) { > + *val++ = '\0'; > + val = skip_spaces(val); > + } else > + continue; key = strsep(&line, ' \t'); val = strsep(&line, '\n'); val = isempty(val) ? NULL : skip_spaces(val); > + > + if (!default_label) { > + if (!strcasecmp(key, "DEFAULT")) > + default_label = xstrdup(val); > + > + continue; > + } > + > + if (!strcasecmp(key, "LABEL")) { > + if (!strcmp(val, default_label)) { defaut_label might not have been set here? You can use streq_ptr which includes NULL pointer checks. > + entry = xzalloc(sizeof(*entry)); > + entry->label = xstrdup(val); > + entry->rootpath = dirname(xstrdup(abspath)); > + } else if (entry) > + break; Kernel coding style is keeping the { braces } for an else when the if has some. > + continue; > + } > + > + /* > + * The same rootfs image may be launched from eMMC or SD card. > + * Remove any hardcoded root= parameter from "append" to avoid > + * conflicts, then let barebox automatically add the correct > + * root= (via appendroot) based on the boot device. > + */ I understand the thought process, but this feels very invasive. What if the extlinux.conf files are on a different partition? I think that's not too uncommon for systems that have a ROM-code mandated FAT partition anyway. At the very least, make this dependent on a parameter being set, maybe just global.bootm.appendroot? > + if (entry) { > + if (!strcasecmp(key, "KERNEL")) > + entry->kernel = xstrdup(val); > + else if (!strcasecmp(key, "INITRD")) > + entry->initrd = xstrdup(val); > + else if (!strcasecmp(key, "FDTDIR")) > + entry->fdtdir = xstrdup(val); > + else if (!strcasecmp(key, "FDT")) > + entry->fdt = xstrdup(val); > + else if (!strcasecmp(key, "APPEND")) > + entry->append = remove_param(val, "ROOT="); > + else > + pr_debug("Unhandled key: %s\n", key); I would make this a pr_warn or at least a pr_info, so new users have an easier time knowing why something doesn't work. > + } > + } > + > + free(default_label); > + free(bufptr); > + > + if (!entry || !entry->kernel) { > + if (entry) > + extlinux_entry_free(&entry->entry); > + return ERR_PTR(-EINVAL); > + } > + > + return entry; > +} > + > +static int extlinux_scan_file(struct bootscanner *scanner, > + struct bootentries *bootentries, > + const char *configname) > +{ > + struct extlinux_entry *e; > + const char *rootpath; > + > + if (!strends(configname, "extlinux.conf")) > + return 0; > + > + rootpath = get_mounted_path(configname); > + if (IS_ERR(rootpath)) > + return PTR_ERR(rootpath); This means you don't support this file existing at a subdirectory of a mountpoint. That can be useful though if one is using ostree or if we include extlinux.conf files in the environment for testing. Please add an intermediate __extlinux_scan_file that takes rootpath, see how blspec does it. > + > + e = parse_extlinux_conf(configname, rootpath); > + if (IS_ERR(e)) > + return PTR_ERR(e); > + > + e->entry.boot = extlinux_boot; > + e->entry.release = extlinux_entry_free; > + e->entry.path = xstrdup(configname); xstrdup_const > + e->entry.title = basprintf("extlinux: %s", e->label); > + e->entry.description = basprintf("extlinux entry \'%s\" on %s", > + e->label, rootpath); > + e->entry.me.type = MENU_ENTRY_NORMAL; > + > + bootentries_add_entry(bootentries, &e->entry); > + > + return 1; > +} > + > +static int extlinux_scan_directory(struct bootscanner *scanner, > + struct bootentries *bootentries, > + const char *rootpath) > +{ > + char *path; > + struct stat s; > + int ret; > + > + path = basprintf("%s/boot/extlinux/extlinux.conf", rootpath); You mention both /boot/extlinux/extlinux and /extlinux/extlinux as directory, but you only check one of them here. Should you not check the second one as well? > + ret = stat(path, &s); > + if (!ret && S_ISREG(s.st_mode)) A extlinux.conf _directory_ is silently skipped by this. Intentional? > + ret = extlinux_scan_file(scanner, bootentries, path); You should pass along rootpath here. > + > + free(path); > + > + return ret < 1 ? ret : 1; This can be simplified to return ret; > +} > + > +static struct bootscanner extlinux_scanner = { > + .name = "extlinux", > + .scan_file = extlinux_scan_file, > + .scan_directory = extlinux_scan_directory, This implements boot -l /mnt/mmc0.1/boot/extlinux/extlinux.conf boot -l /mnt/mmc0.1/ and leaves the rest to the core. I think that's fine, but can you check if the following work: boot -l mmc0 boot -l /dev/mmc0 boot -l mmc0.1 boot -l /dev/mmc0.1 > +}; > + > +static int extlinux_generate(struct bootentries *bootentries, const char *name) > +{ > + return bootentry_scan_generate(&extlinux_scanner, bootentries, name); > +} > + > +static struct bootentry_provider extlinux_provider = { > + .name = "extlinux", > + .generate = extlinux_generate, You need to set a negative priority here, so existing bootloader spec support wins if both are available. I think .priority = -25 is ok, so it's in-between blspec and efiboomgr. > +}; > + > +static int extlinux_init(void) > +{ > + return bootentry_register_provider(&extlinux_provider); > +} > +device_initcall(extlinux_init); Thanks, Ahmad -- 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 | ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/2] Add support for extlinux.conf 2026-04-22 9:10 ` [PATCH 1/2] Add support for extlinux.conf Ahmad Fatoum @ 2026-04-24 8:46 ` Alexander Shiyan 2026-04-24 14:53 ` Ahmad Fatoum 0 siblings, 1 reply; 10+ messages in thread From: Alexander Shiyan @ 2026-04-24 8:46 UTC (permalink / raw) To: Ahmad Fatoum; +Cc: barebox Hello Ahmad. > Thanks for your patch! > > On 4/16/26 3:45 PM, 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. ... > > +static int extlinux_boot(struct bootentry *be, int verbose, int dryrun) > > +{ > > + struct extlinux_entry *e = > > + container_of(be, 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); > > + data.appendroot = true; > > Not sure this is a good idea because of potential of clashing with > extlinux appended command line options. globalvar_add_bool("extlinux.fix_root", NULL); ? ... > > + if (e->append) > > + globalvar_add_simple("linux.bootargs.dyn.extlinux", e->append); > > + > > + pr_info("Booting extlinux label '%s'\n", e->label); > > + > > + ret = bootm_boot(&data); > > Please make use of new bootm_entry instead, so it can be used with devboot: > > https://github.com/barebox/barebox/blob/next/Documentation/user/devboot.rst I haven't figured out how to do this yet... ... > > +static struct extlinux_entry *parse_extlinux_conf(const char *abspath, > > + const char *rootpath) > > +{ > > + char *buf, *bufptr, *line, *p, *default_label = NULL; > > + struct extlinux_entry *entry = NULL; > > + > > + bufptr = read_file(abspath, NULL); > > + if (!bufptr) > > + return ERR_PTR(-errno); > > + > > + for (p = bufptr; *p; p++) > > + if (*p == '\r') > > + *p = '\n'; > > I think this can be dropped. > > > + > > + buf = bufptr; > > + while ((line = strsep(&buf, "\n")) != NULL) { > > And then you replace the set searched here with "\r\n" The end of the line may be \n, \r, \n\r. We are simply converting it to a uniform format. > > + char *key, *val; > > + > > + line = skip_spaces(line); > > + > > + if (*line == '#' || *line == '\0') > > + continue; > > + > > Nitpick: I think below can be simplified to: > > > + key = line; > > + val = strchr(line, ' '); > > + if (!val) > > + val = strchr(line, '\t'); > > + if (val) { > > + *val++ = '\0'; > > + val = skip_spaces(val); > > + } else > > + continue; > > key = strsep(&line, ' \t'); > val = strsep(&line, '\n'); > val = isempty(val) ? NULL : skip_spaces(val); strsep inserts a null byte in place of the separator; this will corrupt the buffer, and consequently, we will not be able to find the val. > > + > > + if (!default_label) { > > + if (!strcasecmp(key, "DEFAULT")) > > + default_label = xstrdup(val); > > + > > + continue; > > + } > > + > > + if (!strcasecmp(key, "LABEL")) { > > + if (!strcmp(val, default_label)) { > > defaut_label might not have been set here? No: if (!default_label) ... continue; ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/2] Add support for extlinux.conf 2026-04-24 8:46 ` Alexander Shiyan @ 2026-04-24 14:53 ` Ahmad Fatoum 2026-04-27 8:58 ` Sascha Hauer 0 siblings, 1 reply; 10+ messages in thread From: Ahmad Fatoum @ 2026-04-24 14:53 UTC (permalink / raw) To: Alexander Shiyan; +Cc: barebox Hello, On 4/24/26 10:46 AM, Alexander Shiyan wrote: >> On 4/16/26 3:45 PM, 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. > ... >>> +static int extlinux_boot(struct bootentry *be, int verbose, int dryrun) >>> +{ >>> + struct extlinux_entry *e = >>> + container_of(be, 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); >>> + data.appendroot = true; >> >> Not sure this is a good idea because of potential of clashing with >> extlinux appended command line options. > > globalvar_add_bool("extlinux.fix_root", NULL); ? global.extlinux.strip_root to remove root= and bootm.appendroot to add barebox' own root? @Sascha, any thoughts on this? > > ... >>> + if (e->append) >>> + globalvar_add_simple("linux.bootargs.dyn.extlinux", e->append); >>> + >>> + pr_info("Booting extlinux label '%s'\n", e->label); >>> + >>> + ret = bootm_boot(&data); >> >> Please make use of new bootm_entry instead, so it can be used with devboot: >> >> https://github.com/barebox/barebox/blob/next/Documentation/user/devboot.rst > > I haven't figured out how to do this yet... Just make sure it can be used by calling bootm_entry instead of bootm_boot. > ... >>> +static struct extlinux_entry *parse_extlinux_conf(const char *abspath, >>> + const char *rootpath) >>> +{ >>> + char *buf, *bufptr, *line, *p, *default_label = NULL; >>> + struct extlinux_entry *entry = NULL; >>> + >>> + bufptr = read_file(abspath, NULL); >>> + if (!bufptr) >>> + return ERR_PTR(-errno); >>> + >>> + for (p = bufptr; *p; p++) >>> + if (*p == '\r') >>> + *p = '\n'; >> >> I think this can be dropped. >> >>> + >>> + buf = bufptr; >>> + while ((line = strsep(&buf, "\n")) != NULL) { >> >> And then you replace the set searched here with "\r\n" > > The end of the line may be \n, \r, \n\r. > We are simply converting it to a uniform format. strsep's second argument means split at any of these characters and not split at them in exactly that order. > >>> + char *key, *val; >>> + >>> + line = skip_spaces(line); >>> + >>> + if (*line == '#' || *line == '\0') >>> + continue; >>> + >> >> Nitpick: I think below can be simplified to: >> >>> + key = line; >>> + val = strchr(line, ' '); >>> + if (!val) >>> + val = strchr(line, '\t'); >>> + if (val) { >>> + *val++ = '\0'; >>> + val = skip_spaces(val); >>> + } else >>> + continue; >> >> key = strsep(&line, ' \t'); >> val = strsep(&line, '\n'); >> val = isempty(val) ? NULL : skip_spaces(val); > > strsep inserts a null byte in place of the separator; this will > corrupt the buffer, > and consequently, we will not be able to find the val. char line[] = "DEFAULT test", *p = line; char *key = strsep(&p, " \t"); char *val = strsep(&p, "\n"); printf("key<%s> value<%s>\n", key, val); prints key<DEFAULT> value<test>. Isn't that exactly what you need? >> defaut_label might not have been set here? > > No: if (!default_label) ... continue; Ah ok. Cheers, Ahmad -- 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 | ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/2] Add support for extlinux.conf 2026-04-24 14:53 ` Ahmad Fatoum @ 2026-04-27 8:58 ` Sascha Hauer 2026-04-27 17:34 ` Alexander Shiyan 2026-05-04 13:29 ` Ahmad Fatoum 0 siblings, 2 replies; 10+ messages in thread From: Sascha Hauer @ 2026-04-27 8:58 UTC (permalink / raw) To: Ahmad Fatoum; +Cc: Alexander Shiyan, barebox On Fri, Apr 24, 2026 at 04:53:59PM +0200, Ahmad Fatoum wrote: > Hello, > > On 4/24/26 10:46 AM, Alexander Shiyan wrote: > >> On 4/16/26 3:45 PM, 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. > > ... > >>> +static int extlinux_boot(struct bootentry *be, int verbose, int dryrun) > >>> +{ > >>> + struct extlinux_entry *e = > >>> + container_of(be, 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); > >>> + data.appendroot = true; > >> > >> Not sure this is a good idea because of potential of clashing with > >> extlinux appended command line options. > > > > globalvar_add_bool("extlinux.fix_root", NULL); ? > > global.extlinux.strip_root to remove root= > and bootm.appendroot to add barebox' own root? We already have the latter, so nothing to do here. Shouldn't we by default remove the root= option once data->appendroot is set? Also in the bootspec case we do not want to end up with two root= options. 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 | ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/2] Add support for extlinux.conf 2026-04-27 8:58 ` Sascha Hauer @ 2026-04-27 17:34 ` Alexander Shiyan 2026-05-04 13:29 ` Ahmad Fatoum 1 sibling, 0 replies; 10+ messages in thread From: Alexander Shiyan @ 2026-04-27 17:34 UTC (permalink / raw) To: Sascha Hauer; +Cc: Ahmad Fatoum, barebox Hello, Sasha. ... > > >>> 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. > > > ... > > >>> +static int extlinux_boot(struct bootentry *be, int verbose, int dryrun) > > >>> +{ > > >>> + struct extlinux_entry *e = > > >>> + container_of(be, 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); > > >>> + data.appendroot = true; > > >> > > >> Not sure this is a good idea because of potential of clashing with > > >> extlinux appended command line options. > > > > > > globalvar_add_bool("extlinux.fix_root", NULL); ? > > > > global.extlinux.strip_root to remove root= > > and bootm.appendroot to add barebox' own root? > > We already have the latter, so nothing to do here. > > Shouldn't we by default remove the root= option once data->appendroot is > set? Also in the bootspec case we do not want to end up with two root= > options. Is this method better? I haven't tested it yet, but it goes something like this: if (getenv_bool("bootm.appendroot", (int *)&data.appendroot)) data.appendroot = true; if (e->append) { /* * The same rootfs image may be launched from eMMC or SD card. * Remove any hardcoded root= parameter from "append" to avoid * conflicts, then let barebox automatically add the correct * root= (via appendroot) based on the boot device. */ if (data.appendroot) { char *append = remove_param(e->append, "ROOT="); free(e->append); e->append = append; } globalvar_add_simple("linux.bootargs.dyn.extlinux", e->append); } ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/2] Add support for extlinux.conf 2026-04-27 8:58 ` Sascha Hauer 2026-04-27 17:34 ` Alexander Shiyan @ 2026-05-04 13:29 ` Ahmad Fatoum 1 sibling, 0 replies; 10+ messages in thread From: Ahmad Fatoum @ 2026-05-04 13:29 UTC (permalink / raw) To: Sascha Hauer; +Cc: Alexander Shiyan, barebox Hello Sascha, On 4/27/26 10:58 AM, Sascha Hauer wrote: > On Fri, Apr 24, 2026 at 04:53:59PM +0200, Ahmad Fatoum wrote: >> Hello, >> >> On 4/24/26 10:46 AM, Alexander Shiyan wrote: >>>> On 4/16/26 3:45 PM, 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. >>> ... >>>>> +static int extlinux_boot(struct bootentry *be, int verbose, int dryrun) >>>>> +{ >>>>> + struct extlinux_entry *e = >>>>> + container_of(be, 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); >>>>> + data.appendroot = true; >>>> >>>> Not sure this is a good idea because of potential of clashing with >>>> extlinux appended command line options. >>> >>> globalvar_add_bool("extlinux.fix_root", NULL); ? >> >> global.extlinux.strip_root to remove root= >> and bootm.appendroot to add barebox' own root? > > We already have the latter, so nothing to do here. > > Shouldn't we by default remove the root= option once data->appendroot is > set? Also in the bootspec case we do not want to end up with two root= > options. I think we can't get this to work properly anyhow. Besides root= there are other options as well (e.g. rootfstype) that we won't be able to exhaustively remove. Add on top of that, that an initrd may decide for itself that another rootfs should be used anyway... If a user knows for a given system that appending root= will work, they can do that, but I think it's useful for the cases where it doesn't work that there are two root='s, so the root appending is directly apparent. We just need to ensure the appended root comes last, so it has precedence. Cheers, Ahmad > > 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 | ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2026-05-04 13:29 UTC | newest] Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2026-04-16 13:45 [PATCH 1/2] Add support for extlinux.conf Alexander Shiyan 2026-04-16 13:45 ` [PATCH 2/2] Documentation: add extlinux.conf support description Alexander Shiyan 2026-04-22 9:14 ` Ahmad Fatoum 2026-04-24 8:19 ` Alexander Shiyan 2026-04-22 9:10 ` [PATCH 1/2] Add support for extlinux.conf Ahmad Fatoum 2026-04-24 8:46 ` Alexander Shiyan 2026-04-24 14:53 ` Ahmad Fatoum 2026-04-27 8:58 ` Sascha Hauer 2026-04-27 17:34 ` Alexander Shiyan 2026-05-04 13:29 ` Ahmad Fatoum
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox