From: Marek Behún <marek.be...@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 new sysinfo IDs
  SYSINFO_ID_DEF_ENV_NAMES
  SYSINFO_ID_DEF_ENV_VALUES
corresponding to sysinfo string list of names and values of default
environment variables that are to take precedence over the
default_environment[] buffer.

Add code to default environemnt handlers in env/common.c, which iterate
these sysinfo string lists correspondingly.

Signed-off-by: Marek Behún <marek.be...@nic.cz>
---
 env/common.c      | 107 +++++++++++++++++++++++++++++++++++++++++++++-
 include/sysinfo.h |   4 ++
 2 files changed, 110 insertions(+), 1 deletion(-)

diff --git a/env/common.c b/env/common.c
index cefe58561b..8ac287beae 100644
--- a/env/common.c
+++ b/env/common.c
@@ -22,6 +22,7 @@
 #include <u-boot/crc.h>
 #include <dm/ofnode.h>
 #include <net.h>
+#include <sysinfo.h>
 #include <watchdog.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -148,6 +149,31 @@ char *from_env(const char *envvar)
        return ret;
 }
 
+static int sysinfo_default_env_get(const char *var, char *buf, unsigned len)
+{
+       struct udevice *dev;
+       unsigned idx;
+       char *name;
+       void *iter;
+
+       if (sysinfo_get(&dev) < 0 || sysinfo_detect(dev) < 0)
+               return -ENODEV;
+
+       idx = 0;
+       for_each_sysinfo_str_list(dev, SYSINFO_ID_DEF_ENV_NAMES, name, iter) {
+               if (strcmp(var, name)) {
+                       ++idx;
+                       continue;
+               }
+
+               free(iter);
+               return sysinfo_get_str_list(dev, SYSINFO_ID_DEF_ENV_VALUES, idx,
+                                           len, buf);
+       }
+
+       return -ENOENT;
+}
+
 static int env_get_from_linear(const char *env, const char *name, char *buf,
                               unsigned len)
 {
@@ -157,6 +183,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 = sysinfo_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,8 +285,69 @@ char *env_get_default(const char *name)
        return NULL;
 }
 
+static int sysinfo_import_default_envs(bool all, int nvars, char * const 
vars[],
+                                      int flags)
+{
+       struct udevice *dev;
+       char *name, *value;
+       unsigned idx;
+       void *iter;
+       int len;
+
+       if (sysinfo_get(&dev) < 0 || sysinfo_detect(dev) < 0)
+               return 0;
+
+       len = sysinfo_get_str_list_max_len(dev, SYSINFO_ID_DEF_ENV_VALUES);
+       if (len == -ENOSYS || len == -ENOENT || len == -ERANGE)
+               return 0;
+       else if (len < 0)
+               return len;
+
+       value = malloc(len + 1);
+       if (!value)
+               return -ENOMEM;
+
+       idx = 0;
+       for_each_sysinfo_str_list(dev, SYSINFO_ID_DEF_ENV_NAMES, name, iter) {
+               struct env_entry e, *ep;
+
+               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) {
+                               idx++;
+                               continue;
+                       }
+               }
+
+               len = sysinfo_get_str_list(dev, SYSINFO_ID_DEF_ENV_VALUES,
+                                          idx++, ENV_SIZE, value);
+               if (len < 0)
+                       continue;
+
+               e.key = name;
+               e.data = value;
+               if (!hsearch_r(e, ENV_ENTER, &ep, &env_htab, flags)) {
+                       int res = -errno;
+                       free(iter);
+                       free(value);
+                       return res;
+               }
+       }
+
+       free(value);
+
+       return 0;
+}
+
 void env_set_default(const char *s, int flags)
 {
+       int res;
+
        if (s) {
                if ((flags & H_INTERACTIVE) == 0) {
                        printf("*** Warning - %s, "
@@ -270,6 +368,13 @@ void env_set_default(const char *s, int flags)
                return;
        }
 
+       res = sysinfo_import_default_envs(true, 0, NULL, flags);
+       if (res < 0) {
+               pr_err("## Error: Board special default environment import 
failed: %d\n",
+                      res);
+               return;
+       }
+
        gd->flags |= GD_FLG_ENV_READY;
        gd->flags |= GD_FLG_ENV_DEFAULT;
 }
@@ -288,7 +393,7 @@ int env_set_default_vars(int nvars, char * const vars[], 
int flags)
                       vars))
                return -errno;
 
-       return 0;
+       return sysinfo_import_default_envs(false, nvars, vars, flags);
 }
 
 /*
diff --git a/include/sysinfo.h b/include/sysinfo.h
index d32bf3e808..587ad0dc75 100644
--- a/include/sysinfo.h
+++ b/include/sysinfo.h
@@ -47,6 +47,10 @@ enum sysinfo_id {
        /* For show_board_info() */
        SYSINFO_ID_BOARD_MODEL,
 
+       /* For overwriting default environment variables */
+       SYSINFO_ID_DEF_ENV_NAMES,
+       SYSINFO_ID_DEF_ENV_VALUES,
+
        /* First value available for downstream/board used */
        SYSINFO_ID_USER = 0x1000,
 };
-- 
2.32.0

Reply via email to