* [PATCH 00/10] boot: revert boot related globalvars after booting
@ 2026-10-30 10:53 Sascha Hauer
2026-10-30 10:53 ` [PATCH 01/10] globalvar: add scopes to snapshot and restore globalvars Sascha Hauer
` (9 more replies)
0 siblings, 10 replies; 11+ messages in thread
From: Sascha Hauer @ 2026-10-30 10:53 UTC (permalink / raw)
To: BAREBOX
Boot entries configure booting through globalvars like global.bootm.*,
global.linux.bootargs.* or global.of.overlay.*. So far only some of these
were restored after a boot entry returned, by saving a fixed set of
variables and by clearing the global.linux.bootargs.dyn.* namespace.
This series adds globalvar scopes, which snapshot all globalvars with
given prefixes and restore them later, and uses them around each boot
entry, bootm and bootchooser boot attempts. With that the .dyn infix is
no longer needed, so it is dropped from the boot entries barebox ships.
The series is based on the "boot: UAF and double free fixes" series.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
Sascha Hauer (10):
globalvar: add scopes to snapshot and restore globalvars
bootm: revert globalvar changes in bootm_boot_cleanup()
boot: revert globalvar changes after each boot entry
bootchooser: use a globalvar scope for its bootargs
test: py: add test for reverting globalvars after boot
bootargs: remove unused linux_bootargs_overwrite()
of: add watchdog bootarg directly instead of via a globalvar
boot: drop the dyn infix from the bootentries bootargs variable
defaultenv: don't use global.linux.bootargs.dyn.* in boot entries
Documentation: migration-guides: describe reverting boot globalvars
.../migration-master/boot-globalvar-scope.rst | 13 ++
Documentation/user/booting-linux.rst | 27 ++--
Documentation/user/devboot.rst | 4 +-
common/Kconfig | 6 +-
common/blspec.c | 2 +-
common/boot.c | 35 ++---
common/bootargs.c | 17 ---
common/bootchooser.c | 6 +-
common/bootm.c | 27 +---
common/extlinux.c | 2 +-
common/globalvar.c | 142 +++++++++++++++++++++
common/oftree.c | 41 +++---
defaultenv/defaultenv-2-base/boot/net | 5 +-
defaultenv/defaultenv-2-base/data/boot-template | 2 +-
defaultenv/defaultenv-2-dfu/boot/dfu | 4 +-
include/boot.h | 16 +++
include/bootargs.h | 5 -
include/bootm.h | 9 +-
include/globalvar.h | 29 +++++
test/py/test_boot_globalvar_scope.py | 117 +++++++++++++++++
20 files changed, 396 insertions(+), 113 deletions(-)
---
base-commit: 9ae453b11d9e222b33247c95405f6a74ee845fa0
change-id: 20261030-boot-globalvar-stack-9c65609b5801
Best regards,
--
Sascha Hauer <s.hauer@pengutronix.de>
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 01/10] globalvar: add scopes to snapshot and restore globalvars
2026-10-30 10:53 [PATCH 00/10] boot: revert boot related globalvars after booting Sascha Hauer
@ 2026-10-30 10:53 ` Sascha Hauer
2026-10-30 10:54 ` [PATCH 02/10] bootm: revert globalvar changes in bootm_boot_cleanup() Sascha Hauer
` (8 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Sascha Hauer @ 2026-10-30 10:53 UTC (permalink / raw)
To: BAREBOX
Code that runs foreign code, like boot scripts, often wants to revert
whatever that code changed in the global namespace afterwards. So far
this is done by hand for each use case: either by saving and restoring a
fixed list of variables, or by putting variables into a dedicated
namespace which is cleared afterwards.
Add globalvar_scope_push() and globalvar_scope_pop() to do this
generically. A scope records the current values of all globalvars whose
name begins with one of the given prefixes. Popping it restores changed
values, removes variables created in the meantime and creates removed
variables again. Variables are only removed or recreated if they were
created with globalvar_add_simple(), which is what the shell's global
command and most dynamically created variables use. For all other
globalvars, which are backed by a C variable, only the value is
restored, through the regular setter so the C variable follows.
Scopes can be nested as long as they are popped in reverse order.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
common/globalvar.c | 142 ++++++++++++++++++++++++++++++++++++++++++++++++++++
include/globalvar.h | 29 +++++++++++
2 files changed, 171 insertions(+)
diff --git a/common/globalvar.c b/common/globalvar.c
index 876379b253..4686378ded 100644
--- a/common/globalvar.c
+++ b/common/globalvar.c
@@ -456,6 +456,148 @@ void globalvar_set_match(const char *match, const char *val)
}
}
+struct globalvar_scope_var {
+ struct list_head list;
+ char *name;
+ char *value;
+ bool unqualified;
+ bool seen;
+};
+
+struct globalvar_scope {
+ const char * const *prefixes;
+ struct list_head vars;
+};
+
+static bool globalvar_scope_match(const struct globalvar_scope *scope,
+ const char *name)
+{
+ const char * const *prefix;
+
+ for (prefix = scope->prefixes; *prefix; prefix++)
+ if (str_has_prefix(name, *prefix))
+ return true;
+
+ return false;
+}
+
+static struct globalvar_scope_var *
+globalvar_scope_find(struct globalvar_scope *scope, const char *name)
+{
+ struct globalvar_scope_var *var;
+
+ list_for_each_entry(var, &scope->vars, list)
+ if (!strcmp(var->name, name))
+ return var;
+
+ return NULL;
+}
+
+/**
+ * __globalvar_scope_push - snapshot a set of globalvars
+ * @prefixes: NULL terminated array of name prefixes to snapshot, which
+ * must stay valid until globalvar_scope_pop()
+ *
+ * Records the current value of all globalvars whose name starts with one
+ * of @prefixes. A later globalvar_scope_pop() reverts all changes done
+ * to these variables in the meantime, including adding and removing them.
+ * Scopes can be nested, but must be popped in reverse order.
+ *
+ * Return: the scope to be passed to globalvar_scope_pop()
+ */
+struct globalvar_scope *__globalvar_scope_push(const char * const *prefixes)
+{
+ struct globalvar_scope *scope;
+ struct param_d *p;
+
+ scope = xzalloc(sizeof(*scope));
+ scope->prefixes = prefixes;
+ INIT_LIST_HEAD(&scope->vars);
+
+ dev_for_each_param(&global_device, p) {
+ struct globalvar_scope_var *var;
+
+ if (!globalvar_scope_match(scope, p->name))
+ continue;
+
+ var = xzalloc(sizeof(*var));
+ var->name = xstrdup(p->name);
+ var->value = xstrdup(p->get(p->bobj, p) ?: "");
+ var->unqualified = p->flags & PARAM_GLOBALVAR_UNQUALIFIED;
+ list_add_tail(&var->list, &scope->vars);
+ }
+
+ return scope;
+}
+
+/**
+ * globalvar_scope_pop - revert globalvars to a snapshot
+ * @scope: the scope returned by globalvar_scope_push()
+ *
+ * Restores all globalvars covered by @scope to the values they had when
+ * the scope was pushed: changed values are set back, variables created
+ * in the meantime are removed and removed variables are created again.
+ * Variables which were not created with globalvar_add_simple() are never
+ * removed or recreated, only their values are restored.
+ *
+ * @scope is freed afterwards.
+ */
+void globalvar_scope_pop(struct globalvar_scope *scope)
+{
+ struct globalvar_scope_var *var, *vtmp;
+ struct param_d *p, *tmp;
+ int ret;
+
+ if (!scope)
+ return;
+
+ dev_for_each_param_safe(&global_device, p, tmp) {
+ const char *cur;
+
+ if (!globalvar_scope_match(scope, p->name))
+ continue;
+
+ var = globalvar_scope_find(scope, p->name);
+ if (!var) {
+ if (!(p->flags & PARAM_GLOBALVAR_UNQUALIFIED))
+ continue;
+
+ pr_debug("scope: removing global.%s\n", p->name);
+ param_remove(p);
+ continue;
+ }
+
+ var->seen = true;
+
+ cur = p->get(p->bobj, p) ?: "";
+ if (!strcmp(cur, var->value))
+ continue;
+
+ pr_debug("scope: restoring global.%s: \"%s\" -> \"%s\"\n",
+ p->name, cur, var->value);
+
+ ret = dev_set_param(&global_device, p->name, var->value);
+ if (ret)
+ pr_warn("Cannot restore global.%s=\"%s\": %pe\n",
+ p->name, var->value, ERR_PTR(ret));
+ }
+
+ list_for_each_entry_safe(var, vtmp, &scope->vars, list) {
+ if (!var->seen && var->unqualified) {
+ pr_debug("scope: recreating global.%s=\"%s\"\n",
+ var->name, var->value);
+ globalvar_add_simple(var->name, var->value);
+ }
+
+ list_del(&var->list);
+ free(var->name);
+ free(var->value);
+ free(var);
+ }
+
+ free(scope);
+}
+
void globalvar_set(const char *name, const char *val)
{
dev_set_param(&global_device, name, val);
diff --git a/include/globalvar.h b/include/globalvar.h
index e369616c63..7fbfdd1284 100644
--- a/include/globalvar.h
+++ b/include/globalvar.h
@@ -10,6 +10,24 @@
extern struct device global_device;
+struct globalvar_scope;
+
+/**
+ * globalvar_scope_push - snapshot a set of globalvars
+ * @...: name prefixes of the globalvars to snapshot
+ *
+ * See __globalvar_scope_push(). The scope borrows the prefixes until
+ * globalvar_scope_pop(). Collecting them in a static array makes the
+ * compiler reject prefixes that don't live that long, as only string
+ * literals and addresses of static objects are allowed as initializers.
+ *
+ * Return: the scope to be passed to globalvar_scope_pop()
+ */
+#define globalvar_scope_push(...) ({ \
+ static const char * const __prefixes[] = { __VA_ARGS__, NULL }; \
+ __globalvar_scope_push(__prefixes); \
+})
+
#ifdef CONFIG_GLOBALVAR
static inline const char *globalvar_get(const char *name)
@@ -24,6 +42,9 @@ char *globalvar_get_match(const char *match, const char *separator);
void globalvar_set_match(const char *match, const char *val);
void globalvar_set(const char *name, const char *val);
+struct globalvar_scope *__globalvar_scope_push(const char * const *prefixes);
+void globalvar_scope_pop(struct globalvar_scope *scope);
+
int globalvar_add_simple_string(const char *name, char **value);
int globalvar_add_simple_int(const char *name, int *value,
const char *format);
@@ -126,6 +147,14 @@ static inline void globalvar_set_match(const char *match, const char *val) {}
static inline void globalvar_set(const char *name, const char *val) {}
+static inline struct globalvar_scope *
+__globalvar_scope_push(const char * const *prefixes)
+{
+ return NULL;
+}
+
+static inline void globalvar_scope_pop(struct globalvar_scope *scope) {}
+
static inline int nvvar_load(void)
{
return 0;
--
2.47.3
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 02/10] bootm: revert globalvar changes in bootm_boot_cleanup()
2026-10-30 10:53 [PATCH 00/10] boot: revert boot related globalvars after booting Sascha Hauer
2026-10-30 10:53 ` [PATCH 01/10] globalvar: add scopes to snapshot and restore globalvars Sascha Hauer
@ 2026-10-30 10:54 ` Sascha Hauer
2026-10-30 10:54 ` [PATCH 03/10] boot: revert globalvar changes after each boot entry Sascha Hauer
` (7 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Sascha Hauer @ 2026-10-30 10:54 UTC (permalink / raw)
To: BAREBOX
bootm adds the Kernel command line options it generates itself as
global.linux.bootargs.!bootm.* and global.linux.bootargs.~bootm.*
variables and removes them again in bootm_boot_cleanup(). Anything else
bootm or the image handlers change in the global namespace while booting
stays, for example global.linux.bootargs.dyn.watchdog which is added by
the devicetree fixups and only cleared again when booting through the
boot command.
Add boot_globalvar_scope_push() which snapshots the globalvars that
configure booting, take a snapshot in bootm_boot_prep() and restore it in
bootm_boot_cleanup(). This covers the variables bootm removed so far, so
drop the explicit removal.
Besides global.bootm.* and global.linux.bootargs.*, the scope covers the
rest of global.linux.*, like global.linux.bootargs_append, which
global.linux.bootargs.* doesn't match, or global.linux.rootwait, then
global.of.*, which includes the global.of.overlay.* variables selecting
the overlays applied to the Kernel device tree, and
global.boot.watchdog_timeout.
It deliberately doesn't cover all globalvars: booting legitimately
changes others, which must persist. For example DHCP sets
global.net.server, global.net.gateway and global.hostname, and reverting
them while the interface stays up would leave the network unusable, as a
later ifup doesn't run DHCP again.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
common/bootm.c | 6 ++++--
include/boot.h | 16 ++++++++++++++++
include/bootm.h | 8 +++++++-
3 files changed, 27 insertions(+), 3 deletions(-)
diff --git a/common/bootm.c b/common/bootm.c
index bcd557d679..22f2ca4081 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -2,6 +2,7 @@
#include <common.h>
#include <bootargs.h>
+#include <boot.h>
#include <bootm.h>
#include <fs.h>
#include <fcntl.h>
@@ -533,6 +534,8 @@ struct image_data *bootm_boot_prep(const struct bootm_data *bootm_data)
data = xzalloc(sizeof(*data));
+ data->globalvar_scope = boot_globalvar_scope_push();
+
bootm_image_name_and_part(bootm_data->os_file, &data->os_file, &data->os_part);
bootm_image_name_and_part(bootm_data->oftree_file, &data->oftree_file, &data->oftree_part);
bootm_image_name_and_part(bootm_data->initrd_file, &data->initrd_file, &data->initrd_part);
@@ -792,8 +795,7 @@ void bootm_boot_cleanup(struct image_data *data)
if (data->of_root_node)
of_delete_node(data->of_root_node);
- globalvar_remove(LINUX_BOOTARGS_BOOTM_EARLY "*");
- globalvar_remove(LINUX_BOOTARGS_BOOTM_LATE "*");
+ globalvar_scope_pop(data->globalvar_scope);
free(data->os_header);
free(data->os_file);
free(data->oftree_file);
diff --git a/include/boot.h b/include/boot.h
index 57f9cb409b..b30cdd314a 100644
--- a/include/boot.h
+++ b/include/boot.h
@@ -7,6 +7,7 @@
#include <environment.h>
#include <bootm-overrides.h>
#include <bootargs.h>
+#include <globalvar.h>
struct bootentries {
struct list_head entries;
@@ -58,4 +59,19 @@ int boot_entry(struct bootentry *be, int verbose, int dryrun);
struct bootm_data;
int bootm_entry(struct bootentry *be, const struct bootm_data *data);
+/*
+ * Snapshot all globalvars that configure booting. Whatever a boot script,
+ * a boot entry or bootm itself changes there is reverted again by
+ * globalvar_scope_pop(), so it doesn't leak into the next boot attempt.
+ *
+ * This deliberately doesn't cover all globalvars: booting may change
+ * others that must persist, e.g. DHCP sets global.net.* and
+ * global.hostname while the interface stays up.
+ */
+static inline struct globalvar_scope *boot_globalvar_scope_push(void)
+{
+ return globalvar_scope_push("bootm.", "linux.", "of.",
+ "boot.watchdog_timeout");
+}
+
#endif /* __BOOT_H */
diff --git a/include/bootm.h b/include/bootm.h
index 8e574040f4..bbdbb8e69d 100644
--- a/include/bootm.h
+++ b/include/bootm.h
@@ -16,7 +16,8 @@
* ! 0x21 is less than any non-space printable character
* ~ 0x7e is greater than any printable character
*
- * Users will never see those as bootm_boot_cleanup() will delete them again.
+ * Users will never see those as bootm_boot_cleanup() reverts the globalvars
+ * to the state before bootm_boot_prep().
*/
#define LINUX_BOOTARGS_BOOTM_EARLY "linux.bootargs.!bootm."
#define LINUX_BOOTARGS_BOOTM_LATE "linux.bootargs.~bootm."
@@ -80,7 +81,12 @@ int bootm_open_os_compressed(struct image_data *data);
int bootm_boot_handler(struct image_data *data);
void bootm_boot_cleanup(struct image_data *data);
+struct globalvar_scope;
+
struct image_data {
+ /* globalvars to restore in bootm_boot_cleanup() */
+ struct globalvar_scope *globalvar_scope;
+
/* simplest case. barebox has already loaded the os here */
struct resource *os_res;
--
2.47.3
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 03/10] boot: revert globalvar changes after each boot entry
2026-10-30 10:53 [PATCH 00/10] boot: revert boot related globalvars after booting Sascha Hauer
2026-10-30 10:53 ` [PATCH 01/10] globalvar: add scopes to snapshot and restore globalvars Sascha Hauer
2026-10-30 10:54 ` [PATCH 02/10] bootm: revert globalvar changes in bootm_boot_cleanup() Sascha Hauer
@ 2026-10-30 10:54 ` Sascha Hauer
2026-10-30 10:54 ` [PATCH 04/10] bootchooser: use a globalvar scope for its bootargs Sascha Hauer
` (6 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Sascha Hauer @ 2026-10-30 10:54 UTC (permalink / raw)
To: BAREBOX
Boot entries, especially boot scripts, configure the boot by setting
global.bootm.* and global.linux.bootargs.* variables. To keep these from
leaking into the boot entries tried afterwards, there are currently two
mechanisms:
- bootscript_boot() saves the global.bootm.* variables that are part of
struct bootm_data and restores them afterwards. Variables not part of
this struct, like global.bootm.tee, are not restored, and empty load
addresses come back as the hex values of UIMAGE_SOME_ADDRESS resp.
UIMAGE_INVALID_ADDRESS.
- Kernel command line options have to be put into
global.linux.bootargs.dyn.*, which boot_entry() clears after each boot
entry. Options set by a boot entry in any other variable stay.
Replace both with a globalvar scope around the boot entry in
boot_entry(). This reverts all changes to the globalvars covered by
boot_globalvar_scope_push(), whatever the variable, and also restores
values that were set before the boot entry instead of clearing them.
This includes global.boot.watchdog_timeout, which boot_entry() reads
before running the boot entry, so a value set by a boot entry so far only
took effect for the following ones.
global.linux.bootargs.dyn.* still works as before for boot entries, but
values set in this namespace before calling boot are now kept instead of
being cleared once the first boot entry returns.
bootm_data_restore_defaults() has no users anymore, so remove it.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
Documentation/user/booting-linux.rst | 20 ++++++++++++++------
Documentation/user/devboot.rst | 4 ++--
common/boot.c | 35 ++++++++---------------------------
common/bootm.c | 21 ---------------------
include/bootm.h | 1 -
5 files changed, 24 insertions(+), 57 deletions(-)
diff --git a/Documentation/user/booting-linux.rst b/Documentation/user/booting-linux.rst
index afc705ac86..0fbdc52c68 100644
--- a/Documentation/user/booting-linux.rst
+++ b/Documentation/user/booting-linux.rst
@@ -164,16 +164,24 @@ A simple boot entry in ``/env/boot/mmc`` could look like this:
global.bootm.image=/mnt/mmc1/zImage
global.bootm.oftree=/env/oftree
- global linux.bootargs.dyn.root="root=PARTUUID=deadbeef:01"
+ global linux.bootargs.root="root=PARTUUID=deadbeef:01"
This takes the kernel from ``/mnt/mmc1/zImage`` (which could be an
:ref:`automount` path registered earlier). The devicetree will be used from
``/env/oftree``. The Kernel gets the command line
-``root=PARTUUID=deadbeef:01``. Note the ``.dyn`` in the bootargs variable name.
-boot entries should always add Kernel command line parameters to variables with
-``.dyn`` in it. These will be cleared before booting different boot entries.
-This is done so that following boot entries do not leak command line
-parameters from the previous boot entries.
+``root=PARTUUID=deadbeef:01``.
+
+All changes a boot entry makes to ``global.bootm.*``, ``global.linux.*``,
+``global.of.*`` and
+:ref:`global.boot.watchdog_timeout <magicvar_global_boot_watchdog_timeout>`
+are reverted when the boot entry returns:
+modified variables get their previous value back, variables created by
+the boot entry are removed and variables it removed are created again.
+This way a boot entry that fails to boot doesn't leak its settings into
+the following boot entries. Older boot entries put their Kernel command
+line parameters into ``global.linux.bootargs.dyn.*`` for this reason,
+which still works, but is no longer necessary. Settings meant for all
+boot entries belong into an init script or an nv variable instead.
This entry can be booted with ``boot mmc``. It can also be made the default by
setting the :ref:`global.boot.default <magicvar_global_boot_default>` variable
diff --git a/Documentation/user/devboot.rst b/Documentation/user/devboot.rst
index e319636994..62cc357c3a 100644
--- a/Documentation/user/devboot.rst
+++ b/Documentation/user/devboot.rst
@@ -191,8 +191,8 @@ when ``CONFIG_BOOTM_OFTREE_FALLBACK`` is enabled), and appends the
contains.
Kernel command line fragments set by the script should use the
-``global.linux.bootargs.devboot.`` namespace. Unlike
-``global.linux.bootargs.dyn.``, which is cleared whenever a boot entry
+``global.linux.bootargs.devboot.`` namespace. Unlike variables set
+by the boot entries themselves, which are reverted whenever a boot entry
returns, it survives falling through to the next boot target, e.g. for
``devboot system0 system1``. The ``devboot`` command removes the
namespace after the boot command returns, so a subsequent plain
diff --git a/common/boot.c b/common/boot.c
index 1d8768b864..eaeff7796e 100644
--- a/common/boot.c
+++ b/common/boot.c
@@ -97,7 +97,7 @@ static int bootscript_boot(struct bootentry *entry, int verbose, int dryrun)
int bootm_nattempts;
int ret;
- struct bootm_data backup = {}, data = {};
+ struct bootm_data data = {};
if (dryrun == 1) {
printf("Would run %s%s%s\n", bs->entry.path,
@@ -105,18 +105,6 @@ static int bootscript_boot(struct bootentry *entry, int verbose, int dryrun)
return 0;
}
- bootm_data_init_defaults(&backup);
-
- /*
- * The strings point to the globalvars' current values, which the
- * script frees when it assigns new ones. Keep our own copies.
- */
- backup.os_file = xstrdup(backup.os_file);
- backup.initrd_file = xstrdup(backup.initrd_file);
- backup.oftree_file = xstrdup(backup.oftree_file);
- backup.root_dev = xstrdup(backup.root_dev);
- backup.root_param = xstrdup(backup.root_param);
-
globalvar_add_simple("linux.bootargs.dyn.ip", NULL);
globalvar_add_simple("linux.bootargs.dyn.root", NULL);
@@ -129,12 +117,12 @@ static int bootscript_boot(struct bootentry *entry, int verbose, int dryrun)
ret = execute_binfmt(bs->args ? 2 : 1, argv);
if (ret) {
pr_err("Running script '%s' failed: %s\n", bs->entry.path, strerror(-ret));
- goto out;
+ return ret;
}
/* No point in repeating bootm if script already called it */
if (bootm_nattempts != bootm_command_attempts())
- goto out;
+ return 0;
bootm_data_init_defaults(&data);
@@ -143,17 +131,7 @@ static int bootscript_boot(struct bootentry *entry, int verbose, int dryrun)
if (dryrun >= 2)
data.dryrun = dryrun - 1;
- ret = bootm_entry(entry, &data);
-out:
- bootm_data_restore_defaults(&backup);
-
- free_const(backup.os_file);
- free_const(backup.initrd_file);
- free_const(backup.oftree_file);
- free_const(backup.root_dev);
- free_const(backup.root_param);
-
- return ret;
+ return bootm_entry(entry, &data);
}
static unsigned int boot_watchdog_timeout;
@@ -210,6 +188,7 @@ BAREBOX_MAGICVAR(global.user,
int boot_entry(struct bootentry *be, int verbose, int dryrun)
{
+ struct globalvar_scope *scope;
int ret;
pr_info("Booting entry '%s'\n", be->title);
@@ -224,11 +203,13 @@ int boot_entry(struct bootentry *be, int verbose, int dryrun)
}
}
+ scope = boot_globalvar_scope_push();
+
ret = be->boot(be, verbose, dryrun);
if (ret && ret != -ENOMEDIUM)
pr_err("Booting entry '%s' failed: %pe\n", be->title, ERR_PTR(ret));
- globalvar_set_match("linux.bootargs.dyn.", "");
+ globalvar_scope_pop(scope);
return ret;
}
diff --git a/common/bootm.c b/common/bootm.c
index 22f2ca4081..2ad8c34bb4 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -101,27 +101,6 @@ void bootm_data_init_defaults(struct bootm_data *data)
data->efi_boot = bootm_efi_mode;
}
-void bootm_data_restore_defaults(const struct bootm_data *data)
-{
- globalvar_set("bootm.oftree", data->oftree_file);
- globalvar_set("bootm.image", data->os_file);
- pr_setenv("global.bootm.image.loadaddr", "0x%lx", data->os_address);
- if (IS_ENABLED(CONFIG_BOOTM_INITRD)) {
- pr_setenv("global.bootm.initrd.loadaddr", "0x%lx", data->initrd_address);
- globalvar_set("bootm.initrd", data->initrd_file);
- }
- globalvar_set("bootm.root_dev", data->root_dev);
- globalvar_set("bootm.root_param", data->root_param);
- bootm_set_verify_mode(data->verify);
- bootm_appendroot = data->appendroot;
- bootm_provide_machine_id = data->provide_machine_id;
- bootm_provide_hostname = data->provide_hostname;
- bootm_provide_policy = data->provide_policy;
- bootm_verbosity = data->verbose;
- bootm_dryrun = data->dryrun;
- bootm_efi_mode = data->efi_boot;
-}
-
static enum bootm_verify bootm_verify_mode = BOOTM_VERIFY_AVAILABLE;
enum bootm_verify bootm_get_verify_mode(void)
diff --git a/include/bootm.h b/include/bootm.h
index bbdbb8e69d..06eb90c5ed 100644
--- a/include/bootm.h
+++ b/include/bootm.h
@@ -196,7 +196,6 @@ static inline int bootm_verbose(struct image_data *data)
#endif
void bootm_data_init_defaults(struct bootm_data *data);
-void bootm_data_restore_defaults(const struct bootm_data *data);
const struct resource *
bootm_load_os(struct image_data *data,
--
2.47.3
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 04/10] bootchooser: use a globalvar scope for its bootargs
2026-10-30 10:53 [PATCH 00/10] boot: revert boot related globalvars after booting Sascha Hauer
` (2 preceding siblings ...)
2026-10-30 10:54 ` [PATCH 03/10] boot: revert globalvar changes after each boot entry Sascha Hauer
@ 2026-10-30 10:54 ` Sascha Hauer
2026-10-30 10:54 ` [PATCH 05/10] test: py: add test for reverting globalvars after boot Sascha Hauer
` (5 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Sascha Hauer @ 2026-10-30 10:54 UTC (permalink / raw)
To: BAREBOX
bootchooser passes the active target to the Kernel in
global.linux.bootargs.bootchooser and sets it to an empty value again
after booting failed. The variable is never removed though, so it stays
around with an empty value after the first boot attempt.
Use a globalvar scope instead, which removes the variable again and
also reverts any other boot related globalvars changed while booting
the target.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
common/bootchooser.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/common/bootchooser.c b/common/bootchooser.c
index 2a75dfdcc8..2049425ab3 100644
--- a/common/bootchooser.c
+++ b/common/bootchooser.c
@@ -6,6 +6,7 @@
#define pr_fmt(fmt) "bootchooser: " fmt
#include <bootchooser.h>
+#include <boot.h>
#include <environment.h>
#include <globalvar.h>
#include <magicvar.h>
@@ -846,6 +847,7 @@ static int bootchooser_boot_one(struct bootchooser *bc, int *tryagain,
struct bootentries *entries;
struct bootentry *entry;
struct bootchooser_target *target;
+ struct globalvar_scope *scope = NULL;
int ret = 0;
entries = bootentries_alloc();
@@ -857,6 +859,8 @@ static int bootchooser_boot_one(struct bootchooser *bc, int *tryagain,
goto out;
}
+ scope = boot_globalvar_scope_push();
+
system = basprintf("bootchooser.active=%s", target->name);
globalvar_add_simple("linux.bootargs.bootchooser", system);
free(system);
@@ -887,7 +891,7 @@ static int bootchooser_boot_one(struct bootchooser *bc, int *tryagain,
*tryagain = 1;
out:
- globalvar_set_match("linux.bootargs.bootchooser", NULL);
+ globalvar_scope_pop(scope);
bootentries_free(entries);
--
2.47.3
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 05/10] test: py: add test for reverting globalvars after boot
2026-10-30 10:53 [PATCH 00/10] boot: revert boot related globalvars after booting Sascha Hauer
` (3 preceding siblings ...)
2026-10-30 10:54 ` [PATCH 04/10] bootchooser: use a globalvar scope for its bootargs Sascha Hauer
@ 2026-10-30 10:54 ` Sascha Hauer
2026-10-30 10:54 ` [PATCH 06/10] bootargs: remove unused linux_bootargs_overwrite() Sascha Hauer
` (4 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Sascha Hauer @ 2026-10-30 10:54 UTC (permalink / raw)
To: BAREBOX
Add tests for the globalvar scope around boot entries: a failing boot
script that changes, creates and removes global.bootm.* and
global.linux.bootargs.* variables and changes global.of.overlay.path and
global.linux.bootargs_append, where the configuration has them, must
leave them as they were before, while globalvars outside the scope keep
their new values. A
second test nests boot entries like devboot does and checks that the
outer entry's variables are visible in the inner one and survive it.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
test/py/test_boot_globalvar_scope.py | 117 +++++++++++++++++++++++++++++++++++
1 file changed, 117 insertions(+)
diff --git a/test/py/test_boot_globalvar_scope.py b/test/py/test_boot_globalvar_scope.py
new file mode 100644
index 0000000000..041d38c814
--- /dev/null
+++ b/test/py/test_boot_globalvar_scope.py
@@ -0,0 +1,117 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+import pytest
+from .helper import devinfo, skip_disabled
+
+
+def write_bootscript(barebox, name, lines):
+ barebox.run_check(f"echo -o /env/boot/{name} '#!/bin/sh'")
+ for line in lines:
+ # Variable references must reach the script unexpanded. Neither
+ # quoting nor a backslash achieves that here, so splice in the
+ # dollar sign from a variable.
+ line = line.replace("$", "${dollar}")
+ barebox.run_check(f"dollar='$'; echo -a /env/boot/{name} \"{line}\"")
+
+
+def globals_now(barebox):
+ params = devinfo(barebox, "global")["Parameters"]
+ # devinfo prints "value (type: ...)", strip the annotation
+ return {k: v.split(" (type:")[0].strip('"') for k, v in params.items()}
+
+
+@pytest.fixture(scope="function")
+def scope_globals(barebox, barebox_config):
+ skip_disabled(barebox_config, "CONFIG_CMD_BOOT", "CONFIG_CMD_GLOBAL",
+ "CONFIG_CMD_ECHO")
+
+ barebox.run_check("global.bootm.image=/preset/image")
+ barebox.run_check("global linux.bootargs.preset=preset=1")
+ barebox.run_check("global linux.bootargs.removed=removed=1")
+ barebox.run_check("global.bootm.appendroot=0")
+ old_user = barebox.run_check("echo ${global.user}")[0]
+
+ yield old_user
+
+ barebox.run_check(f"global.user={old_user}")
+ barebox.run("global -r linux.bootargs.preset")
+ barebox.run("global -r linux.bootargs.removed")
+ barebox.run_check("global.bootm.image=")
+
+
+def test_boot_entry_reverts_globalvars(barebox, scope_globals):
+ old_user = scope_globals
+ before = globals_now(barebox)
+
+ # boot related globalvars outside of bootm.* and linux.bootargs.*,
+ # where the configuration has them
+ others = {var: val for var, val in (("of.overlay.path", "/does/not/exist"),
+ ("linux.bootargs_append", "1"))
+ if var in before}
+
+ write_bootscript(barebox, "scope", [
+ *(f"global.{var}={val}" for var, val in others.items()),
+ "global.bootm.image=/does/not/exist",
+ "global.bootm.oftree=/does/not/exist.dtb",
+ "global.bootm.appendroot=1",
+ "global.linux.bootargs.dyn.root=root=/dev/leak",
+ "global linux.bootargs.leak=leak=1",
+ "global.linux.bootargs.preset=preset=2",
+ "global -r linux.bootargs.removed",
+ "global.user=scope-test",
+ ])
+
+ # bootm fails on the nonexistent image, so boot returns
+ barebox.run("boot scope")
+
+ after = globals_now(barebox)
+
+ # values within the boot scope are restored...
+ assert after["bootm.image"] == "/preset/image"
+ assert after["bootm.oftree"] == before["bootm.oftree"]
+ assert after["bootm.appendroot"] == "0"
+ assert after["linux.bootargs.preset"] == "preset=1"
+ for var in others:
+ assert after[var] == before[var]
+
+ # ...vars created by the boot entry are gone...
+ assert "linux.bootargs.leak" not in after
+ assert "linux.bootargs.dyn.root" not in after
+ assert "linux.bootargs.dyn.ip" not in after
+
+ # ...vars removed by the boot entry are back...
+ assert after["linux.bootargs.removed"] == "removed=1"
+
+ # ...and the loadaddrs don't come back as 0xfffffffe after a failed boot
+ assert after["bootm.image.loadaddr"] == before["bootm.image.loadaddr"]
+
+ # globalvars outside the boot scope are left alone
+ assert after["user"] == "scope-test"
+ assert old_user != "scope-test"
+
+
+@pytest.mark.usefixtures("scope_globals")
+def test_boot_entry_scope_nests(barebox):
+ # devboot-style: an outer entry sets up bootargs that must be visible
+ # in, and survive, the inner boot entry
+ write_bootscript(barebox, "scope-inner", [
+ "global.bootm.image=/does/not/exist",
+ "echo inner-sees ${global.linux.bootargs.outer}",
+ "global.linux.bootargs.outer=outer=clobbered",
+ "global linux.bootargs.inner=inner=1",
+ ])
+ write_bootscript(barebox, "scope-outer", [
+ "global linux.bootargs.outer=outer=1",
+ "boot scope-inner",
+ "echo outer-sees ${global.linux.bootargs.outer} "
+ "inner=${global.linux.bootargs.inner}",
+ ])
+
+ stdout, _, _ = barebox.run("boot scope-outer")
+ assert "inner-sees outer=1" in stdout
+ assert "outer-sees outer=1 inner=" in stdout
+
+ after = globals_now(barebox)
+ assert "linux.bootargs.outer" not in after
+ assert "linux.bootargs.inner" not in after
+ assert after["bootm.image"] == "/preset/image"
--
2.47.3
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 06/10] bootargs: remove unused linux_bootargs_overwrite()
2026-10-30 10:53 [PATCH 00/10] boot: revert boot related globalvars after booting Sascha Hauer
` (4 preceding siblings ...)
2026-10-30 10:54 ` [PATCH 05/10] test: py: add test for reverting globalvars after boot Sascha Hauer
@ 2026-10-30 10:54 ` Sascha Hauer
2026-10-30 10:54 ` [PATCH 07/10] of: add watchdog bootarg directly instead of via a globalvar Sascha Hauer
` (3 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Sascha Hauer @ 2026-10-30 10:54 UTC (permalink / raw)
To: BAREBOX
linux_bootargs_overwrite() lost its last user with commit fe1e02cc68cd
("bootm: add generic android image handler"), which replaced the
old ARM32 specific Android image handler calling it. Remove it together
with the linux_bootargs_overwritten state it maintained.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
common/bootargs.c | 17 -----------------
include/bootargs.h | 5 -----
2 files changed, 22 deletions(-)
diff --git a/common/bootargs.c b/common/bootargs.c
index 6373d9ccb1..06623bb60b 100644
--- a/common/bootargs.c
+++ b/common/bootargs.c
@@ -12,7 +12,6 @@
#include <environment.h>
static char *linux_bootargs;
-static int linux_bootargs_overwritten;
/*
* This returns the Linux bootargs
@@ -28,9 +27,6 @@ const char *linux_bootargs_get(void)
{
char *bootargs, *parts;
- if (linux_bootargs_overwritten)
- return linux_bootargs;
-
free(linux_bootargs);
linux_bootargs = NULL;
@@ -65,19 +61,6 @@ const char *linux_bootargs_get(void)
return linux_bootargs;
}
-int linux_bootargs_overwrite(const char *bootargs)
-{
- if (bootargs) {
- free(linux_bootargs);
- linux_bootargs = xstrdup(bootargs);
- linux_bootargs_overwritten = 1;
- } else {
- linux_bootargs_overwritten = 0;
- }
-
- return 0;
-}
-
char *linux_bootargs_append_rootwait(char *rootarg_old)
{
char *rootarg = xasprintf("%s rootwait=%d",
diff --git a/include/bootargs.h b/include/bootargs.h
index 4a51e81173..93ec621ad1 100644
--- a/include/bootargs.h
+++ b/include/bootargs.h
@@ -8,7 +8,6 @@ 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)
@@ -16,10 +15,6 @@ static inline const char *linux_bootargs_get(void)
return getenv("bootargs");
}
-static inline int linux_bootargs_overwrite(const char *bootargs)
-{
- return setenv("bootargs", bootargs);
-}
static inline char *linux_bootargs_append_rootwait(char *rootarg)
{
return rootarg;
--
2.47.3
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 07/10] of: add watchdog bootarg directly instead of via a globalvar
2026-10-30 10:53 [PATCH 00/10] boot: revert boot related globalvars after booting Sascha Hauer
` (5 preceding siblings ...)
2026-10-30 10:54 ` [PATCH 06/10] bootargs: remove unused linux_bootargs_overwrite() Sascha Hauer
@ 2026-10-30 10:54 ` Sascha Hauer
2026-10-30 10:54 ` [PATCH 08/10] boot: drop the dyn infix from the bootentries bootargs variable Sascha Hauer
` (2 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Sascha Hauer @ 2026-10-30 10:54 UTC (permalink / raw)
To: BAREBOX
With CONFIG_SYSTEMD_OF_WATCHDOG, the device tree bootargs fixup puts
systemd.watchdog_device= into global.linux.bootargs.dyn.watchdog only to
read it back right away via linux_bootargs_get(). This has side effects
beyond the fixup:
- The variable is created whenever the fixup runs, so also for of_dump
-F, oftree -s or of_diff after a boot attempt has enabled the
watchdog, and stays around afterwards.
- Its mere existence makes linux_bootargs_get() ignore the legacy
bootargs environment variable, which is only used when no
global.linux.bootargs.* variables exist.
Return the option from watchdog_build_bootargs() and append it to the
bootargs in of_write_bootargs() instead. Note this moves the option to
the end of the command line, while it was previously sorted among the
global.linux.bootargs.* variables.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
Documentation/user/booting-linux.rst | 2 ++
common/Kconfig | 6 +++---
common/oftree.c | 41 ++++++++++++++++++++----------------
3 files changed, 28 insertions(+), 21 deletions(-)
diff --git a/Documentation/user/booting-linux.rst b/Documentation/user/booting-linux.rst
index 0fbdc52c68..158aa8b313 100644
--- a/Documentation/user/booting-linux.rst
+++ b/Documentation/user/booting-linux.rst
@@ -124,6 +124,8 @@ interleaved with externally provided command-line arguments:
* ``systemd.machine_id=`` controlled by :ref:`global.bootm.provide_machine_id <magicvar_global_bootm_provide_machine_id>`
* ``systemd.hostname=`` controlled by :ref:`global.bootm.provide_hostname <magicvar_global_bootm_provide_hostname>`
* ``barebox.security.policy=`` controlled by :ref:`global.bootm.provide_policy <magicvar_global_bootm_provide_policy>`
+ * ``systemd.watchdog_device=`` controlled by ``CONFIG_SYSTEMD_OF_WATCHDOG``,
+ only when booting with a device tree
Creating root= options for the Kernel
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/common/Kconfig b/common/Kconfig
index 9adecfd2e4..da4cc8a5c9 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -1443,9 +1443,9 @@ config SYSTEMD_OF_WATCHDOG
bool "inform devicetree-enabled kernel of used watchdog"
depends on WATCHDOG && OFTREE && FLEXIBLE_BOOTARGS
help
- Sets the linux.bootargs.dyn.watchdog global variable with a value of
- systemd.watchdog_device=/dev/WDOG if barebox succeeded in enabling
- the watchdog WDOG prior to boot. WDOG is the alias of the watchdog
+ Appends systemd.watchdog_device=/dev/WDOG to the Kernel command line
+ in the device tree if barebox succeeded in enabling the watchdog
+ WDOG prior to boot. WDOG is the alias of the watchdog
in the kernel device tree. If the kernel is booted without a device
tree or with one that lacks aliases, nothing is added.
diff --git a/common/oftree.c b/common/oftree.c
index 7aaed70e40..5f9b2e50cb 100644
--- a/common/oftree.c
+++ b/common/oftree.c
@@ -160,22 +160,18 @@ static int of_fixup_bootargs_reset_source(struct device_node *root,
return of_property_write_string(chosen, "reset-source-device", np->full_name);
}
-static void watchdog_build_bootargs(struct watchdog *watchdog, struct device_node *root)
+static char *watchdog_build_bootargs(struct watchdog *watchdog, struct device_node *root)
{
int alias_id;
- char *buf;
if (!watchdog)
- return;
+ return NULL;
alias_id = watchdog_get_alias_id_from(watchdog, root);
if (alias_id < 0)
- return;
-
- buf = xasprintf("systemd.watchdog_device=/dev/watchdog%d", alias_id);
+ return NULL;
- globalvar_add_simple("linux.bootargs.dyn.watchdog", buf);
- free(buf);
+ return xasprintf("systemd.watchdog_device=/dev/watchdog%d", alias_id);
}
static int bootargs_append = 0;
@@ -183,31 +179,40 @@ BAREBOX_MAGICVAR(global.linux.bootargs_append, "append to original oftree bootar
static int of_write_bootargs(struct device_node *node)
{
- const char *str;
+ const char *str, *oldstr;
+ char *watchdog = NULL;
char *buf = NULL;
int ret;
if (IS_ENABLED(CONFIG_SYSTEMD_OF_WATCHDOG))
- watchdog_build_bootargs(boot_get_enabled_watchdog(), of_get_parent(node));
+ watchdog = watchdog_build_bootargs(boot_get_enabled_watchdog(),
+ of_get_parent(node));
- str = linux_bootargs_get();
- if (!str)
- return 0;
+ str = skip_spaces(linux_bootargs_get() ?: "");
+
+ if (watchdog) {
+ if (*str)
+ str = buf = xasprintf("%s %s", str, watchdog);
+ else
+ str = watchdog;
+ }
- str = skip_spaces(str);
if (strlen(str) == 0)
return 0;
if (bootargs_append) {
- const char *oldstr;
-
ret = of_property_read_string(node, "bootargs", &oldstr);
- if (!ret)
- str = buf = xasprintf("%s %s", oldstr, str);
+ if (!ret) {
+ char *tmp = xasprintf("%s %s", oldstr, str);
+
+ free(buf);
+ str = buf = tmp;
+ }
}
ret = of_property_write_string(node, "bootargs", str);
free(buf);
+ free(watchdog);
return ret;
}
--
2.47.3
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 08/10] boot: drop the dyn infix from the bootentries bootargs variable
2026-10-30 10:53 [PATCH 00/10] boot: revert boot related globalvars after booting Sascha Hauer
` (6 preceding siblings ...)
2026-10-30 10:54 ` [PATCH 07/10] of: add watchdog bootarg directly instead of via a globalvar Sascha Hauer
@ 2026-10-30 10:54 ` Sascha Hauer
2026-10-30 10:54 ` [PATCH 09/10] defaultenv: don't use global.linux.bootargs.dyn.* in boot entries Sascha Hauer
2026-10-30 10:54 ` [PATCH 10/10] Documentation: migration-guides: describe reverting boot globalvars Sascha Hauer
9 siblings, 0 replies; 11+ messages in thread
From: Sascha Hauer @ 2026-10-30 10:54 UTC (permalink / raw)
To: BAREBOX
blspec and extlinux pass the options of a boot entry to the Kernel in
global.linux.bootargs.dyn.bootentries. The dyn infix used to be
necessary for boot_entry() to clear the variable again after a boot
entry returned. Now that boot_entry() reverts all changes to
global.linux.bootargs.* anyway, it no longer carries any meaning, so
name the variable global.linux.bootargs.bootentries.
As the variables are concatenated in lexicographical order, the boot
entry options may end up at a different position in the command line.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
common/blspec.c | 2 +-
common/extlinux.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/common/blspec.c b/common/blspec.c
index 0552e93b79..e2fa4956e9 100644
--- a/common/blspec.c
+++ b/common/blspec.c
@@ -128,7 +128,7 @@ static int blspec_boot(struct bootentry *be, int verbose, int dryrun)
if (initrd)
data.initrd_file = basprintf("%s/%s", abspath, initrd);
- globalvar_add_simple("linux.bootargs.dyn.bootentries", options);
+ globalvar_add_simple("linux.bootargs.bootentries", options);
appendroot = blspec_entry_var_get(entry, "linux-appendroot");
if (appendroot) {
diff --git a/common/extlinux.c b/common/extlinux.c
index 1976fe09aa..f502bffc7d 100644
--- a/common/extlinux.c
+++ b/common/extlinux.c
@@ -68,7 +68,7 @@ static int extlinux_boot(struct bootentry *entry, int verbose, int dryrun)
}
if (e->append)
- globalvar_add_simple("linux.bootargs.dyn.bootentries",
+ globalvar_add_simple("linux.bootargs.bootentries",
e->append);
pr_info("Booting extlinux label '%s'\n", e->label);
--
2.47.3
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 09/10] defaultenv: don't use global.linux.bootargs.dyn.* in boot entries
2026-10-30 10:53 [PATCH 00/10] boot: revert boot related globalvars after booting Sascha Hauer
` (7 preceding siblings ...)
2026-10-30 10:54 ` [PATCH 08/10] boot: drop the dyn infix from the bootentries bootargs variable Sascha Hauer
@ 2026-10-30 10:54 ` Sascha Hauer
2026-10-30 10:54 ` [PATCH 10/10] Documentation: migration-guides: describe reverting boot globalvars Sascha Hauer
9 siblings, 0 replies; 11+ messages in thread
From: Sascha Hauer @ 2026-10-30 10:54 UTC (permalink / raw)
To: BAREBOX
Boot entries no longer need to put their Kernel command line options
into global.linux.bootargs.dyn.*, as boot_entry() reverts all changes to
global.linux.bootargs.* when the boot entry returns. Use plain names in
the net and dfu boot entries, the boot entry template and the matching
example in the documentation.
Unlike the dyn.ip and dyn.root variables, which bootscript_boot()
creates for compatibility with existing boot scripts, the new variables
don't exist beforehand, so create them with the global command.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
Documentation/user/booting-linux.rst | 5 +++--
defaultenv/defaultenv-2-base/boot/net | 5 +++--
defaultenv/defaultenv-2-base/data/boot-template | 2 +-
defaultenv/defaultenv-2-dfu/boot/dfu | 4 ++--
4 files changed, 9 insertions(+), 7 deletions(-)
diff --git a/Documentation/user/booting-linux.rst b/Documentation/user/booting-linux.rst
index 158aa8b313..85f7694fe8 100644
--- a/Documentation/user/booting-linux.rst
+++ b/Documentation/user/booting-linux.rst
@@ -442,9 +442,10 @@ If the preconfigured paths or names are not suitable, they can be adjusted in
fi
nfsroot="/home/${global.user}/nfsroot/${global.hostname}"
- ip_route_get -b ${global.net.server} global.linux.bootargs.dyn.ip
+ global linux.bootargs.ip
+ ip_route_get -b ${global.net.server} global.linux.bootargs.ip
- global.linux.bootargs.dyn.root="root=/dev/nfs nfsroot=$nfsroot,v3,tcp"
+ global linux.bootargs.root="root=/dev/nfs nfsroot=$nfsroot,v3,tcp"
``boot net`` will then retrieve the kernel (and also the device tree and
initramfs, if used) over TFTP and boot it.
diff --git a/defaultenv/defaultenv-2-base/boot/net b/defaultenv/defaultenv-2-base/boot/net
index 8408ceaf39..f025bb4098 100644
--- a/defaultenv/defaultenv-2-base/boot/net
+++ b/defaultenv/defaultenv-2-base/boot/net
@@ -23,6 +23,7 @@ if [ -f "${initramfs}" ]; then
global.bootm.initrd="$initramfs"
else
nfsroot="${nfsserver}:/home/${global.user}/nfsroot/${global.hostname}"
- ip_route_get -b ${global.net.server} global.linux.bootargs.dyn.ip
- global.linux.bootargs.dyn.root="root=/dev/nfs nfsroot=$nfsroot,v3,tcp"
+ global linux.bootargs.ip
+ ip_route_get -b ${global.net.server} global.linux.bootargs.ip
+ global linux.bootargs.root="root=/dev/nfs nfsroot=$nfsroot,v3,tcp"
fi
diff --git a/defaultenv/defaultenv-2-base/data/boot-template b/defaultenv/defaultenv-2-base/data/boot-template
index 689d98e1e9..b63eb86d1a 100644
--- a/defaultenv/defaultenv-2-base/data/boot-template
+++ b/defaultenv/defaultenv-2-base/data/boot-template
@@ -6,4 +6,4 @@ global.bootm.image=<path to image>
#bootargs-ip
-global.linux.bootargs.dyn.root="root=<rootfs here>"
+global linux.bootargs.root="root=<rootfs here>"
diff --git a/defaultenv/defaultenv-2-dfu/boot/dfu b/defaultenv/defaultenv-2-dfu/boot/dfu
index 682091141e..56a88ae0a3 100644
--- a/defaultenv/defaultenv-2-dfu/boot/dfu
+++ b/defaultenv/defaultenv-2-dfu/boot/dfu
@@ -23,8 +23,8 @@ if [ ! -f "$kernel" ]; then
fi
if [ -f "$cmdline" ]; then
- global linux.bootargs.dyn.dfu
- readf $cmdline global.linux.bootargs.dyn.dfu
+ global linux.bootargs.dfu
+ readf $cmdline global.linux.bootargs.dfu
fi
if [ -f "$dtb" ]; then
--
2.47.3
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 10/10] Documentation: migration-guides: describe reverting boot globalvars
2026-10-30 10:53 [PATCH 00/10] boot: revert boot related globalvars after booting Sascha Hauer
` (8 preceding siblings ...)
2026-10-30 10:54 ` [PATCH 09/10] defaultenv: don't use global.linux.bootargs.dyn.* in boot entries Sascha Hauer
@ 2026-10-30 10:54 ` Sascha Hauer
9 siblings, 0 replies; 11+ messages in thread
From: Sascha Hauer @ 2026-10-30 10:54 UTC (permalink / raw)
To: BAREBOX
Describe that the boot related globalvars are now reverted after
booting, that the .dyn infix is no longer necessary and that the order
of the Kernel command line options may change.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
.../migration-master/boot-globalvar-scope.rst | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/Documentation/migration-guides/migration-master/boot-globalvar-scope.rst b/Documentation/migration-guides/migration-master/boot-globalvar-scope.rst
new file mode 100644
index 0000000000..d7e322ca0b
--- /dev/null
+++ b/Documentation/migration-guides/migration-master/boot-globalvar-scope.rst
@@ -0,0 +1,13 @@
+Boot related globalvars are reverted after booting
+--------------------------------------------------
+
+``global.bootm.*``, ``global.linux.*``, ``global.of.*`` and
+``global.boot.watchdog_timeout`` are now snapshotted before each boot
+entry and each bootm and restored afterwards, so changes made while
+booting no longer leak into subsequent boot attempts.
+
+Boot entries therefore no longer need to put Kernel command line options
+into ``global.linux.bootargs.dyn.*``. The boot entries shipped with
+barebox have dropped the ``.dyn`` infix. As the bootargs variables are
+concatenated in lexicographical order, the order of the Kernel command
+line options may change.
--
2.47.3
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2026-10-30 11:16 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-30 10:53 [PATCH 00/10] boot: revert boot related globalvars after booting Sascha Hauer
2026-10-30 10:53 ` [PATCH 01/10] globalvar: add scopes to snapshot and restore globalvars Sascha Hauer
2026-10-30 10:54 ` [PATCH 02/10] bootm: revert globalvar changes in bootm_boot_cleanup() Sascha Hauer
2026-10-30 10:54 ` [PATCH 03/10] boot: revert globalvar changes after each boot entry Sascha Hauer
2026-10-30 10:54 ` [PATCH 04/10] bootchooser: use a globalvar scope for its bootargs Sascha Hauer
2026-10-30 10:54 ` [PATCH 05/10] test: py: add test for reverting globalvars after boot Sascha Hauer
2026-10-30 10:54 ` [PATCH 06/10] bootargs: remove unused linux_bootargs_overwrite() Sascha Hauer
2026-10-30 10:54 ` [PATCH 07/10] of: add watchdog bootarg directly instead of via a globalvar Sascha Hauer
2026-10-30 10:54 ` [PATCH 08/10] boot: drop the dyn infix from the bootentries bootargs variable Sascha Hauer
2026-10-30 10:54 ` [PATCH 09/10] defaultenv: don't use global.linux.bootargs.dyn.* in boot entries Sascha Hauer
2026-10-30 10:54 ` [PATCH 10/10] Documentation: migration-guides: describe reverting boot globalvars Sascha Hauer
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox