[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