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 <[email protected]> --- 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
