This patch makes it possible to have a first environment that will be the base environment, secondary environment that will be pre-loaded and have its variables passing through the whitelist "mask" to override variables in the base environment.
The base environment will be the environment with the highest priority (0 is highest) that can load and the next loadable environment will be the secondary environment (with a lowest priority than the base environment of course). The whitelist "mask" is built with the content of space-separated list of environment variables in ENV_VAR_WHITELIST_LIST in Kconfig. Signed-off-by: Quentin Schulz <quentin.sch...@free-electrons.com> --- env/Kconfig | 17 +++++++- env/common.c | 7 +++- env/env.c | 100 +++++++++++++++++++++++++++++++++++++++---- include/environment.h | 6 +++- 4 files changed, 123 insertions(+), 7 deletions(-) diff --git a/env/Kconfig b/env/Kconfig index 1952463..d57594d 100644 --- a/env/Kconfig +++ b/env/Kconfig @@ -438,4 +438,21 @@ config ENV_UBI_VOLUME endif +config ENV_VAR_WHITELIST + bool "Enable overriding some variables from secondary environments" + help + This allows overriding some variables from secondary environments. + After the first valid environment is loaded, a secondary environment + is pre-loaded and its variables that are present in the whitelist will + be added to the current environment or will override existing + variables. + +config ENV_VAR_WHITELIST_LIST + depends on ENV_VAR_WHITELIST + string "Whitelist of variables from secondary environments" + help + This defines the variables that are allowed to be overriden by + ones from secondary environments. + This is a list of environment variables that are space-separated. + endmenu diff --git a/env/common.c b/env/common.c index 9d97541..00c454d 100644 --- a/env/common.c +++ b/env/common.c @@ -177,8 +177,15 @@ int env_import(const char *buf, int check) return ret; } +#ifdef CONFIG_ENV_VAR_WHITELIST + if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', + whitelisting ? H_NOCLEAR : 0, 0, + whitelisting ? whitelist_nvars : 0, + whitelisting ? whitelist : NULL, whitelisting)) { +#else if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0, 0, 0, NULL, false)) { +#endif gd->flags |= GD_FLG_ENV_READY; return 1; } diff --git a/env/env.c b/env/env.c index 5e70ddf..43a62b8 100644 --- a/env/env.c +++ b/env/env.c @@ -7,9 +7,18 @@ #include <common.h> #include <environment.h> +#ifdef CONFIG_ENV_VAR_WHITELIST +# include <malloc.h> +#endif DECLARE_GLOBAL_DATA_PTR; +#ifdef CONFIG_ENV_VAR_WHITELIST +char *const *whitelist; +bool whitelisting; +unsigned int whitelist_nvars; +#endif + static struct env_driver *_env_driver_lookup(enum env_location loc) { struct env_driver *drv; @@ -62,6 +71,31 @@ static enum env_location env_locations[] = { static enum env_location env_load_location; +#ifdef CONFIG_ENV_VAR_WHITELIST +void env_create_whitelist(void) +{ + char **wl_vars; + char *wl = strchr(CONFIG_ENV_VAR_WHITELIST_LIST, ' '); + unsigned int nvars = 0; + + while(wl) { + nvars++; + wl = strchr(wl + 1, ' '); + } + + whitelist_nvars = nvars + 1; + + wl_vars = malloc(sizeof(char *) * (nvars + 1)); + + wl_vars[nvars] = strtok(CONFIG_ENV_VAR_WHITELIST_LIST, " "); + while (nvars) { + wl_vars[--nvars] = strtok(NULL, " "); + } + + whitelist = wl_vars; +} +#endif + __weak enum env_location env_get_location(enum env_operation op, int prio) { switch (op) { @@ -74,7 +108,11 @@ __weak enum env_location env_get_location(enum env_operation op, int prio) return env_load_location = env_locations[prio]; case ENVO_SAVE: +#ifdef CONFIG_ENV_VAR_WHITELIST + return env_locations[prio]; +#else return env_load_location; +#endif } return ENVL_UNKNOWN; @@ -130,10 +168,12 @@ int env_load(void) { struct env_driver *drv; int prio; + int ret = 1; +#ifdef CONFIG_ENV_VAR_WHITELIST + bool found = false; +#endif for (prio = 0; (drv = env_driver_lookup(ENVO_LOAD, prio)); prio++) { - int ret; - if (!drv->load) continue; @@ -144,16 +184,52 @@ int env_load(void) ret = drv->load(); printf("%s\n", ret ? "Failed" : "OK"); if (!ret) - return 0; + break; } - return -ENODEV; + if (ret) + return -ENODEV; + +#ifdef CONFIG_ENV_VAR_WHITELIST + env_create_whitelist(); + + whitelisting = true; + /* When whitelisting, env from prio x+n will override env from prio x */ + for (prio++; prio < ARRAY_SIZE(env_locations); prio++) { + drv = env_driver_lookup(ENVO_LOAD, prio); + if (!drv) + continue; + + if (!drv->load) + continue; + + printf("Overriding env variables with ones from %s env...", + __func__, drv->name); + ret = drv->load(); + printf("%s\n", ret ? "Failed" : "OK"); + if (!ret) { + found = true; + continue; + } + } + +out: + if (!found) + debug("%s: Couldn't find other valid env for whitelisting\n", + __func__); + + whitelisting = false; +#endif + return 0; } int env_save(void) { struct env_driver *drv; int prio; +#ifdef CONFIG_ENV_VAR_WHITELIST + bool saved = false; +#endif for (prio = 0; (drv = env_driver_lookup(ENVO_SAVE, prio)); prio++) { int ret; @@ -167,13 +243,23 @@ int env_save(void) printf("Saving Environment to %s... ", drv->name); ret = drv->save(); printf("%s\n", ret ? "Failed" : "OK"); +#ifdef CONFIG_ENV_VAR_WHITELIST + /* When whitelisting, we want to save to all media available */ + if (!ret) { + saved = true; + continue; + } +#else if (!ret) return 0; - - debug("%s: Environment %s failed to save (err=%d)\n", __func__, - drv->name, ret); +#endif } +#ifdef CONFIG_ENV_VAR_WHITELIST + if (saved) + return 0; +#endif + return -ENODEV; } diff --git a/include/environment.h b/include/environment.h index 7fa8b98..33e47ba 100644 --- a/include/environment.h +++ b/include/environment.h @@ -267,6 +267,12 @@ struct env_driver { int (*init)(void); }; +#ifdef CONFIG_ENV_VAR_WHITELIST +extern char *const *whitelist; +extern unsigned int whitelist_nvars; +extern bool whitelisting; +#endif + /* Declare a new environment location driver */ #define U_BOOT_ENV_LOCATION(__name) \ ll_entry_declare(struct env_driver, __name, env_driver) -- git-series 0.9.1 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot