It is not possible to set environment variables without having
CONFIG_CMD_NVEDIT enabled. When CONFIG_CMDLINE is disabled, we need a
way to set variables.

Split the setting code out into its own file, so that env_set() is
available even when CONFIG_CMDLINE is not. If it is never called, the
code will be dropped at link time.

Update the Makefile rule to only include the env commands when
CONFIG_CMD_NVEDIT is enabled.

Signed-off-by: Simon Glass <s...@chromium.org>
---

 cmd/Makefile           |   2 +-
 cmd/nvedit.c           | 122 ++-----------------------------------
 env/Makefile           |   1 +
 env/env_set.c          | 132 +++++++++++++++++++++++++++++++++++++++++
 include/env_internal.h |  23 +++++++
 5 files changed, 161 insertions(+), 119 deletions(-)
 create mode 100644 env/env_set.c

diff --git a/cmd/Makefile b/cmd/Makefile
index 9bebf321c397..5be2b4bd3800 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -240,7 +240,7 @@ endif # !CONFIG_SPL_BUILD
 obj-$(CONFIG_$(SPL_)CMD_TLV_EEPROM) += tlv_eeprom.o
 
 # core command
-obj-y += nvedit.o
+obj-$(CONFIG_$(SPL_)CMDLINE) += nvedit.o
 
 obj-$(CONFIG_CMD_BCM_EXT_UTILS) += broadcom/
 
diff --git a/cmd/nvedit.c b/cmd/nvedit.c
index fe99157fd17b..0c9efa052baf 100644
--- a/cmd/nvedit.c
+++ b/cmd/nvedit.c
@@ -48,20 +48,6 @@ DECLARE_GLOBAL_DATA_PTR;
  */
 #define        MAX_ENV_SIZE    (1 << 20)       /* 1 MiB */
 
-/*
- * This variable is incremented on each do_env_set(), so it can
- * be used via env_get_id() as an indication, if the environment
- * has changed or not. So it is possible to reread an environment
- * variable only if the environment was changed ... done so for
- * example in NetInitLoop()
- */
-static int env_id = 1;
-
-int env_get_id(void)
-{
-       return env_id;
-}
-
 #ifndef CONFIG_SPL_BUILD
 /*
  * Command interface: print one or all environment variables
@@ -194,108 +180,8 @@ DONE:
 
        return 0;
 }
-#endif
-#endif /* CONFIG_SPL_BUILD */
-
-/*
- * Set a new environment variable,
- * or replace or delete an existing one.
- */
-static int _do_env_set(int flag, int argc, char *const argv[], int env_flag)
-{
-       int   i, len;
-       char  *name, *value, *s;
-       struct env_entry e, *ep;
-
-       debug("Initial value for argc=%d\n", argc);
-
-#if !IS_ENABLED(CONFIG_SPL_BUILD) && IS_ENABLED(CONFIG_CMD_NVEDIT_EFI)
-       if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'e')
-               return do_env_set_efi(NULL, flag, --argc, ++argv);
-#endif
-
-       while (argc > 1 && **(argv + 1) == '-') {
-               char *arg = *++argv;
-
-               --argc;
-               while (*++arg) {
-                       switch (*arg) {
-                       case 'f':               /* force */
-                               env_flag |= H_FORCE;
-                               break;
-                       default:
-                               return CMD_RET_USAGE;
-                       }
-               }
-       }
-       debug("Final value for argc=%d\n", argc);
-       name = argv[1];
-
-       if (strchr(name, '=')) {
-               printf("## Error: illegal character '='"
-                      "in variable name \"%s\"\n", name);
-               return 1;
-       }
-
-       env_id++;
-
-       /* Delete only ? */
-       if (argc < 3 || argv[2] == NULL) {
-               int rc = hdelete_r(name, &env_htab, env_flag);
-
-               /* If the variable didn't exist, don't report an error */
-               return rc && rc != -ENOENT ? 1 : 0;
-       }
-
-       /*
-        * Insert / replace new value
-        */
-       for (i = 2, len = 0; i < argc; ++i)
-               len += strlen(argv[i]) + 1;
-
-       value = malloc(len);
-       if (value == NULL) {
-               printf("## Can't malloc %d bytes\n", len);
-               return 1;
-       }
-       for (i = 2, s = value; i < argc; ++i) {
-               char *v = argv[i];
-
-               while ((*s++ = *v++) != '\0')
-                       ;
-               *(s - 1) = ' ';
-       }
-       if (s != value)
-               *--s = '\0';
-
-       e.key   = name;
-       e.data  = value;
-       hsearch_r(e, ENV_ENTER, &ep, &env_htab, env_flag);
-       free(value);
-       if (!ep) {
-               printf("## Error inserting \"%s\" variable, errno=%d\n",
-                       name, errno);
-               return 1;
-       }
-
-       return 0;
-}
-
-int env_set(const char *varname, const char *varvalue)
-{
-       const char * const argv[4] = { "setenv", varname, varvalue, NULL };
-
-       /* before import into hashtable */
-       if (!(gd->flags & GD_FLG_ENV_READY))
-               return 1;
-
-       if (varvalue == NULL || varvalue[0] == '\0')
-               return _do_env_set(0, 2, (char * const *)argv, H_PROGRAMMATIC);
-       else
-               return _do_env_set(0, 3, (char * const *)argv, H_PROGRAMMATIC);
-}
+#endif /* CONFIG_CMD_GREPENV */
 
-#ifndef CONFIG_SPL_BUILD
 static int do_env_set(struct cmd_tbl *cmdtp, int flag, int argc,
                      char *const argv[])
 {
@@ -455,7 +341,7 @@ int do_env_callback(struct cmd_tbl *cmdtp, int flag, int 
argc,
        hwalk_r(&env_htab, print_active_callback);
        return 0;
 }
-#endif
+#endif /* CONFIG_CMD_ENV_CALLBACK */
 
 #if defined(CONFIG_CMD_ENV_FLAGS)
 static int print_static_flags(const char *var_name, const char *flags,
@@ -528,7 +414,7 @@ int do_env_flags(struct cmd_tbl *cmdtp, int flag, int argc, 
char *const argv[])
        hwalk_r(&env_htab, print_active_flags);
        return 0;
 }
-#endif
+#endif /* CONFIG_CMD_ENV_FLAGS */
 
 /*
  * Interactively edit an environment variable
@@ -678,7 +564,7 @@ static int do_env_delete(struct cmd_tbl *cmdtp, int flag,
        }
        debug("Final value for argc=%d\n", argc);
 
-       env_id++;
+       env_inc_id();
 
        while (--argc > 0) {
                char *name = *++argv;
diff --git a/env/Makefile b/env/Makefile
index 673b979fdfa9..5250b6df2cfc 100644
--- a/env/Makefile
+++ b/env/Makefile
@@ -5,6 +5,7 @@
 
 obj-$(CONFIG_$(SPL_TPL_)ENV_SUPPORT) += common.o
 obj-$(CONFIG_$(SPL_TPL_)ENV_SUPPORT) += env.o
+obj-$(CONFIG_$(SPL_TPL_)ENV_SUPPORT) += env_set.o
 obj-$(CONFIG_$(SPL_TPL_)ENV_SUPPORT) += attr.o
 obj-$(CONFIG_$(SPL_TPL_)ENV_SUPPORT) += flags.o
 
diff --git a/env/env_set.c b/env/env_set.c
new file mode 100644
index 000000000000..eccbda6a791c
--- /dev/null
+++ b/env/env_set.c
@@ -0,0 +1,132 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2000-2013
+ * Wolfgang Denk, DENX Software Engineering, w...@denx.de.
+ *
+ * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Andreas Heppel <ahep...@sysgo.de>
+ *
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <env.h>
+#include <env_internal.h>
+#include <malloc.h>
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * This variable is incremented on each do_env_set(), so it can
+ * be used via env_get_id() as an indication, if the environment
+ * has changed or not. So it is possible to reread an environment
+ * variable only if the environment was changed ... done so for
+ * example in NetInitLoop()
+ */
+static int env_id = 1;
+
+int env_get_id(void)
+{
+       return env_id;
+}
+
+void env_inc_id(void)
+{
+       env_id++;
+}
+
+int _do_env_set(int flag, int argc, char *const argv[], int env_flag)
+{
+       int   i, len;
+       char  *name, *value, *s;
+       struct env_entry e, *ep;
+
+       debug("Initial value for argc=%d\n", argc);
+
+#if !IS_ENABLED(CONFIG_SPL_BUILD) && IS_ENABLED(CONFIG_CMD_NVEDIT_EFI)
+       if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'e')
+               return do_env_set_efi(NULL, flag, --argc, ++argv);
+#endif
+
+       while (argc > 1 && **(argv + 1) == '-') {
+               char *arg = *++argv;
+
+               --argc;
+               while (*++arg) {
+                       switch (*arg) {
+                       case 'f':               /* force */
+                               env_flag |= H_FORCE;
+                               break;
+                       default:
+                               return CMD_RET_USAGE;
+                       }
+               }
+       }
+       debug("Final value for argc=%d\n", argc);
+       name = argv[1];
+
+       if (strchr(name, '=')) {
+               printf("## Error: illegal character '=' in variable name 
\"%s\"\n",
+                      name);
+               return 1;
+       }
+
+       env_id++;
+
+       /* Delete only ? */
+       if (argc < 3 || !argv[2]) {
+               int rc = hdelete_r(name, &env_htab, env_flag);
+
+               /* If the variable didn't exist, don't report an error */
+               return rc && rc != -ENOENT ? 1 : 0;
+       }
+
+       /*
+        * Insert / replace new value
+        */
+       for (i = 2, len = 0; i < argc; ++i)
+               len += strlen(argv[i]) + 1;
+
+       value = malloc(len);
+       if (!value) {
+               printf("## Can't malloc %d bytes\n", len);
+               return 1;
+       }
+       for (i = 2, s = value; i < argc; ++i) {
+               char *v = argv[i];
+
+               while ((*s++ = *v++) != '\0')
+                       ;
+               *(s - 1) = ' ';
+       }
+       if (s != value)
+               *--s = '\0';
+
+       e.key   = name;
+       e.data  = value;
+       hsearch_r(e, ENV_ENTER, &ep, &env_htab, env_flag);
+       free(value);
+       if (!ep) {
+               printf("## Error inserting \"%s\" variable, errno=%d\n",
+                      name, errno);
+               return 1;
+       }
+
+       return 0;
+}
+
+int env_set(const char *varname, const char *varvalue)
+{
+       const char * const argv[4] = { "setenv", varname, varvalue, NULL };
+
+       /* before import into hashtable */
+       if (!(gd->flags & GD_FLG_ENV_READY))
+               return 1;
+
+       if (!varvalue || !varvalue[0])
+               return _do_env_set(0, 2, (char * const *)argv, H_PROGRAMMATIC);
+       else
+               return _do_env_set(0, 3, (char * const *)argv, H_PROGRAMMATIC);
+}
diff --git a/include/env_internal.h b/include/env_internal.h
index 6a6949464689..99e358b6d8a5 100644
--- a/include/env_internal.h
+++ b/include/env_internal.h
@@ -260,6 +260,29 @@ const char *env_fat_get_intf(void);
  * Return: string of device and partition
  */
 char *env_fat_get_dev_part(void);
+
+/*
+ * _do_env_set() - Add / replace / delete an environment variable
+ *
+ * This implements the bulk of the 'env set' command:
+ *
+ *     env set [-f] name [value]
+ *
+ * Sets the value of variable <name>
+ * If <value> is NULL, it removes the variable
+ * Use the -f flag to overwrite read-only/write-once variables
+ *
+ * @flag: CMD_FLAG_... value
+ * @argc: Number of arguments
+ * @args: List of arguments
+ * @env_flag: H_... flags from search.h
+ * Return: 0 if OK, 1 on failure, or CMD_RET_USAGE for invalid flag
+ */
+int _do_env_set(int flag, int argc, char *const argv[], int env_flag);
+
+/** env_inc_id() - Increment the environment ID */
+void env_inc_id(void);
+
 #endif /* DO_DEPS_ONLY */
 
 #endif /* _ENV_INTERNAL_H_ */
-- 
2.42.0.515.g380fc7ccd1-goog

Reply via email to