[PATCH 4/5] env: Add support for board specific special default environment
Marek Behún
kabel at kernel.org
Thu Oct 28 05:28:09 CEST 2021
From: Marek Behún <marek.behun at nic.cz>
The default_environment[] buffer is built at compile time, but sometimes
it makes sense for some default environment variables to be determined
at runtime, for example:
- one board code may support different boards, and needs that
fdtfile, board, board_name
are set appropriately when command
env default -a
is executed
- some boards may want to prohibit the
env default -a
command to remove device MAC addresses stored in
ethaddr, ethNaddr.
This is the case for the ESPRESSObin board code, for example, where
currently the board_late_init() function rewrites the default
environment array to achieve this.
Add a new board specific function,
const char *board_special_default_env(unsigned i, const char **name);
which returns the value of i-th board special default environemnt
variable, while storing it's name to *name.
Add default weak implementation of this functions returning NULL.
Add code to default environemnt handlers in env/common.c, which iterate
these special board default environment variables and get it's values in
precedence to values in the default_environment[] buffer.
Signed-off-by: Marek Behún <marek.behun at nic.cz>
---
env/common.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 96 insertions(+), 3 deletions(-)
diff --git a/env/common.c b/env/common.c
index 208e2adaa0..d157ca562a 100644
--- a/env/common.c
+++ b/env/common.c
@@ -148,6 +148,41 @@ char *from_env(const char *envvar)
return ret;
}
+__weak const char *board_special_default_env(unsigned i, const char **name)
+{
+ return NULL;
+}
+
+static int board_special_default_env_get(const char *var, char *buf,
+ unsigned len)
+{
+ int i;
+
+ /*
+ * Iterate all board special default env variables, and if one
+ * exists with the requested name, return it.
+ */
+ for (i = 0; ; ++i) {
+ const char *name, *value;
+
+ value = board_special_default_env(i, &name);
+ if (!value)
+ break;
+
+ if (!strcmp(var, name)) {
+ unsigned res = strlen(value);
+
+ memcpy(buf, value, min(len, res + 1));
+ if (len <= res)
+ buf[len - 1] = '\0';
+
+ return res;
+ }
+ }
+
+ return -1;
+}
+
static int env_get_from_linear(const char *env, const char *name, char *buf,
unsigned len)
{
@@ -157,6 +192,17 @@ static int env_get_from_linear(const char *env, const char *name, char *buf,
if (name == NULL || *name == '\0')
return -1;
+ if (env == default_environment) {
+ int res = board_special_default_env_get(name, buf, len);
+
+ /*
+ * Board special default envs take precedence over the
+ * default_environment[] array.
+ */
+ if (res >= 0)
+ return res;
+ }
+
name_len = strlen(name);
for (p = env; *p != '\0'; p = end + 1) {
@@ -248,6 +294,41 @@ char *env_get_default(const char *name)
return NULL;
}
+static int import_board_special_default_envs(bool all, int nvars,
+ char * const vars[], int flags)
+{
+ int i;
+
+ for (i = 0; ; ++i) {
+ const char *name, *value;
+ struct env_entry e, *ep;
+
+ value = board_special_default_env(i, &name);
+ if (!value)
+ break;
+
+ if (!all) {
+ int j;
+
+ /* If name is not in vars, skip */
+
+ for (j = 0; j < nvars; ++j)
+ if (!strcmp(name, vars[j]))
+ break;
+ if (j == nvars)
+ continue;
+ }
+
+ e.key = name;
+ e.data = (char *)value;
+
+ if (!hsearch_r(e, ENV_ENTER, &ep, &env_htab, flags))
+ return -1;
+ }
+
+ return 0;
+}
+
void env_set_default(const char *s, int flags)
{
if (s) {
@@ -270,6 +351,12 @@ void env_set_default(const char *s, int flags)
return;
}
+ if (import_board_special_default_envs(true, 0, NULL, flags) < 0) {
+ pr_err("## Error: Board special default environment import failed: errno = %d\n",
+ errno);
+ return;
+ }
+
gd->flags |= GD_FLG_ENV_READY;
gd->flags |= GD_FLG_ENV_DEFAULT;
}
@@ -278,14 +365,20 @@ void env_set_default(const char *s, int flags)
/* [re]set individual variables to their value in the default environment */
int env_set_default_vars(int nvars, char * const vars[], int flags)
{
+ int res;
+
/*
* Special use-case: import from default environment
* (and use \0 as a separator)
*/
flags |= H_NOCLEAR | H_DEFAULT;
- return himport_r(&env_htab, default_environment,
- sizeof(default_environment), '\0',
- flags, 0, nvars, vars);
+ res = himport_r(&env_htab, default_environment,
+ sizeof(default_environment), '\0', flags, 0, nvars,
+ vars);
+ if (!res)
+ return res;
+
+ return import_board_special_default_envs(false, nvars, vars, flags);
}
/*
--
2.32.0
More information about the U-Boot
mailing list