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