All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V3 0/3] cmd: env: select: Add output for available environment targets
@ 2025-05-09 19:00 Christoph Niedermaier
  2025-05-09 19:00 ` [PATCH V3 1/3] cmd: nvedit: Convert the parsing of arguments to getopt() Christoph Niedermaier
                   ` (3 more replies)
  0 siblings, 4 replies; 11+ messages in thread
From: Christoph Niedermaier @ 2025-05-09 19:00 UTC (permalink / raw)
  To: u-boot
  Cc: Christoph Niedermaier, Andy Shevchenko, Christian Marangi,
	Heinrich Schuchardt, Ilias Apalodimas, Jerome Forissier,
	Joe Hershberger, Marek Vasut, Michal Simek, Patrick Delaunay,
	Rasmus Villemoes, Simon Glass, Tom Rini, Venkatesh Yadav Abbarapu

Add the "-l" parameter to the "env select" command to print the available
environment targets, convert all argument parsing in the file nvedit.c to
getopt() and check that with unit tests.

The first patch converts the parsing of arguments to getopt() for all env
commands. The second one adds unit tests for checking the env command.
These were used to check the env commands before and after the conversion.
The third patch adds the actual new parameter "-l" for the "env select"
command.

Christoph Niedermaier (3):
  cmd: nvedit: Convert the parsing of arguments to getopt()
  test: cmd: nvedit: Add basic unit tests
  cmd: env: select: Add output for available environment targets

 cmd/nvedit.c      | 353 +++++++++----------
 env/Kconfig       |   1 +
 env/env.c         |  16 +
 include/env.h     |   7 +
 test/cmd/Makefile |   1 +
 test/cmd/nvedit.c | 844 ++++++++++++++++++++++++++++++++++++++++++++++
 test/cmd_ut.c     |   2 +
 7 files changed, 1051 insertions(+), 173 deletions(-)
 create mode 100644 test/cmd/nvedit.c

Signed-off-by: Christoph Niedermaier <cniedermaier@dh-electronics.com>
---
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Christian Marangi <ansuelsmth@gmail.com>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jerome Forissier <jerome.forissier@linaro.org>
Cc: Joe Hershberger <joe.hershberger@ni.com>
Cc: Marek Vasut <marex@denx.de>
Cc: Michal Simek <michal.simek@amd.com>
Cc: Patrick Delaunay <patrick.delaunay@foss.st.com>
Cc: Rasmus Villemoes <ravi@prevas.dk>
Cc: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Venkatesh Yadav Abbarapu <venkatesh.abbarapu@amd.com>
-- 
2.30.2


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH V3 1/3] cmd: nvedit: Convert the parsing of arguments to getopt()
  2025-05-09 19:00 [PATCH V3 0/3] cmd: env: select: Add output for available environment targets Christoph Niedermaier
@ 2025-05-09 19:00 ` Christoph Niedermaier
  2025-05-09 19:00 ` [PATCH V3 2/3] test: cmd: nvedit: Add basic unit tests Christoph Niedermaier
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 11+ messages in thread
From: Christoph Niedermaier @ 2025-05-09 19:00 UTC (permalink / raw)
  To: u-boot
  Cc: Christoph Niedermaier, Andy Shevchenko, Christian Marangi,
	Heinrich Schuchardt, Ilias Apalodimas, Jerome Forissier,
	Joe Hershberger, Marek Vasut, Michal Simek, Patrick Delaunay,
	Rasmus Villemoes, Simon Glass, Tom Rini, Venkatesh Yadav Abbarapu

The entire parsing of the arguments is done manually. Improve this
by converting all parsing of arguments to getopt().

Signed-off-by: Christoph Niedermaier <cniedermaier@dh-electronics.com>
---
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Christian Marangi <ansuelsmth@gmail.com>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jerome Forissier <jerome.forissier@linaro.org>
Cc: Joe Hershberger <joe.hershberger@ni.com>
Cc: Marek Vasut <marex@denx.de>
Cc: Michal Simek <michal.simek@amd.com>
Cc: Patrick Delaunay <patrick.delaunay@foss.st.com>
Cc: Rasmus Villemoes <ravi@prevas.dk>
Cc: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Venkatesh Yadav Abbarapu <venkatesh.abbarapu@amd.com>
---
V3: - Add this patch to the series
---
 cmd/nvedit.c | 335 +++++++++++++++++++++++++--------------------------
 env/Kconfig  |   1 +
 2 files changed, 164 insertions(+), 172 deletions(-)

diff --git a/cmd/nvedit.c b/cmd/nvedit.c
index 1f259801293..e5e89b51e0a 100644
--- a/cmd/nvedit.c
+++ b/cmd/nvedit.c
@@ -41,6 +41,7 @@
 #include <linux/stddef.h>
 #include <asm/byteorder.h>
 #include <asm/io.h>
+#include <getopt.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -92,19 +93,26 @@ static int do_env_print(struct cmd_tbl *cmdtp, int flag, int argc,
 	int i;
 	int rcode = 0;
 	int env_flag = H_HIDE_DOT;
+	struct getopt_state gs;
+	int opt;
 
+	getopt_init_state(&gs);
+	while ((opt = getopt(&gs, argc, argv, "ea")) > 0) {
+		switch (opt) {
+		case 'e':
 #if defined(CONFIG_CMD_NVEDIT_EFI)
-	if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'e')
-		return do_env_print_efi(cmdtp, flag, --argc, ++argv);
+			return do_env_print_efi(cmdtp, flag, argc - gs.index, &argv[gs.index]);
 #endif
-
-	if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'a') {
-		argc--;
-		argv++;
-		env_flag &= ~H_HIDE_DOT;
+			break;
+		case 'a':
+			env_flag &= ~H_HIDE_DOT;
+			break;
+		default:
+			return CMD_RET_USAGE;
+		}
 	}
 
-	if (argc == 1) {
+	if (gs.index == argc) {
 		/* print all env vars */
 		rcode = env_print(NULL, env_flag);
 		if (!rcode)
@@ -116,7 +124,7 @@ static int do_env_print(struct cmd_tbl *cmdtp, int flag, int argc,
 
 	/* print selected env vars */
 	env_flag &= ~H_HIDE_DOT;
-	for (i = 1; i < argc; ++i) {
+	for (i = gs.index; i < argc; ++i) {
 		int rc = env_print(argv[i], env_flag);
 		if (!rc) {
 			printf("## Error: \"%s\" not defined\n", argv[i]);
@@ -133,6 +141,8 @@ static int do_env_grep(struct cmd_tbl *cmdtp, int flag,
 {
 	char *res = NULL;
 	int len, grep_how, grep_what;
+	struct getopt_state gs;
+	int opt;
 
 	if (argc < 2)
 		return CMD_RET_USAGE;
@@ -140,36 +150,31 @@ static int do_env_grep(struct cmd_tbl *cmdtp, int flag,
 	grep_how  = H_MATCH_SUBSTR;	/* default: substring search	*/
 	grep_what = H_MATCH_BOTH;	/* default: grep names and values */
 
-	while (--argc > 0 && **++argv == '-') {
-		char *arg = *argv;
-		while (*++arg) {
-			switch (*arg) {
+	getopt_init_state(&gs);
+	while ((opt = getopt(&gs, argc, argv, "envb")) > 0) {
+		switch (opt) {
 #ifdef CONFIG_REGEX
-			case 'e':		/* use regex matching */
-				grep_how  = H_MATCH_REGEX;
-				break;
+		case 'e':		/* use regex matching */
+			grep_how  = H_MATCH_REGEX;
+			break;
 #endif
-			case 'n':		/* grep for name */
-				grep_what = H_MATCH_KEY;
-				break;
-			case 'v':		/* grep for value */
-				grep_what = H_MATCH_DATA;
-				break;
-			case 'b':		/* grep for both */
-				grep_what = H_MATCH_BOTH;
-				break;
-			case '-':
-				goto DONE;
-			default:
-				return CMD_RET_USAGE;
-			}
+		case 'n':		/* grep for name */
+			grep_what = H_MATCH_KEY;
+			break;
+		case 'v':		/* grep for value */
+			grep_what = H_MATCH_DATA;
+			break;
+		case 'b':		/* grep for both */
+			grep_what = H_MATCH_BOTH;
+			break;
+		default:
+			return CMD_RET_USAGE;
 		}
 	}
 
-DONE:
 	len = hexport_r(&env_htab, '\n',
 			flag | grep_what | grep_how,
-			&res, 0, argc, argv);
+			&res, 0, argc - gs.index, &argv[gs.index]);
 
 	if (len > 0) {
 		puts(res);
@@ -510,37 +515,34 @@ static int do_env_default(struct cmd_tbl *cmdtp, int flag,
 			  int argc, char *const argv[])
 {
 	int all = 0, env_flag = H_INTERACTIVE;
-
-	debug("Initial value for argc=%d\n", argc);
-	while (--argc > 0 && **++argv == '-') {
-		char *arg = *argv;
-
-		while (*++arg) {
-			switch (*arg) {
-			case 'a':		/* default all */
-				all = 1;
-				break;
-			case 'f':		/* force */
-				env_flag |= H_FORCE;
-				break;
-			case 'k':
-				env_flag |= H_NOCLEAR;
-				break;
-			default:
-				return cmd_usage(cmdtp);
-			}
+	struct getopt_state gs;
+	int opt;
+
+	getopt_init_state(&gs);
+	while ((opt = getopt(&gs, argc, argv, "afk")) > 0) {
+		switch (opt) {
+		case 'a':		/* default all */
+			all = 1;
+			break;
+		case 'f':		/* force */
+			env_flag |= H_FORCE;
+			break;
+		case 'k':
+			env_flag |= H_NOCLEAR;
+			break;
+		default:
+			return cmd_usage(cmdtp);
 		}
 	}
-	debug("Final value for argc=%d\n", argc);
-	if (all && (argc == 0)) {
+	if (all && (argc == gs.index)) {
 		/* Reset the whole environment */
 		env_set_default("## Resetting to default environment\n",
 				env_flag);
 		return 0;
 	}
-	if (!all && (argc > 0)) {
+	if (!all && (argc > gs.index)) {
 		/* Reset individual variables */
-		env_set_default_vars(argc, argv, env_flag);
+		env_set_default_vars(argc - gs.index, &argv[gs.index], env_flag);
 		return 0;
 	}
 
@@ -552,32 +554,26 @@ static int do_env_delete(struct cmd_tbl *cmdtp, int flag,
 {
 	int env_flag = H_INTERACTIVE;
 	int ret = 0;
+	struct getopt_state gs;
+	int opt;
+	int i;
 
-	debug("Initial value for argc=%d\n", argc);
-	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;
-			}
+	getopt_init_state(&gs);
+	while ((opt = getopt(&gs, argc, argv, "f")) > 0) {
+		switch (opt) {
+		case 'f':		/* force */
+			env_flag |= H_FORCE;
+			break;
+		default:
+			return CMD_RET_USAGE;
 		}
 	}
-	debug("Final value for argc=%d\n", argc);
 
 	env_inc_id();
 
-	while (--argc > 0) {
-		char *name = *++argv;
-
-		if (hdelete_r(name, &env_htab, env_flag))
+	for (i = gs.index; i < argc; i++)
+		if (hdelete_r(argv[i], &env_htab, env_flag))
 			ret = 1;
-	}
 
 	return ret;
 }
@@ -633,64 +629,58 @@ static int do_env_export(struct cmd_tbl *cmdtp, int flag,
 {
 	char	buf[32];
 	ulong	addr;
-	char	*ptr, *cmd, *res;
+	char	*ptr, *res;
 	size_t	size = 0;
 	ssize_t	len;
 	env_t	*envp;
 	char	sep = '\n';
 	int	chk = 0;
 	int	fmt = 0;
-
-	cmd = *argv;
-
-	while (--argc > 0 && **++argv == '-') {
-		char *arg = *argv;
-		while (*++arg) {
-			switch (*arg) {
-			case 'b':		/* raw binary format */
-				if (fmt++)
-					goto sep_err;
-				sep = '\0';
-				break;
-			case 'c':		/* external checksum format */
-				if (fmt++)
-					goto sep_err;
-				sep = '\0';
-				chk = 1;
-				break;
-			case 's':		/* size given */
-				if (--argc <= 0)
-					return cmd_usage(cmdtp);
-				size = hextoul(*++argv, NULL);
-				goto NXTARG;
-			case 't':		/* text format */
-				if (fmt++)
-					goto sep_err;
-				sep = '\n';
-				break;
-			default:
-				return CMD_RET_USAGE;
-			}
+	struct getopt_state gs;
+	int opt;
+
+	getopt_init_state(&gs);
+	while ((opt = getopt(&gs, argc, argv, "bcs:t")) > 0) {
+		switch (opt) {
+		case 'b':		/* raw binary format */
+			if (fmt++)
+				goto sep_err;
+			sep = '\0';
+			break;
+		case 'c':		/* external checksum format */
+			if (fmt++)
+				goto sep_err;
+			sep = '\0';
+			chk = 1;
+			break;
+		case 's':		/* size given */
+			size = hextoul(gs.arg, NULL);
+			break;
+		case 't':		/* text format */
+			if (fmt++)
+				goto sep_err;
+			sep = '\n';
+			break;
+		default:
+			return CMD_RET_USAGE;
 		}
-NXTARG:		;
 	}
 
-	if (argc < 1)
+	if (argc == gs.index)
 		return CMD_RET_USAGE;
 
-	addr = hextoul(argv[0], NULL);
+	addr = hextoul(argv[gs.index], NULL);
 	ptr = map_sysmem(addr, size);
 
+	gs.index++;
+
 	if (size)
 		memset(ptr, '\0', size);
 
-	argc--;
-	argv++;
-
 	if (sep) {		/* export as text file */
 		len = hexport_r(&env_htab, sep,
 				H_MATCH_KEY | H_MATCH_IDENT,
-				&ptr, size, argc, argv);
+				&ptr, size, argc - gs.index, &argv[gs.index]);
 		if (len < 0) {
 			pr_err("## Error: Cannot export environment: errno = %d\n",
 			       errno);
@@ -711,7 +701,7 @@ NXTARG:		;
 
 	len = hexport_r(&env_htab, '\0',
 			H_MATCH_KEY | H_MATCH_IDENT,
-			&res, ENV_SIZE, argc, argv);
+			&res, ENV_SIZE, argc - gs.index, &argv[gs.index]);
 	if (len < 0) {
 		pr_err("## Error: Cannot export environment: errno = %d\n",
 		       errno);
@@ -731,7 +721,7 @@ NXTARG:		;
 
 sep_err:
 	printf("## Error: %s: only one of \"-b\", \"-c\" or \"-t\" allowed\n",
-	       cmd);
+	       argv[0]);
 	return 1;
 }
 #endif
@@ -765,7 +755,7 @@ static int do_env_import(struct cmd_tbl *cmdtp, int flag,
 			 int argc, char *const argv[])
 {
 	ulong	addr;
-	char	*cmd, *ptr;
+	char	*ptr;
 	char	sep = '\n';
 	int	chk = 0;
 	int	fmt = 0;
@@ -773,42 +763,40 @@ static int do_env_import(struct cmd_tbl *cmdtp, int flag,
 	int	crlf_is_lf = 0;
 	int	wl = 0;
 	size_t	size;
-
-	cmd = *argv;
-
-	while (--argc > 0 && **++argv == '-') {
-		char *arg = *argv;
-		while (*++arg) {
-			switch (*arg) {
-			case 'b':		/* raw binary format */
-				if (fmt++)
-					goto sep_err;
-				sep = '\0';
-				break;
-			case 'c':		/* external checksum format */
-				if (fmt++)
-					goto sep_err;
-				sep = '\0';
-				chk = 1;
-				break;
-			case 't':		/* text format */
-				if (fmt++)
-					goto sep_err;
-				sep = '\n';
-				break;
-			case 'r':		/* handle CRLF like LF */
-				crlf_is_lf = 1;
-				break;
-			case 'd':
-				del = 1;
-				break;
-			default:
-				return CMD_RET_USAGE;
-			}
+	struct getopt_state gs;
+	int opt;
+
+	getopt_init_state(&gs);
+	while ((opt = getopt(&gs, argc, argv, "bctrd")) > 0) {
+		switch (opt) {
+		case 'b':		/* raw binary format */
+			if (fmt++)
+				goto sep_err;
+			sep = '\0';
+			break;
+		case 'c':		/* external checksum format */
+			if (fmt++)
+				goto sep_err;
+			sep = '\0';
+			chk = 1;
+			break;
+		case 't':		/* text format */
+			if (fmt++)
+				goto sep_err;
+			sep = '\n';
+			break;
+		case 'r':		/* handle CRLF like LF */
+			crlf_is_lf = 1;
+			break;
+		case 'd':
+			del = 1;
+			break;
+		default:
+			return CMD_RET_USAGE;
 		}
 	}
 
-	if (argc < 1)
+	if (argc == gs.index)
 		return CMD_RET_USAGE;
 
 	if (!fmt)
@@ -817,11 +805,13 @@ static int do_env_import(struct cmd_tbl *cmdtp, int flag,
 	if (sep != '\n' && crlf_is_lf )
 		crlf_is_lf = 0;
 
-	addr = hextoul(argv[0], NULL);
+	addr = hextoul(argv[gs.index], NULL);
 	ptr = map_sysmem(addr, 0);
 
-	if (argc >= 2 && strcmp(argv[1], "-")) {
-		size = hextoul(argv[1], NULL);
+	gs.index++;
+
+	if (argc - gs.index >= 1 && strcmp(argv[gs.index], "-")) {
+		size = hextoul(argv[gs.index], NULL);
 	} else if (chk) {
 		puts("## Error: external checksum format must pass size\n");
 		return CMD_RET_FAILURE;
@@ -844,7 +834,7 @@ static int do_env_import(struct cmd_tbl *cmdtp, int flag,
 		printf("## Info: input data size = %zu = 0x%zX\n", size, size);
 	}
 
-	if (argc > 2)
+	if (argc - gs.index > 1)
 		wl = 1;
 
 	if (chk) {
@@ -866,8 +856,10 @@ static int do_env_import(struct cmd_tbl *cmdtp, int flag,
 		ptr = (char *)ep->data;
 	}
 
+	gs.index++;
+
 	if (!himport_r(&env_htab, ptr, size, sep, del ? 0 : H_NOCLEAR,
-		       crlf_is_lf, wl ? argc - 2 : 0, wl ? &argv[2] : NULL)) {
+		       crlf_is_lf, wl ? argc - gs.index : 0, wl ? &argv[gs.index] : NULL)) {
 		pr_err("## Error: Environment import failed: errno = %d\n",
 		       errno);
 		return 1;
@@ -878,7 +870,7 @@ static int do_env_import(struct cmd_tbl *cmdtp, int flag,
 
 sep_err:
 	printf("## %s: only one of \"-b\", \"-c\" or \"-t\" allowed\n",
-		cmd);
+		argv[0]);
 	return 1;
 }
 #endif
@@ -971,6 +963,8 @@ static int do_env_info(struct cmd_tbl *cmdtp, int flag,
 	int eval_flags = 0;
 	int eval_results = 0;
 	bool quiet = false;
+	struct getopt_state gs;
+	int opt;
 #if defined(CONFIG_CMD_SAVEENV) && !IS_ENABLED(CONFIG_ENV_IS_DEFAULT)
 	enum env_location loc;
 #endif
@@ -980,23 +974,20 @@ static int do_env_info(struct cmd_tbl *cmdtp, int flag,
 		return print_env_info();
 
 	/* process options */
-	while (--argc > 0 && **++argv == '-') {
-		char *arg = *argv;
-
-		while (*++arg) {
-			switch (*arg) {
-			case 'd':
-				eval_flags |= ENV_INFO_IS_DEFAULT;
-				break;
-			case 'p':
-				eval_flags |= ENV_INFO_IS_PERSISTED;
-				break;
-			case 'q':
-				quiet = true;
-				break;
-			default:
-				return CMD_RET_USAGE;
-			}
+	getopt_init_state(&gs);
+	while ((opt = getopt(&gs, argc, argv, "dpq")) > 0) {
+		switch (opt) {
+		case 'd':
+			eval_flags |= ENV_INFO_IS_DEFAULT;
+			break;
+		case 'p':
+			eval_flags |= ENV_INFO_IS_PERSISTED;
+			break;
+		case 'q':
+			quiet = true;
+			break;
+		default:
+			return CMD_RET_USAGE;
 		}
 	}
 
diff --git a/env/Kconfig b/env/Kconfig
index 9f5ec44601e..9b6cce62999 100644
--- a/env/Kconfig
+++ b/env/Kconfig
@@ -2,6 +2,7 @@ menu "Environment"
 
 config ENV_SUPPORT
 	def_bool y
+	select GETOPT
 
 config ENV_SOURCE_FILE
 	string "Environment file to use"
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH V3 2/3] test: cmd: nvedit: Add basic unit tests
  2025-05-09 19:00 [PATCH V3 0/3] cmd: env: select: Add output for available environment targets Christoph Niedermaier
  2025-05-09 19:00 ` [PATCH V3 1/3] cmd: nvedit: Convert the parsing of arguments to getopt() Christoph Niedermaier
@ 2025-05-09 19:00 ` Christoph Niedermaier
  2025-06-03 20:12   ` Tom Rini
  2025-05-09 19:00 ` [PATCH V3 3/3] cmd: env: select: Add output for available environment targets Christoph Niedermaier
  2025-05-12  7:37 ` [PATCH V3 0/3] " Andy Shevchenko
  3 siblings, 1 reply; 11+ messages in thread
From: Christoph Niedermaier @ 2025-05-09 19:00 UTC (permalink / raw)
  To: u-boot
  Cc: Christoph Niedermaier, Andy Shevchenko, Christian Marangi,
	Heinrich Schuchardt, Ilias Apalodimas, Jerome Forissier,
	Joe Hershberger, Marek Vasut, Michal Simek, Patrick Delaunay,
	Rasmus Villemoes, Simon Glass, Tom Rini, Venkatesh Yadav Abbarapu

Add basic unit tests for argument checking of the env command.

Signed-off-by: Christoph Niedermaier <cniedermaier@dh-electronics.com>
---
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Christian Marangi <ansuelsmth@gmail.com>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jerome Forissier <jerome.forissier@linaro.org>
Cc: Joe Hershberger <joe.hershberger@ni.com>
Cc: Marek Vasut <marex@denx.de>
Cc: Michal Simek <michal.simek@amd.com>
Cc: Patrick Delaunay <patrick.delaunay@foss.st.com>
Cc: Rasmus Villemoes <ravi@prevas.dk>
Cc: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Venkatesh Yadav Abbarapu <venkatesh.abbarapu@amd.com>
---
V3: - Add this patch to the series
---
 test/cmd/Makefile |   1 +
 test/cmd/nvedit.c | 844 ++++++++++++++++++++++++++++++++++++++++++++++
 test/cmd_ut.c     |   2 +
 3 files changed, 847 insertions(+)
 create mode 100644 test/cmd/nvedit.c

diff --git a/test/cmd/Makefile b/test/cmd/Makefile
index 595e4cfcada..4149e82e5ea 100644
--- a/test/cmd/Makefile
+++ b/test/cmd/Makefile
@@ -23,6 +23,7 @@ obj-$(CONFIG_CMD_LOADM) += loadm.o
 obj-$(CONFIG_CMD_MEMINFO) += meminfo.o
 obj-$(CONFIG_CMD_MEMORY) += mem_copy.o
 obj-$(CONFIG_CMD_MEM_SEARCH) += mem_search.o
+obj-$(CONFIG_ENV_SUPPORT) += nvedit.o
 ifdef CONFIG_CMD_PCI
 obj-$(CONFIG_CMD_PCI_MPS) += pci_mps.o
 endif
diff --git a/test/cmd/nvedit.c b/test/cmd/nvedit.c
new file mode 100644
index 00000000000..bb845de1597
--- /dev/null
+++ b/test/cmd/nvedit.c
@@ -0,0 +1,844 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Tests for env command
+ *
+ * Copyright (C) 2025 Christoph Niedermaier <cniedermaier@dh-electronics.com>
+ */
+
+#include <asm/global_data.h>
+#include <command.h>
+#include <env.h>
+#include <env_internal.h>
+#include <linux/errno.h>
+#include <log.h>
+#include <string.h>
+#include <test/cmd.h>
+#include <test/ut.h>
+
+/* Declare a new nvedit test */
+#define NVEDIT_TEST(_name, _flags)	UNIT_TEST(_name, _flags, nvedit)
+
+static int nvedit_test_print(struct unit_test_state *uts)
+{
+	ut_assertok(run_command("env set .Testdotvar dotvalue", 0));
+	ut_assertok(run_command("env set TestvarP1 valueP1", 0));
+	ut_assertok(run_command("env set TestvarP2 valueP2", 0));
+	ut_assert_console_end();
+
+	ut_assertok(run_command("env print .Testdotvar TestvarP1 TestvarP2", 0));
+	ut_assert_nextline(".Testdotvar=dotvalue");
+	ut_assert_nextline("TestvarP1=valueP1");
+	ut_assert_nextline("TestvarP2=valueP2");
+	ut_assert_console_end();
+
+	return 0;
+}
+NVEDIT_TEST(nvedit_test_print, UTF_CONSOLE);
+
+#if CONFIG_IS_ENABLED(CMD_GREPENV)
+static int nvedit_test_grep(struct unit_test_state *uts)
+{
+	ut_assertok(run_command("env set TestvarG1 valueG1", 0));
+	ut_assertok(run_command("env set TestvarG2 valueG2", 0));
+	ut_assertok(run_command("env set TestvarG3 valueG3", 0));
+	ut_assertok(run_command("env set TestGREP '-e -n -v -b'", 0));
+	ut_assert_console_end();
+
+	/* Match for name */
+	ut_assertok(run_command("env grep -n TestvarG1", 0));
+	ut_assert_nextline("TestvarG1=valueG1");
+	ut_assert_console_end();
+	ut_assert(run_command("env grep -n valueG1", 0));
+	ut_assert_console_end();
+
+	/* Match for value */
+	ut_assertok(run_command("env grep -v valueG2", 0));
+	ut_assert_nextline("TestvarG2=valueG2");
+	ut_assert_console_end();
+	ut_assert(run_command("env grep -v TestvarG2", 0));
+	ut_assert_console_end();
+
+	/* Match for name and value */
+	ut_assertok(run_command("env grep -b TestvarG3", 0));
+	ut_assert_nextline("TestvarG3=valueG3");
+	ut_assert_console_end();
+	ut_assertok(run_command("env grep -b valueG3", 0));
+	ut_assert_nextline("TestvarG3=valueG3");
+	ut_assert_console_end();
+
+	/* Match for name and value (without a parameter) */
+	ut_assertok(run_command("env grep TestvarG3", 0));
+	ut_assert_nextline("TestvarG3=valueG3");
+	ut_assert_console_end();
+	ut_assertok(run_command("env grep valueG3", 0));
+	ut_assert_nextline("TestvarG3=valueG3");
+	ut_assert_console_end();
+
+#if CONFIG_IS_ENABLED(REGEX)
+	ut_assertok(run_command("env grep -e TestvarG[13]", 0));
+	ut_assert_nextline("TestvarG1=valueG1");
+	ut_assert_nextline("TestvarG3=valueG3");
+	ut_assert_console_end();
+#endif
+
+	/* Test '--' */
+	ut_assertok(run_command("env grep -- '-e -n -v -b'", 0));
+	ut_assert_nextline("TestGREP=-e -n -v -b");
+	ut_assert_console_end();
+
+	return 0;
+}
+NVEDIT_TEST(nvedit_test_grep, UTF_CONSOLE);
+#endif /* CONFIG_IS_ENABLED(CMD_GREPENV) */
+
+static int nvedit_test_default(struct unit_test_state *uts)
+{
+	ut_assertok(run_command("env set TestvarDEF1 valueDEF1", 0));
+	ut_assertok(run_command("env set TestvarDEF2 valueDEF2", 0));
+	ut_assert_console_end();
+
+	ut_assertok(run_command("env default TestvarDEF1", 0));
+	ut_assert_nextline("WARNING: 'TestvarDEF1' not in imported env, deleting it!");
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env print TestvarDEF1", 0));
+	ut_assert_nextline("## Error: \"TestvarDEF1\" not defined");
+	ut_assert_console_end();
+	ut_asserteq(0, run_command("env print TestvarDEF2", 0));
+	ut_assert_nextline("TestvarDEF2=valueDEF2");
+	ut_assert_console_end();
+
+	ut_assertok(run_command("env set TestvarDEF1 nextvalue", 0));
+	ut_assert_console_end();
+	ut_assertok(run_command("env default -k TestvarDEF1", 0));
+	ut_assert_console_end();
+	ut_asserteq(0, run_command("env print TestvarDEF1", 0));
+	ut_assert_nextline("TestvarDEF1=nextvalue");
+	ut_assert_console_end();
+	ut_asserteq(0, run_command("env print TestvarDEF2", 0));
+	ut_assert_nextline("TestvarDEF2=valueDEF2");
+	ut_assert_console_end();
+
+	ut_assertok(run_command("env default -k -a -f", 0));
+	ut_assert_nextline("## Resetting to default environment");
+	ut_assert_console_end();
+	ut_asserteq(0, run_command("env print TestvarDEF1", 0));
+	ut_assert_nextline("TestvarDEF1=nextvalue");
+	ut_assert_console_end();
+	ut_asserteq(0, run_command("env print TestvarDEF2", 0));
+	ut_assert_nextline("TestvarDEF2=valueDEF2");
+	ut_assert_console_end();
+
+	return 0;
+}
+NVEDIT_TEST(nvedit_test_default, UTF_CONSOLE);
+
+static int nvedit_test_delete(struct unit_test_state *uts)
+{
+	ut_assertok(run_command("env set TestvarDEL1 valueDEL1", 0));
+	ut_assertok(run_command("env set TestvarDEL2 valueDEL2", 0));
+	ut_assert_console_end();
+
+	/* Delete one by one */
+	ut_asserteq(0, run_command("env print TestvarDEL1", 0));
+	ut_assert_nextline("TestvarDEL1=valueDEL1");
+	ut_assert_console_end();
+	ut_asserteq(0, run_command("env print TestvarDEL2", 0));
+	ut_assert_nextline("TestvarDEL2=valueDEL2");
+	ut_assert_console_end();
+	ut_assertok(run_command("env delete TestvarDEL1", 0));
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env print TestvarDEL1", 0));
+	ut_assert_nextline("## Error: \"TestvarDEL1\" not defined");
+	ut_assert_console_end();
+	ut_asserteq(0, run_command("env print TestvarDEL2", 0));
+	ut_assert_nextline("TestvarDEL2=valueDEL2");
+	ut_assert_console_end();
+	ut_assertok(run_command("env delete TestvarDEL2", 0));
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env print TestvarDEL1", 0));
+	ut_assert_nextline("## Error: \"TestvarDEL1\" not defined");
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env print TestvarDEL2", 0));
+	ut_assert_nextline("## Error: \"TestvarDEL2\" not defined");
+	ut_assert_console_end();
+
+	ut_assertok(run_command("env set TestvarDEL1 valueDEL1", 0));
+	ut_assertok(run_command("env set TestvarDEL2 valueDEL2", 0));
+	ut_assert_console_end();
+
+	/* Delete both together */
+	ut_asserteq(0, run_command("env print TestvarDEL1", 0));
+	ut_assert_nextline("TestvarDEL1=valueDEL1");
+	ut_assert_console_end();
+	ut_asserteq(0, run_command("env print TestvarDEL2", 0));
+	ut_assert_nextline("TestvarDEL2=valueDEL2");
+	ut_assert_console_end();
+	ut_assertok(run_command("env delete TestvarDEL1 TestvarDEL2", 0));
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env print TestvarDEL1", 0));
+	ut_assert_nextline("## Error: \"TestvarDEL1\" not defined");
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env print TestvarDEL2", 0));
+	ut_assert_nextline("## Error: \"TestvarDEL2\" not defined");
+	ut_assert_console_end();
+
+	ut_asserteq(1, run_command("env delete stdout", 0));
+	ut_assert_nextline("Can't delete \"stdout\"");
+	ut_assert_console_end();
+
+	ut_asserteq(1, run_command("env delete -f stdout", 0));
+	ut_assert_console_end();
+
+	return 0;
+}
+NVEDIT_TEST(nvedit_test_delete, UTF_CONSOLE);
+
+#if CONFIG_IS_ENABLED(CMD_NVEDIT_INFO)
+static int nvedit_test_info(struct unit_test_state *uts)
+{
+	int ret = 0;
+
+	/* Without a parameter */
+	ut_assertok(run_command("env info", 0));
+	ut_assert_nextlinen("env_valid = ");
+	ut_assert_nextlinen("env_ready = ");
+	ut_assert_nextlinen("env_use_default = ");
+	ut_assert_console_end();
+
+	/* Parameter -q (quiet output) */
+	ut_asserteq(0, run_command("env info -q", 0));
+	ut_assert_console_end();
+
+	/* Parameter -d (default environment is used) */
+	ret = run_command("env info -d", 0);
+	if (ret == 0)
+		ut_assert_nextline("Default environment is used");
+	else if (ret == 1)
+		ut_assert_nextline("Environment was loaded from persistent storage");
+	ut_assert_console_end();
+
+	/* Parameter -dq (default environment is used | quiet output) */
+	ret = run_command("env info -dq", 0);
+	ut_asserteq(0, ret > 1);
+	ut_assert_console_end();
+
+	/* Parameter -p (environment can be persisted) */
+	ret = run_command("env info -p", 0);
+	if (ret == 0)
+		ut_assert_nextline("Environment can be persisted");
+	else if (ret == 1)
+		ut_assert_nextline("Environment cannot be persisted");
+	ut_assert_console_end();
+
+	/* Parameter -pq (environment can be persisted | quiet output) */
+	ret = run_command("env info -pq", 0);
+	ut_asserteq(0, ret > 1);
+	ut_assert_console_end();
+
+	return 0;
+}
+NVEDIT_TEST(nvedit_test_info, UTF_CONSOLE);
+#endif
+
+#if CONFIG_IS_ENABLED(CMD_EXPORTENV)
+static int nvedit_test_export(struct unit_test_state *uts)
+{
+	ut_assertok(run_command("env set TestvarE1 valueE1", 0));
+	ut_assertok(run_command("env set TestvarE2 valueE2", 0));
+	ut_assert_console_end();
+
+	/* Test error (combined parameter) */
+	ut_asserteq(1, run_command("env export -tb ${loadaddr} TestvarE1 TestvarE2", 0));
+	ut_assert_nextline("## Error: export: only one of \"-b\", \"-c\" or \"-t\" allowed");
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env export -tc ${loadaddr} TestvarE1 TestvarE2", 0));
+	ut_assert_nextline("## Error: export: only one of \"-b\", \"-c\" or \"-t\" allowed");
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env export -bc ${loadaddr} TestvarE1 TestvarE2", 0));
+	ut_assert_nextline("## Error: export: only one of \"-b\", \"-c\" or \"-t\" allowed");
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env export -tbc ${loadaddr} TestvarE1 TestvarE2", 0));
+	ut_assert_nextline("## Error: export: only one of \"-b\", \"-c\" or \"-t\" allowed");
+	ut_assert_console_end();
+
+	/* Test error (sperate parameter) */
+	ut_asserteq(1, run_command("env export -t -b ${loadaddr} TestvarE1 TestvarE2", 0));
+	ut_assert_nextline("## Error: export: only one of \"-b\", \"-c\" or \"-t\" allowed");
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env export -t -c ${loadaddr} TestvarE1 TestvarE2", 0));
+	ut_assert_nextline("## Error: export: only one of \"-b\", \"-c\" or \"-t\" allowed");
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env export -b -c ${loadaddr} TestvarE1 TestvarE2", 0));
+	ut_assert_nextline("## Error: export: only one of \"-b\", \"-c\" or \"-t\" allowed");
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env export -t -b -c ${loadaddr} TestvarE1 TestvarE2", 0));
+	ut_assert_nextline("## Error: export: only one of \"-b\", \"-c\" or \"-t\" allowed");
+	ut_assert_console_end();
+
+	/* Text format (without parameter -t) */
+	ut_assertok(run_command("env export ${loadaddr} TestvarE1 TestvarE2", 0));
+	ut_assert_console_end();
+	ut_assertok(run_command("md.b ${loadaddr} 25", 0));
+	ut_assert_nextline("%08lx: 54 65 73 74 76 61 72 45 31 3d 76 61 6c 75 65 45  TestvarE1=valueE",
+			   hextoul(env_get("loadaddr"), NULL) + 0x00);
+	ut_assert_nextline("%08lx: 31 0a 54 65 73 74 76 61 72 45 32 3d 76 61 6c 75  1.TestvarE2=valu",
+			   hextoul(env_get("loadaddr"), NULL) + 0x10);
+	ut_assert_nextline("%08lx: 65 45 32 0a 00                                   eE2..",
+			   hextoul(env_get("loadaddr"), NULL) + 0x20);
+	ut_assert_console_end();
+	ut_asserteq_str("25", env_get("filesize"));
+	ut_assert_console_end();
+
+	/* Text format */
+	ut_assertok(run_command("env export -t ${loadaddr} TestvarE1 TestvarE2", 0));
+	ut_assert_console_end();
+	ut_assertok(run_command("md.b ${loadaddr} 25", 0));
+	ut_assert_nextline("%08lx: 54 65 73 74 76 61 72 45 31 3d 76 61 6c 75 65 45  TestvarE1=valueE",
+			   hextoul(env_get("loadaddr"), NULL) + 0x00);
+	ut_assert_nextline("%08lx: 31 0a 54 65 73 74 76 61 72 45 32 3d 76 61 6c 75  1.TestvarE2=valu",
+			   hextoul(env_get("loadaddr"), NULL) + 0x10);
+	ut_assert_nextline("%08lx: 65 45 32 0a 00                                   eE2..",
+			   hextoul(env_get("loadaddr"), NULL) + 0x20);
+	ut_assert_console_end();
+	ut_asserteq_str("25", env_get("filesize"));
+	ut_assert_console_end();
+
+	/* Text format (size too small) */
+	ut_asserteq(1, run_command("env export -t -s 24 ${loadaddr} TestvarE1 TestvarE2", 0));
+	ut_assert_nextline("Env export buffer too small: 36, but need 37");
+	ut_assert_nextline("## Error: Cannot export environment: errno = 12");
+	ut_assert_console_end();
+
+	/* Text format (correct size) */
+	ut_assertok(run_command("env export -t -s 25 ${loadaddr} TestvarE1 TestvarE2", 0));
+	ut_assert_console_end();
+	ut_assertok(run_command("md.b ${loadaddr} 25", 0));
+	ut_assert_nextline("%08lx: 54 65 73 74 76 61 72 45 31 3d 76 61 6c 75 65 45  TestvarE1=valueE",
+			   hextoul(env_get("loadaddr"), NULL) + 0x00);
+	ut_assert_nextline("%08lx: 31 0a 54 65 73 74 76 61 72 45 32 3d 76 61 6c 75  1.TestvarE2=valu",
+			   hextoul(env_get("loadaddr"), NULL) + 0x10);
+	ut_assert_nextline("%08lx: 65 45 32 0a 00                                   eE2..",
+			   hextoul(env_get("loadaddr"), NULL) + 0x20);
+	ut_assert_console_end();
+	ut_asserteq_str("25", env_get("filesize"));
+	ut_assert_console_end();
+
+	/* Text format (size too big => padded with '\0') */
+	ut_assertok(run_command("env export -t -s 30 ${loadaddr} TestvarE1 TestvarE2", 0));
+	ut_assert_console_end();
+	ut_assertok(run_command("md.b ${loadaddr} 30", 0));
+	ut_assert_nextline("%08lx: 54 65 73 74 76 61 72 45 31 3d 76 61 6c 75 65 45  TestvarE1=valueE",
+			   hextoul(env_get("loadaddr"), NULL) + 0x00);
+	ut_assert_nextline("%08lx: 31 0a 54 65 73 74 76 61 72 45 32 3d 76 61 6c 75  1.TestvarE2=valu",
+			   hextoul(env_get("loadaddr"), NULL) + 0x10);
+	ut_assert_nextline("%08lx: 65 45 32 0a 00 00 00 00 00 00 00 00 00 00 00 00  eE2.............",
+			   hextoul(env_get("loadaddr"), NULL) + 0x20);
+	ut_assert_console_end();
+	ut_asserteq_str("30", env_get("filesize"));
+	ut_assert_console_end();
+
+	/* Binary format */
+	ut_assertok(run_command("env export -b ${loadaddr} TestvarE1 TestvarE2", 0));
+	ut_assert_console_end();
+	ut_assertok(run_command("md.b ${loadaddr} 25", 0));
+	ut_assert_nextline("%08lx: 54 65 73 74 76 61 72 45 31 3d 76 61 6c 75 65 45  TestvarE1=valueE",
+			   hextoul(env_get("loadaddr"), NULL) + 0x00);
+	ut_assert_nextline("%08lx: 31 00 54 65 73 74 76 61 72 45 32 3d 76 61 6c 75  1.TestvarE2=valu",
+			   hextoul(env_get("loadaddr"), NULL) + 0x10);
+	ut_assert_nextline("%08lx: 65 45 32 00 00                                   eE2..",
+			   hextoul(env_get("loadaddr"), NULL) + 0x20);
+	ut_assert_console_end();
+	ut_assertok(run_command("echo ${filesize}", 0));
+	ut_assert_nextline("%x", CONFIG_ENV_SIZE);
+	ut_assert_console_end();
+
+	/* Clear memory at loadaddr */
+	ut_assertok(run_commandf("mw.b ${loadaddr} 0x00 %x", CONFIG_ENV_SIZE));
+	ut_assert_console_end();
+
+	/* Binary format with checksum */
+	ut_assertok(run_command("env export -c ${loadaddr} TestvarE1 TestvarE2", 0));
+	ut_assert_console_end();
+	ut_assertok(run_command("md.b ${loadaddr} 2a", 0));
+#if CONFIG_IS_ENABLED(ENV_ADDR_REDUND)
+	ut_assert_nextline("%08lx: b0 8b 81 b5 01 54 65 73 74 76 61 72 45 31 3d 76  .....TestvarE1=v",
+			   hextoul(env_get("loadaddr"), NULL) + 0x00);
+#else
+	ut_assert_nextline("%08lx: b0 8b 81 b5 00 54 65 73 74 76 61 72 45 31 3d 76  .....TestvarE1=v",
+			   hextoul(env_get("loadaddr"), NULL) + 0x00);
+#endif
+	ut_assert_nextline("%08lx: 61 6c 75 65 45 31 00 54 65 73 74 76 61 72 45 32  alueE1.TestvarE2",
+			   hextoul(env_get("loadaddr"), NULL) + 0x10);
+	ut_assert_nextline("%08lx: 3d 76 61 6c 75 65 45 32 00 00                    =valueE2..",
+			   hextoul(env_get("loadaddr"), NULL) + 0x20);
+	ut_assert_console_end();
+	ut_assertok(run_command("echo ${filesize}", 0));
+	ut_assert_nextline("%x", CONFIG_ENV_SIZE);
+	ut_assert_console_end();
+
+	/* Clear memory at loadaddr */
+	ut_assertok(run_commandf("mw.b ${loadaddr} 0x00 %x", CONFIG_ENV_SIZE));
+	ut_assert_console_end();
+
+	/* Binary format with checksum and size */
+	ut_assertok(run_command("env export -c -s 2a ${loadaddr} TestvarE1 TestvarE2", 0));
+	ut_assert_console_end();
+	ut_assertok(run_command("md.b ${loadaddr} 2a", 0));
+#if CONFIG_IS_ENABLED(ENV_ADDR_REDUND)
+	ut_assert_nextline("%08lx: bb 9e b9 96 01 54 65 73 74 76 61 72 45 31 3d 76  .....TestvarE1=v",
+			   hextoul(env_get("loadaddr"), NULL) + 0x00);
+#else
+	ut_assert_nextline("%08lx: bb 9e b9 96 00 54 65 73 74 76 61 72 45 31 3d 76  .....TestvarE1=v",
+			   hextoul(env_get("loadaddr"), NULL) + 0x00);
+#endif
+	ut_assert_nextline("%08lx: 61 6c 75 65 45 31 00 54 65 73 74 76 61 72 45 32  alueE1.TestvarE2",
+			   hextoul(env_get("loadaddr"), NULL) + 0x10);
+	ut_assert_nextline("%08lx: 3d 76 61 6c 75 65 45 32 00 00                    =valueE2..",
+			   hextoul(env_get("loadaddr"), NULL) + 0x20);
+	ut_assert_console_end();
+	ut_assertok(run_command("echo ${filesize}", 0));
+	ut_assert_nextline("%x", CONFIG_ENV_SIZE);
+	ut_assert_console_end();
+
+	return 0;
+}
+NVEDIT_TEST(nvedit_test_export, UTF_CONSOLE);
+#endif
+
+#if CONFIG_IS_ENABLED(CMD_IMPORTENV)
+static int nvedit_test_import(struct unit_test_state *uts)
+{
+	const char example_t[]   = {0x54, 0x65, 0x73, 0x74, 0x76, 0x61, 0x72, 0x49, 0x31, 0x3d,
+				    0x76, 0x61, 0x6c, 0x75, 0x65, 0x49, 0x31, 0x0a, 0x54, 0x65,
+				    0x73, 0x74, 0x76, 0x61, 0x72, 0x49, 0x32, 0x3d, 0x76, 0x61,
+				    0x6c, 0x75, 0x65, 0x49, 0x32, 0x0a, 0x00};
+	const char example_tr[]  = {0x54, 0x65, 0x73, 0x74, 0x76, 0x61, 0x72, 0x49, 0x31, 0x3d,
+				    0x76, 0x61, 0x6c, 0x75, 0x65, 0x49, 0x31, 0x0d, 0x0a, 0x54,
+				    0x65, 0x73, 0x74, 0x76, 0x61, 0x72, 0x49, 0x32, 0x3d, 0x76,
+				    0x61, 0x6c, 0x75, 0x65, 0x49, 0x32, 0x0d, 0x0a, 0x00};
+	const char example_b[]   = {0x54, 0x65, 0x73, 0x74, 0x76, 0x61, 0x72, 0x49, 0x31, 0x3d,
+				    0x76, 0x61, 0x6c, 0x75, 0x65, 0x49, 0x31, 0x00, 0x54, 0x65,
+				    0x73, 0x74, 0x76, 0x61, 0x72, 0x49, 0x32, 0x3d, 0x76, 0x61,
+				    0x6c, 0x75, 0x65, 0x49, 0x32, 0x00, 0x00};
+	const char example_c[]   = {0xa3, 0x4b, 0x72, 0xf5, 0x00, 0x54, 0x65, 0x73, 0x74, 0x76,
+				    0x61, 0x72, 0x49, 0x31, 0x3d, 0x76, 0x61, 0x6c, 0x75, 0x65,
+				    0x49, 0x31, 0x00, 0x54, 0x65, 0x73, 0x74, 0x76, 0x61, 0x72,
+				    0x49, 0x32, 0x3d, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x49, 0x32,
+				    0x00, 0x00};
+	const char example_cw[]  = {0x3a, 0x57, 0xae, 0xc8, 0x00, 0x54, 0x65, 0x73, 0x74, 0x76,
+				    0x61, 0x72, 0x49, 0x31, 0x3d, 0x76, 0x61, 0x6c, 0x75, 0x65,
+				    0x49, 0x31, 0x00, 0x54, 0x65, 0x73, 0x74, 0x76, 0x61, 0x72,
+				    0x49, 0x32, 0x3d, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x49, 0x32,
+				    0x00, 0x00};
+	const char example_inv[] = {0x3d, 0x3d, 0x0a, 0x00};
+	unsigned long loadaddr = hextoul(env_get("loadaddr"), NULL);
+	int index = 0;
+
+	/* Test error (combined parameter) */
+	ut_asserteq(1, run_command("env import -tb ${loadaddr} TestvarI1 TestvarI2", 0));
+	ut_assert_nextline("## import: only one of \"-b\", \"-c\" or \"-t\" allowed");
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env import -tc ${loadaddr} TestvarI1 TestvarI2", 0));
+	ut_assert_nextline("## import: only one of \"-b\", \"-c\" or \"-t\" allowed");
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env import -trb ${loadaddr} TestvarI1 TestvarI2", 0));
+	ut_assert_nextline("## import: only one of \"-b\", \"-c\" or \"-t\" allowed");
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env import -trc ${loadaddr} TestvarI1 TestvarI2", 0));
+	ut_assert_nextline("## import: only one of \"-b\", \"-c\" or \"-t\" allowed");
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env import -bc ${loadaddr} TestvarI1 TestvarI2", 0));
+	ut_assert_nextline("## import: only one of \"-b\", \"-c\" or \"-t\" allowed");
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env import -tbc ${loadaddr} TestvarI1 TestvarI2", 0));
+	ut_assert_nextline("## import: only one of \"-b\", \"-c\" or \"-t\" allowed");
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env import -trbc ${loadaddr} TestvarI1 TestvarI2", 0));
+	ut_assert_nextline("## import: only one of \"-b\", \"-c\" or \"-t\" allowed");
+	ut_assert_console_end();
+
+	/* Test error (sperate parameter) */
+	ut_asserteq(1, run_command("env import -t -b ${loadaddr} TestvarI1 TestvarI2", 0));
+	ut_assert_nextline("## import: only one of \"-b\", \"-c\" or \"-t\" allowed");
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env import -t -c ${loadaddr} TestvarI1 TestvarI2", 0));
+	ut_assert_nextline("## import: only one of \"-b\", \"-c\" or \"-t\" allowed");
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env import -t -r -b ${loadaddr} TestvarI1 TestvarI2", 0));
+	ut_assert_nextline("## import: only one of \"-b\", \"-c\" or \"-t\" allowed");
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env import -t -r -c ${loadaddr} TestvarI1 TestvarI2", 0));
+	ut_assert_nextline("## import: only one of \"-b\", \"-c\" or \"-t\" allowed");
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env import -b -c ${loadaddr} TestvarI1 TestvarI2", 0));
+	ut_assert_nextline("## import: only one of \"-b\", \"-c\" or \"-t\" allowed");
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env import -t -b -c ${loadaddr} TestvarI1 TestvarI2", 0));
+	ut_assert_nextline("## import: only one of \"-b\", \"-c\" or \"-t\" allowed");
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env import -t -r -b -c ${loadaddr} TestvarI1 TestvarI2", 0));
+	ut_assert_nextline("## import: only one of \"-b\", \"-c\" or \"-t\" allowed");
+	ut_assert_console_end();
+
+	/* Text format (without parameter -t) */
+	for (index = 0; index < sizeof(example_t); index++)
+		ut_assertok(run_commandf("mw.b %lx %x", loadaddr + index, example_t[index]));
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env print TestvarI1", 0));
+	ut_assert_nextline("## Error: \"TestvarI1\" not defined");
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env print TestvarI2", 0));
+	ut_assert_nextline("## Error: \"TestvarI2\" not defined");
+	ut_assert_console_end();
+	ut_assertok(run_command("env import ${loadaddr} 25 TestvarI1 TestvarI2", 0));
+	ut_assert_nextline("## Warning: defaulting to text format");
+	ut_assert_console_end();
+	ut_assertok(run_command("env print TestvarI1", 0));
+	ut_assert_nextline("TestvarI1=valueI1");
+	ut_assert_console_end();
+	ut_assertok(run_command("env print TestvarI2", 0));
+	ut_assert_nextline("TestvarI2=valueI2");
+	ut_assert_console_end();
+	ut_assertok(run_command("env delete TestvarI1 TestvarI2", 0));
+	ut_assert_console_end();
+
+	/* Text format */
+	for (index = 0; index < sizeof(example_t); index++)
+		ut_assertok(run_commandf("mw.b %lx %x", loadaddr + index, example_t[index]));
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env print TestvarI1", 0));
+	ut_assert_nextline("## Error: \"TestvarI1\" not defined");
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env print TestvarI2", 0));
+	ut_assert_nextline("## Error: \"TestvarI2\" not defined");
+	ut_assert_console_end();
+	ut_assertok(run_command("env import -t ${loadaddr} 25 TestvarI1 TestvarI2", 0));
+	ut_assert_console_end();
+	ut_assertok(run_command("env print TestvarI1", 0));
+	ut_assert_nextline("TestvarI1=valueI1");
+	ut_assert_console_end();
+	ut_assertok(run_command("env print TestvarI2", 0));
+	ut_assert_nextline("TestvarI2=valueI2");
+	ut_assert_console_end();
+	ut_assertok(run_command("env delete TestvarI1 TestvarI2", 0));
+	ut_assert_console_end();
+
+	/* Text format CRLF (without parameter -t) */
+	for (index = 0; index < sizeof(example_tr); index++)
+		ut_assertok(run_commandf("mw.b %lx %x", loadaddr + index, example_tr[index]));
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env print TestvarI1", 0));
+	ut_assert_nextline("## Error: \"TestvarI1\" not defined");
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env print TestvarI2", 0));
+	ut_assert_nextline("## Error: \"TestvarI2\" not defined");
+	ut_assert_console_end();
+	ut_assertok(run_command("env import -r ${loadaddr} 27 TestvarI1 TestvarI2", 0));
+	ut_assert_nextline("## Warning: defaulting to text format");
+	ut_assert_console_end();
+	ut_assertok(run_command("env print TestvarI1", 0));
+	ut_assert_nextline("TestvarI1=valueI1");
+	ut_assert_console_end();
+	ut_assertok(run_command("env print TestvarI2", 0));
+	ut_assert_nextline("TestvarI2=valueI2");
+	ut_assert_console_end();
+	ut_assertok(run_command("env delete TestvarI1 TestvarI2", 0));
+	ut_assert_console_end();
+
+	/* Text format CRLF */
+	for (index = 0; index < sizeof(example_tr); index++)
+		ut_assertok(run_commandf("mw.b %lx %x", loadaddr + index, example_tr[index]));
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env print TestvarI1", 0));
+	ut_assert_nextline("## Error: \"TestvarI1\" not defined");
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env print TestvarI2", 0));
+	ut_assert_nextline("## Error: \"TestvarI2\" not defined");
+	ut_assert_console_end();
+	ut_assertok(run_command("env import -tr ${loadaddr} 27 TestvarI1 TestvarI2", 0));
+	ut_assert_console_end();
+	ut_assertok(run_command("env print TestvarI1", 0));
+	ut_assert_nextline("TestvarI1=valueI1");
+	ut_assert_console_end();
+	ut_assertok(run_command("env print TestvarI2", 0));
+	ut_assert_nextline("TestvarI2=valueI2");
+	ut_assert_console_end();
+	ut_assertok(run_command("env delete TestvarI1 TestvarI2", 0));
+	ut_assert_console_end();
+
+	/* Text format without size (without parameter -t) */
+	for (index = 0; index < sizeof(example_t); index++)
+		ut_assertok(run_commandf("mw.b %lx %x", loadaddr + index, example_t[index]));
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env print TestvarI1", 0));
+	ut_assert_nextline("## Error: \"TestvarI1\" not defined");
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env print TestvarI2", 0));
+	ut_assert_nextline("## Error: \"TestvarI2\" not defined");
+	ut_assert_console_end();
+	ut_assertok(run_command("env import ${loadaddr} - TestvarI1 TestvarI2", 0));
+	ut_assert_nextline("## Warning: defaulting to text format");
+	ut_assert_nextline("## Info: input data size = 37 = 0x25");
+	ut_assert_console_end();
+	ut_assertok(run_command("env print TestvarI1", 0));
+	ut_assert_nextline("TestvarI1=valueI1");
+	ut_assert_console_end();
+	ut_assertok(run_command("env print TestvarI2", 0));
+	ut_assert_nextline("TestvarI2=valueI2");
+	ut_assert_console_end();
+	ut_assertok(run_command("env delete TestvarI1 TestvarI2", 0));
+	ut_assert_console_end();
+
+	/* Text format without size */
+	for (index = 0; index < sizeof(example_t); index++)
+		ut_assertok(run_commandf("mw.b %lx %x", loadaddr + index, example_t[index]));
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env print TestvarI1", 0));
+	ut_assert_nextline("## Error: \"TestvarI1\" not defined");
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env print TestvarI2", 0));
+	ut_assert_nextline("## Error: \"TestvarI2\" not defined");
+	ut_assert_console_end();
+	ut_assertok(run_command("env import -t ${loadaddr} - TestvarI1 TestvarI2", 0));
+	ut_assert_nextline("## Info: input data size = 37 = 0x25");
+	ut_assert_console_end();
+	ut_assertok(run_command("env print TestvarI1", 0));
+	ut_assert_nextline("TestvarI1=valueI1");
+	ut_assert_console_end();
+	ut_assertok(run_command("env print TestvarI2", 0));
+	ut_assert_nextline("TestvarI2=valueI2");
+	ut_assert_console_end();
+	ut_assertok(run_command("env delete TestvarI1 TestvarI2", 0));
+	ut_assert_console_end();
+
+	/* Text format with delete parameter (without parameter -t) */
+	for (index = 0; index < sizeof(example_t); index++)
+		ut_assertok(run_commandf("mw.b %lx %x", loadaddr + index, example_t[index]));
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env print TestvarI1", 0));
+	ut_assert_nextline("## Error: \"TestvarI1\" not defined");
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env print TestvarI2", 0));
+	ut_assert_nextline("## Error: \"TestvarI2\" not defined");
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env print TestvarI3", 0));
+	ut_assert_nextline("## Error: \"TestvarI3\" not defined");
+	ut_assert_console_end();
+	ut_assertok(run_command("env set TestvarI3 valueI3", 0));
+	ut_assert_console_end();
+	ut_assertok(run_command("env import -d ${loadaddr} 25 TestvarI1 TestvarI2 TestvarI3", 0));
+	ut_assert_nextline("## Warning: defaulting to text format");
+	ut_assert_nextline("WARNING: 'TestvarI3' not in imported env, deleting it!");
+	ut_assert_console_end();
+	ut_assertok(run_command("env print TestvarI1", 0));
+	ut_assert_nextline("TestvarI1=valueI1");
+	ut_assert_console_end();
+	ut_assertok(run_command("env print TestvarI2", 0));
+	ut_assert_nextline("TestvarI2=valueI2");
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env print TestvarI3", 0));
+	ut_assert_nextline("## Error: \"TestvarI3\" not defined");
+	ut_assert_console_end();
+	ut_assertok(run_command("env delete TestvarI1 TestvarI2", 0));
+	ut_assert_console_end();
+
+	/* Text format with delete parameter */
+	for (index = 0; index < sizeof(example_t); index++)
+		ut_assertok(run_commandf("mw.b %lx %x", loadaddr + index, example_t[index]));
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env print TestvarI1", 0));
+	ut_assert_nextline("## Error: \"TestvarI1\" not defined");
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env print TestvarI2", 0));
+	ut_assert_nextline("## Error: \"TestvarI2\" not defined");
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env print TestvarI3", 0));
+	ut_assert_nextline("## Error: \"TestvarI3\" not defined");
+	ut_assert_console_end();
+	ut_assertok(run_command("env set TestvarI3 valueI3", 0));
+	ut_assert_console_end();
+	ut_assertok(run_command("env import -d -t ${loadaddr} 25 TestvarI1 TestvarI2 TestvarI3", 0));
+	ut_assert_nextline("WARNING: 'TestvarI3' not in imported env, deleting it!");
+	ut_assert_console_end();
+	ut_assertok(run_command("env print TestvarI1", 0));
+	ut_assert_nextline("TestvarI1=valueI1");
+	ut_assert_console_end();
+	ut_assertok(run_command("env print TestvarI2", 0));
+	ut_assert_nextline("TestvarI2=valueI2");
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env print TestvarI3", 0));
+	ut_assert_nextline("## Error: \"TestvarI3\" not defined");
+	ut_assert_console_end();
+	ut_assertok(run_command("env delete TestvarI1 TestvarI2", 0));
+	ut_assert_console_end();
+
+	/* Text format with delete parameter and without vars (without parameter -t) */
+	for (index = 0; index < sizeof(example_t); index++)
+		ut_assertok(run_commandf("mw.b %lx %x", loadaddr + index, example_t[index]));
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env print TestvarI1", 0));
+	ut_assert_nextline("## Error: \"TestvarI1\" not defined");
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env print TestvarI2", 0));
+	ut_assert_nextline("## Error: \"TestvarI2\" not defined");
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env print TestvarI3", 0));
+	ut_assert_nextline("## Error: \"TestvarI3\" not defined");
+	ut_assert_console_end();
+	ut_assertok(run_command("env set TestvarI3 valueI3", 0));
+	ut_assert_console_end();
+	ut_assertok(run_command("env import -d ${loadaddr} 25", 0));
+	ut_assert_nextline("## Warning: defaulting to text format");
+	ut_assert_console_end();
+	ut_assertok(run_command("env print TestvarI1", 0));
+	ut_assert_nextline("TestvarI1=valueI1");
+	ut_assert_console_end();
+	ut_assertok(run_command("env print TestvarI2", 0));
+	ut_assert_nextline("TestvarI2=valueI2");
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env print TestvarI3", 0));
+	ut_assert_nextline("## Error: \"TestvarI3\" not defined");
+	ut_assert_console_end();
+	ut_assertok(run_command("env default -a", 0));
+	ut_assert_nextline("## Resetting to default environment");
+	ut_assert_console_end();
+
+	/* Text format with delete parameter and without vars */
+	for (index = 0; index < sizeof(example_t); index++)
+		ut_assertok(run_commandf("mw.b %lx %x", loadaddr + index, example_t[index]));
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env print TestvarI1", 0));
+	ut_assert_nextline("## Error: \"TestvarI1\" not defined");
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env print TestvarI2", 0));
+	ut_assert_nextline("## Error: \"TestvarI2\" not defined");
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env print TestvarI3", 0));
+	ut_assert_nextline("## Error: \"TestvarI3\" not defined");
+	ut_assert_console_end();
+	ut_assertok(run_command("env set TestvarI3 valueI3", 0));
+	ut_assert_console_end();
+	ut_assertok(run_command("env import -d -t ${loadaddr} 25", 0));
+	ut_assert_console_end();
+	ut_assertok(run_command("env print TestvarI1", 0));
+	ut_assert_nextline("TestvarI1=valueI1");
+	ut_assert_console_end();
+	ut_assertok(run_command("env print TestvarI2", 0));
+	ut_assert_nextline("TestvarI2=valueI2");
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env print TestvarI3", 0));
+	ut_assert_nextline("## Error: \"TestvarI3\" not defined");
+	ut_assert_console_end();
+	ut_assertok(run_command("env default -a", 0));
+	ut_assert_nextline("## Resetting to default environment");
+	ut_assert_console_end();
+
+	/* Text format with wrong data */
+	for (index = 0; index < sizeof(example_inv); index++)
+		ut_assertok(run_commandf("mw.b %lx %x", loadaddr + index, example_inv[index]));
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env import -t ${loadaddr} 4", 0));
+	ut_assert_nextline("## Error: Environment import failed: errno = 22");
+	ut_assert_console_end();
+
+	/* Binary format */
+	for (index = 0; index < sizeof(example_b); index++)
+		ut_assertok(run_commandf("mw.b %lx %x", loadaddr + index, example_b[index]));
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env print TestvarI1", 0));
+	ut_assert_nextline("## Error: \"TestvarI1\" not defined");
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env print TestvarI2", 0));
+	ut_assert_nextline("## Error: \"TestvarI2\" not defined");
+	ut_assert_console_end();
+	ut_assertok(run_command("env import -b ${loadaddr} 25 TestvarI1 TestvarI2", 0));
+	ut_assert_console_end();
+	ut_assertok(run_command("env print TestvarI1", 0));
+	ut_assert_nextline("TestvarI1=valueI1");
+	ut_assert_console_end();
+	ut_assertok(run_command("env print TestvarI2", 0));
+	ut_assert_nextline("TestvarI2=valueI2");
+	ut_assert_console_end();
+	ut_assertok(run_command("env delete TestvarI1 TestvarI2", 0));
+	ut_assert_console_end();
+
+	/* Binary format without size */
+	for (index = 0; index < sizeof(example_b); index++)
+		ut_assertok(run_commandf("mw.b %lx %x", loadaddr + index, example_b[index]));
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env print TestvarI1", 0));
+	ut_assert_nextline("## Error: \"TestvarI1\" not defined");
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env print TestvarI2", 0));
+	ut_assert_nextline("## Error: \"TestvarI2\" not defined");
+	ut_assert_console_end();
+	ut_assertok(run_command("env import -b ${loadaddr} - TestvarI1 TestvarI2", 0));
+	ut_assert_nextline("## Info: input data size = 37 = 0x25");
+	ut_assert_console_end();
+	ut_assertok(run_command("env print TestvarI1", 0));
+	ut_assert_nextline("TestvarI1=valueI1");
+	ut_assert_console_end();
+	ut_assertok(run_command("env print TestvarI2", 0));
+	ut_assert_nextline("TestvarI2=valueI2");
+	ut_assert_console_end();
+	ut_assertok(run_command("env delete TestvarI1 TestvarI2", 0));
+	ut_assert_console_end();
+
+	/* Binary format with checksum */
+	for (index = 0; index < sizeof(example_c); index++)
+		ut_assertok(run_commandf("mw.b %lx %x", loadaddr + index, example_c[index]));
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env print TestvarI1", 0));
+	ut_assert_nextline("## Error: \"TestvarI1\" not defined");
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env print TestvarI2", 0));
+	ut_assert_nextline("## Error: \"TestvarI2\" not defined");
+	ut_assert_console_end();
+	ut_assertok(run_command("env import -c ${loadaddr} 2a TestvarI1 TestvarI2", 0));
+	ut_assert_console_end();
+	ut_assertok(run_command("env print TestvarI1", 0));
+	ut_assert_nextline("TestvarI1=valueI1");
+	ut_assert_console_end();
+	ut_assertok(run_command("env print TestvarI2", 0));
+	ut_assert_nextline("TestvarI2=valueI2");
+	ut_assert_console_end();
+	ut_assertok(run_command("env delete TestvarI1 TestvarI2", 0));
+	ut_assert_console_end();
+
+	/* Binary format with wrong checksum */
+	for (index = 0; index < sizeof(example_cw); index++)
+		ut_assertok(run_commandf("mw.b %lx %x", loadaddr + index, example_cw[index]));
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env print TestvarI1", 0));
+	ut_assert_nextline("## Error: \"TestvarI1\" not defined");
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env print TestvarI2", 0));
+	ut_assert_nextline("## Error: \"TestvarI2\" not defined");
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env import -c ${loadaddr} 2a TestvarI1 TestvarI2", 0));
+	ut_assert_nextline("## Error: bad CRC, import failed");
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env print TestvarI1", 0));
+	ut_assert_nextline("## Error: \"TestvarI1\" not defined");
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env print TestvarI2", 0));
+	ut_assert_nextline("## Error: \"TestvarI2\" not defined");
+	ut_assert_console_end();
+
+	/* Binary format with checksum and without size */
+	for (index = 0; index < sizeof(example_c); index++)
+		ut_assertok(run_commandf("mw.b %lx %x", loadaddr + index, example_c[index]));
+	ut_assert_console_end();
+	ut_asserteq(1, run_command("env import -c ${loadaddr}", 0));
+	ut_assert_nextline("## Error: external checksum format must pass size");
+	ut_assert_console_end();
+
+	/* Binary format with checksum and with wrong size */
+	ut_asserteq(1, run_commandf("env import -c ${loadaddr} %x", offsetof(env_t, data)));
+	ut_assert_nextline("## Error: Invalid size 0x5");
+	ut_assert_console_end();
+
+	return 0;
+}
+NVEDIT_TEST(nvedit_test_import, UTF_CONSOLE);
+#endif
diff --git a/test/cmd_ut.c b/test/cmd_ut.c
index 44e5fdfdaa6..0ab31b400f5 100644
--- a/test/cmd_ut.c
+++ b/test/cmd_ut.c
@@ -67,6 +67,7 @@ SUITE_DECL(log);
 SUITE_DECL(mbr);
 SUITE_DECL(measurement);
 SUITE_DECL(mem);
+SUITE_DECL(nvedit);
 SUITE_DECL(optee);
 SUITE_DECL(pci_mps);
 SUITE_DECL(seama);
@@ -94,6 +95,7 @@ static struct suite suites[] = {
 	SUITE(mbr, "mbr command"),
 	SUITE(measurement, "TPM-based measured boot"),
 	SUITE(mem, "memory-related commands"),
+	SUITE(nvedit, "env command"),
 	SUITE(optee, "OP-TEE"),
 	SUITE(pci_mps, "PCI Express Maximum Payload Size"),
 	SUITE(seama, "seama command parameters loading and decoding"),
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH V3 3/3] cmd: env: select: Add output for available environment targets
  2025-05-09 19:00 [PATCH V3 0/3] cmd: env: select: Add output for available environment targets Christoph Niedermaier
  2025-05-09 19:00 ` [PATCH V3 1/3] cmd: nvedit: Convert the parsing of arguments to getopt() Christoph Niedermaier
  2025-05-09 19:00 ` [PATCH V3 2/3] test: cmd: nvedit: Add basic unit tests Christoph Niedermaier
@ 2025-05-09 19:00 ` Christoph Niedermaier
  2025-05-12  7:37 ` [PATCH V3 0/3] " Andy Shevchenko
  3 siblings, 0 replies; 11+ messages in thread
From: Christoph Niedermaier @ 2025-05-09 19:00 UTC (permalink / raw)
  To: u-boot
  Cc: Christoph Niedermaier, Andy Shevchenko, Christian Marangi,
	Heinrich Schuchardt, Ilias Apalodimas, Jerome Forissier,
	Joe Hershberger, Marek Vasut, Michal Simek, Patrick Delaunay,
	Rasmus Villemoes, Simon Glass, Tom Rini, Venkatesh Yadav Abbarapu

Add parameter "-l" for printing available environment targets. The
active target is marked with an asterisk. This is done by adding
the function env_select_print_list().

If "env select" is called without a target parameter the result is
"Select Environment on <NULL>: driver not found". Replace this not
so useful output by showing the env usage message instead.

Signed-off-by: Christoph Niedermaier <cniedermaier@dh-electronics.com>
---
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Christian Marangi <ansuelsmth@gmail.com>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>
Cc: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Cc: Jerome Forissier <jerome.forissier@linaro.org>
Cc: Joe Hershberger <joe.hershberger@ni.com>
Cc: Marek Vasut <marex@denx.de>
Cc: Michal Simek <michal.simek@amd.com>
Cc: Patrick Delaunay <patrick.delaunay@foss.st.com>
Cc: Rasmus Villemoes <ravi@prevas.dk>
Cc: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>
Cc: Venkatesh Yadav Abbarapu <venkatesh.abbarapu@amd.com>
---
V2: - Showing available environment targets by parameter "-l"
    - Showing env usage message if env select is called without a target
V3: - Convert the parsing of arguments to getopt()
---
 cmd/nvedit.c  | 18 +++++++++++++++++-
 env/env.c     | 16 ++++++++++++++++
 include/env.h |  7 +++++++
 3 files changed, 40 insertions(+), 1 deletion(-)

diff --git a/cmd/nvedit.c b/cmd/nvedit.c
index e5e89b51e0a..10fd93d4a45 100644
--- a/cmd/nvedit.c
+++ b/cmd/nvedit.c
@@ -504,6 +504,22 @@ static int do_env_load(struct cmd_tbl *cmdtp, int flag, int argc,
 static int do_env_select(struct cmd_tbl *cmdtp, int flag, int argc,
 			 char *const argv[])
 {
+	struct getopt_state gs;
+	int opt;
+
+	if (!argv[1])
+		return CMD_RET_USAGE;
+
+	getopt_init_state(&gs);
+	while ((opt = getopt(&gs, argc, argv, "l")) > 0) {
+		switch (opt) {
+		case 'l': /* list */
+			return env_select_print_list() ? 1 : 0;
+		default:
+			return CMD_RET_USAGE;
+		}
+	}
+
 	return env_select(argv[1]) ? 1 : 0;
 }
 #endif
@@ -1180,7 +1196,7 @@ U_BOOT_LONGHELP(env,
 	"env load - load environment\n"
 #endif
 #if defined(CONFIG_CMD_NVEDIT_SELECT)
-	"env select [target] - select environment target\n"
+	"env select [-l] [target] - list/select environment target(s)\n"
 #endif
 #if defined(CONFIG_CMD_NVEDIT_EFI)
 	"env set -e [-nv][-bs][-rt][-at][-a][-i addr:size][-v] name [arg ...]\n"
diff --git a/env/env.c b/env/env.c
index dbaeedc3c3b..f94976d4271 100644
--- a/env/env.c
+++ b/env/env.c
@@ -350,6 +350,22 @@ int env_init(void)
 	return ret;
 }
 
+int env_select_print_list(void)
+{
+	struct env_driver *drv;
+	int prio;
+
+	printf("Available Environment targets:\n");
+	for (prio = 0; (drv = env_driver_lookup(ENVOP_INIT, prio)); prio++) {
+		if (gd->env_load_prio == prio)
+			printf("* ");
+		else
+			printf("  ");
+		printf("%s\n", drv->name);
+	}
+	return 0;
+}
+
 int env_select(const char *name)
 {
 	struct env_driver *drv;
diff --git a/include/env.h b/include/env.h
index 01c3eeae7e2..4553c7bc109 100644
--- a/include/env.h
+++ b/include/env.h
@@ -286,6 +286,13 @@ int env_save(void);
  */
 int env_erase(void);
 
+/**
+ * env_select_print_list() - Print available environment targets
+ *
+ * Return: 0 if OK, -ve on error
+ */
+int env_select_print_list(void);
+
 /**
  * env_select() - Select the environment storage
  *
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH V3 0/3] cmd: env: select: Add output for available environment targets
  2025-05-09 19:00 [PATCH V3 0/3] cmd: env: select: Add output for available environment targets Christoph Niedermaier
                   ` (2 preceding siblings ...)
  2025-05-09 19:00 ` [PATCH V3 3/3] cmd: env: select: Add output for available environment targets Christoph Niedermaier
@ 2025-05-12  7:37 ` Andy Shevchenko
  2025-05-12  8:22   ` Christoph Niedermaier
  3 siblings, 1 reply; 11+ messages in thread
From: Andy Shevchenko @ 2025-05-12  7:37 UTC (permalink / raw)
  To: Christoph Niedermaier
  Cc: u-boot, Christian Marangi, Heinrich Schuchardt, Ilias Apalodimas,
	Jerome Forissier, Joe Hershberger, Marek Vasut, Michal Simek,
	Patrick Delaunay, Rasmus Villemoes, Simon Glass, Tom Rini,
	Venkatesh Yadav Abbarapu

On Fri, May 09, 2025 at 09:00:40PM +0200, Christoph Niedermaier wrote:
> Add the "-l" parameter to the "env select" command to print the available
> environment targets, convert all argument parsing in the file nvedit.c to
> getopt() and check that with unit tests.
> 
> The first patch converts the parsing of arguments to getopt() for all env
> commands. The second one adds unit tests for checking the env command.
> These were used to check the env commands before and after the conversion.
> The third patch adds the actual new parameter "-l" for the "env select"
> command.

What is the binary size increase with this change, please?

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 11+ messages in thread

* RE: [PATCH V3 0/3] cmd: env: select: Add output for available environment targets
  2025-05-12  7:37 ` [PATCH V3 0/3] " Andy Shevchenko
@ 2025-05-12  8:22   ` Christoph Niedermaier
  2025-05-12  8:38     ` Andy Shevchenko
  0 siblings, 1 reply; 11+ messages in thread
From: Christoph Niedermaier @ 2025-05-12  8:22 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: u-boot@lists.denx.de, Christian Marangi, Heinrich Schuchardt,
	Ilias Apalodimas, Jerome Forissier, Joe Hershberger, Marek Vasut,
	Michal Simek, Patrick Delaunay, Rasmus Villemoes, Simon Glass,
	Tom Rini, Venkatesh Yadav Abbarapu

From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Sent: Monday, May 12, 2025 9:38 AM
> On Fri, May 09, 2025 at 09:00:40PM +0200, Christoph Niedermaier wrote:
>> Add the "-l" parameter to the "env select" command to print the available
>> environment targets, convert all argument parsing in the file nvedit.c to
>> getopt() and check that with unit tests.
>>
>> The first patch converts the parsing of arguments to getopt() for all env
>> commands. The second one adds unit tests for checking the env command.
>> These were used to check the env commands before and after the conversion.
>> The third patch adds the actual new parameter "-l" for the "env select"
>> command.
> 
> What is the binary size increase with this change, please?

I don't know exactly which binary size I should look at?
I have looked at the object file of nvedit.c:

I built it with the config dh_imx6_defconfig.

Before my patches:
$ ls -la cmd/nvedit.o 
-rw-r--r-- 1 developer developer 57644 May 12 10:03 cmd/nvedit.o

After my patches:
$ ls -la cmd/nvedit.o 
-rw-r--r-- 1 developer developer 59292 May 12 10:06 cmd/nvedit.o

So the increase is 1648 Bytes (+2.86%).


Regards
Christoph

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH V3 0/3] cmd: env: select: Add output for available environment targets
  2025-05-12  8:22   ` Christoph Niedermaier
@ 2025-05-12  8:38     ` Andy Shevchenko
  2025-05-12 15:15       ` Christoph Niedermaier
  0 siblings, 1 reply; 11+ messages in thread
From: Andy Shevchenko @ 2025-05-12  8:38 UTC (permalink / raw)
  To: Christoph Niedermaier
  Cc: u-boot@lists.denx.de, Christian Marangi, Heinrich Schuchardt,
	Ilias Apalodimas, Jerome Forissier, Joe Hershberger, Marek Vasut,
	Michal Simek, Patrick Delaunay, Rasmus Villemoes, Simon Glass,
	Tom Rini, Venkatesh Yadav Abbarapu

On Mon, May 12, 2025 at 08:22:19AM +0000, Christoph Niedermaier wrote:
> From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> Sent: Monday, May 12, 2025 9:38 AM
> > On Fri, May 09, 2025 at 09:00:40PM +0200, Christoph Niedermaier wrote:
> >> Add the "-l" parameter to the "env select" command to print the available
> >> environment targets, convert all argument parsing in the file nvedit.c to
> >> getopt() and check that with unit tests.
> >>
> >> The first patch converts the parsing of arguments to getopt() for all env
> >> commands. The second one adds unit tests for checking the env command.
> >> These were used to check the env commands before and after the conversion.
> >> The third patch adds the actual new parameter "-l" for the "env select"
> >> command.
> > 
> > What is the binary size increase with this change, please?
> 
> I don't know exactly which binary size I should look at?
> I have looked at the object file of nvedit.c:
> 
> I built it with the config dh_imx6_defconfig.
> 
> Before my patches:
> $ ls -la cmd/nvedit.o 
> -rw-r--r-- 1 developer developer 57644 May 12 10:03 cmd/nvedit.o
> 
> After my patches:
> $ ls -la cmd/nvedit.o 
> -rw-r--r-- 1 developer developer 59292 May 12 10:06 cmd/nvedit.o
> 
> So the increase is 1648 Bytes (+2.86%).

U-Boot binary. And better to use bloat-o-meter script for that, it shows the
breakdown in more precise terms.

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 11+ messages in thread

* RE: [PATCH V3 0/3] cmd: env: select: Add output for available environment targets
  2025-05-12  8:38     ` Andy Shevchenko
@ 2025-05-12 15:15       ` Christoph Niedermaier
  2025-05-12 18:25         ` Andy Shevchenko
  0 siblings, 1 reply; 11+ messages in thread
From: Christoph Niedermaier @ 2025-05-12 15:15 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: u-boot@lists.denx.de, Christian Marangi, Heinrich Schuchardt,
	Ilias Apalodimas, Jerome Forissier, Joe Hershberger, Marek Vasut,
	Michal Simek, Patrick Delaunay, Rasmus Villemoes, Simon Glass,
	Tom Rini, Venkatesh Yadav Abbarapu

From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Sent: Monday, May 12, 2025 10:38 AM
> On Mon, May 12, 2025 at 08:22:19AM +0000, Christoph Niedermaier wrote:
>> From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
>> Sent: Monday, May 12, 2025 9:38 AM
>>> On Fri, May 09, 2025 at 09:00:40PM +0200, Christoph Niedermaier wrote:
>>>> Add the "-l" parameter to the "env select" command to print the available
>>>> environment targets, convert all argument parsing in the file nvedit.c to
>>>> getopt() and check that with unit tests.
>>>>
>>>> The first patch converts the parsing of arguments to getopt() for all env
>>>> commands. The second one adds unit tests for checking the env command.
>>>> These were used to check the env commands before and after the conversion.
>>>> The third patch adds the actual new parameter "-l" for the "env select"
>>>> command.
>>>
>>> What is the binary size increase with this change, please?
>>
>> I don't know exactly which binary size I should look at?
>> I have looked at the object file of nvedit.c:
>>
>> I built it with the config dh_imx6_defconfig.
>>
>> Before my patches:
>> $ ls -la cmd/nvedit.o
>> -rw-r--r-- 1 developer developer 57644 May 12 10:03 cmd/nvedit.o
>>
>> After my patches:
>> $ ls -la cmd/nvedit.o
>> -rw-r--r-- 1 developer developer 59292 May 12 10:06 cmd/nvedit.o
>>
>> So the increase is 1648 Bytes (+2.86%).
> 
> U-Boot binary. And better to use bloat-o-meter script for that, it shows the
> breakdown in more precise terms.

With bloat-o-meter it looks like this (before and after my patches):

./bloat-o-meter -p arm-linux-gnueabihf- u-boot_before u-boot_after
add/remove: 5/1 grow/shrink: 4/2 up/down: 1152/-652 (500)
Function                                     old     new   delta
bdinfo_print_all                               -     404    +404
__getopt.constprop                             -     292    +292
substitute                                     -     156    +156
print_eth                                      -     124    +124
print_bi_dram                                  -      72     +72
do_env_default                               116     152     +36
do_env_import                                424     456     +32
do_env_print                                 740     764     +24
do_env_delete                                 92     104     +12
do_env_export                                336     328      -8
substitute.lto_priv                          156       -    -156
do_bdinfo                                    580      92    -488
Total: Before=501681, After=502181, chg +0.10%


Regards
Christoph

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH V3 0/3] cmd: env: select: Add output for available environment targets
  2025-05-12 15:15       ` Christoph Niedermaier
@ 2025-05-12 18:25         ` Andy Shevchenko
  0 siblings, 0 replies; 11+ messages in thread
From: Andy Shevchenko @ 2025-05-12 18:25 UTC (permalink / raw)
  To: Christoph Niedermaier
  Cc: u-boot@lists.denx.de, Christian Marangi, Heinrich Schuchardt,
	Ilias Apalodimas, Jerome Forissier, Joe Hershberger, Marek Vasut,
	Michal Simek, Patrick Delaunay, Rasmus Villemoes, Simon Glass,
	Tom Rini, Venkatesh Yadav Abbarapu

On Mon, May 12, 2025 at 03:15:06PM +0000, Christoph Niedermaier wrote:
> From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> Sent: Monday, May 12, 2025 10:38 AM
> > On Mon, May 12, 2025 at 08:22:19AM +0000, Christoph Niedermaier wrote:
> >> From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> >> Sent: Monday, May 12, 2025 9:38 AM
> >>> On Fri, May 09, 2025 at 09:00:40PM +0200, Christoph Niedermaier wrote:
> >>>> Add the "-l" parameter to the "env select" command to print the available
> >>>> environment targets, convert all argument parsing in the file nvedit.c to
> >>>> getopt() and check that with unit tests.
> >>>>
> >>>> The first patch converts the parsing of arguments to getopt() for all env
> >>>> commands. The second one adds unit tests for checking the env command.
> >>>> These were used to check the env commands before and after the conversion.
> >>>> The third patch adds the actual new parameter "-l" for the "env select"
> >>>> command.
> >>>
> >>> What is the binary size increase with this change, please?
> >>
> >> I don't know exactly which binary size I should look at?
> >> I have looked at the object file of nvedit.c:
> >>
> >> I built it with the config dh_imx6_defconfig.
> >>
> >> Before my patches:
> >> $ ls -la cmd/nvedit.o
> >> -rw-r--r-- 1 developer developer 57644 May 12 10:03 cmd/nvedit.o
> >>
> >> After my patches:
> >> $ ls -la cmd/nvedit.o
> >> -rw-r--r-- 1 developer developer 59292 May 12 10:06 cmd/nvedit.o
> >>
> >> So the increase is 1648 Bytes (+2.86%).
> > 
> > U-Boot binary. And better to use bloat-o-meter script for that, it shows the
> > breakdown in more precise terms.
> 
> With bloat-o-meter it looks like this (before and after my patches):
> 
> ./bloat-o-meter -p arm-linux-gnueabihf- u-boot_before u-boot_after
> add/remove: 5/1 grow/shrink: 4/2 up/down: 1152/-652 (500)
> Function                                     old     new   delta
> bdinfo_print_all                               -     404    +404
> __getopt.constprop                             -     292    +292
> substitute                                     -     156    +156
> print_eth                                      -     124    +124
> print_bi_dram                                  -      72     +72
> do_env_default                               116     152     +36
> do_env_import                                424     456     +32
> do_env_print                                 740     764     +24
> do_env_delete                                 92     104     +12
> do_env_export                                336     328      -8
> substitute.lto_priv                          156       -    -156
> do_bdinfo                                    580      92    -488
> Total: Before=501681, After=502181, chg +0.10%

Not bad. Thank you for sharing!

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH V3 2/3] test: cmd: nvedit: Add basic unit tests
  2025-05-09 19:00 ` [PATCH V3 2/3] test: cmd: nvedit: Add basic unit tests Christoph Niedermaier
@ 2025-06-03 20:12   ` Tom Rini
  2025-06-06 21:40     ` Christoph Niedermaier
  0 siblings, 1 reply; 11+ messages in thread
From: Tom Rini @ 2025-06-03 20:12 UTC (permalink / raw)
  To: Christoph Niedermaier
  Cc: u-boot, Andy Shevchenko, Christian Marangi, Heinrich Schuchardt,
	Ilias Apalodimas, Jerome Forissier, Joe Hershberger, Marek Vasut,
	Michal Simek, Patrick Delaunay, Rasmus Villemoes, Simon Glass,
	Venkatesh Yadav Abbarapu

[-- Attachment #1: Type: text/plain, Size: 490 bytes --]

On Fri, May 09, 2025 at 09:00:42PM +0200, Christoph Niedermaier wrote:

> Add basic unit tests for argument checking of the env command.
> 
> Signed-off-by: Christoph Niedermaier <cniedermaier@dh-electronics.com>
[snip]
> +	/* Binary format with checksum and with wrong size */
> +	ut_asserteq(1, run_commandf("env import -c ${loadaddr} %x", offsetof(env_t, data)));

This will be "unsigned long int" on 64bit or "unsigned int" on 32bit,
and so we can't use %x here.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

* RE: [PATCH V3 2/3] test: cmd: nvedit: Add basic unit tests
  2025-06-03 20:12   ` Tom Rini
@ 2025-06-06 21:40     ` Christoph Niedermaier
  0 siblings, 0 replies; 11+ messages in thread
From: Christoph Niedermaier @ 2025-06-06 21:40 UTC (permalink / raw)
  To: Tom Rini
  Cc: u-boot@lists.denx.de, Andy Shevchenko, Christian Marangi,
	Heinrich Schuchardt, Ilias Apalodimas, Jerome Forissier,
	Joe Hershberger, Marek Vasut, Michal Simek, Patrick Delaunay,
	Rasmus Villemoes, Simon Glass, Venkatesh Yadav Abbarapu

From: Tom Rini <trini@konsulko.com>
Sent: Tuesday, June 3, 2025 10:13 PM
> On Fri, May 09, 2025 at 09:00:42PM +0200, Christoph Niedermaier wrote:
> 
>> Add basic unit tests for argument checking of the env command.
>>
>> Signed-off-by: Christoph Niedermaier <cniedermaier@dh-electronics.com>
> [snip]
>> +	/* Binary format with checksum and with wrong size */
>> +	ut_asserteq(1, run_commandf("env import -c ${loadaddr} %x", offsetof(env_t, data)));
> 
> This will be "unsigned long int" on 64bit or "unsigned int" on 32bit,
> and so we can't use %x here.

I will have a look at it and make a new version. I may not get round to
it straight away.

Thanks and regards
Christoph

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2025-06-06 21:47 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-05-09 19:00 [PATCH V3 0/3] cmd: env: select: Add output for available environment targets Christoph Niedermaier
2025-05-09 19:00 ` [PATCH V3 1/3] cmd: nvedit: Convert the parsing of arguments to getopt() Christoph Niedermaier
2025-05-09 19:00 ` [PATCH V3 2/3] test: cmd: nvedit: Add basic unit tests Christoph Niedermaier
2025-06-03 20:12   ` Tom Rini
2025-06-06 21:40     ` Christoph Niedermaier
2025-05-09 19:00 ` [PATCH V3 3/3] cmd: env: select: Add output for available environment targets Christoph Niedermaier
2025-05-12  7:37 ` [PATCH V3 0/3] " Andy Shevchenko
2025-05-12  8:22   ` Christoph Niedermaier
2025-05-12  8:38     ` Andy Shevchenko
2025-05-12 15:15       ` Christoph Niedermaier
2025-05-12 18:25         ` Andy Shevchenko

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.