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


Reply via email to