[PATCH v4 10/14] cmd: nvedit: Use getopt() in env export
Simon Glass
sjg at chromium.org
Wed Jul 1 13:42:30 CEST 2026
do_env_export() is one of the gnarliest hand-rolled parsers in the env
code. It walks each - argument by hand, opens an inner while (*++arg)
to split grouped flags, tracks an fmt counter to reject a second
-b/-c/-t and uses a goto NXTARG to skip the rest of the current element
after -s has eaten the following argument for its size.
Replace all of that with getopt(). Move do_env_export() to the
getopt-state command signature, declared with U_BOOT_CMD_MKENT_GETOPT().
The -s argument arrives in gs->arg. Move the format-flag
mutual-exclusion check after the option loop (it is a per-command rule,
not an option-parsing rule) and read the trailing positional list from
gs->argv[gs->index]. Keep the + prefix on the optstring so getopt()
stops at the first non-option, exactly as the hand-rolled loop did.
While here, write the text-format filesize with env_set_hex() rather
than an open-coded sprintf() into a stack buffer. This drops the buffer
and matches the binary path, which already uses env_set_hex(); the only
visible change is that the value is now lower-case hex (its consumers
read it with hextoul(), which is case-insensitive). Check the return
value of both env_set_hex() calls and return 1 on failure, rather than
ignoring it.
Route the env subcommand dispatch in do_env() through cmd_invoke() so
subcommands using either signature are called correctly.
CMD_EXPORTENV selects GETOPT so the parser is linked in on boards that
do not already enable it.
Also redo the sep_err logic, use env_set_hex() and shorten error
messages to reduce code size.
Signed-off-by: Simon Glass <sjg at chromium.org>
---
(no changes since v2)
Changes in v2:
- Redo the sep_err logic to reduce code size
cmd/Kconfig | 1 +
cmd/nvedit.c | 80 +++++++++++++++++++++++++---------------------------
2 files changed, 39 insertions(+), 42 deletions(-)
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 3c5abddd31f..e3d92055f17 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -704,6 +704,7 @@ config CMD_ASKENV
config CMD_EXPORTENV
bool "env export"
default y
+ select GETOPT
help
Export environments.
diff --git a/cmd/nvedit.c b/cmd/nvedit.c
index 636bddee1be..c74898a05fb 100644
--- a/cmd/nvedit.c
+++ b/cmd/nvedit.c
@@ -29,6 +29,7 @@
#include <console.h>
#include <env.h>
#include <env_internal.h>
+#include <getopt.h>
#include <log.h>
#include <search.h>
#include <errno.h>
@@ -631,10 +632,8 @@ static int do_env_delete(struct cmd_tbl *cmdtp, int flag,
*
* => env import -d -t ${backup_addr}
*/
-static int do_env_export(struct cmd_tbl *cmdtp, int flag,
- int argc, char *const argv[])
+static int do_env_export(struct getopt_state *gs)
{
- char buf[32];
ulong addr;
char *ptr, *cmd, *res;
size_t size = 0;
@@ -643,52 +642,48 @@ static int do_env_export(struct cmd_tbl *cmdtp, int flag,
char sep = '\n';
int chk = 0;
int fmt = 0;
+ int argc;
+ char *const *argv;
+ int opt;
- cmd = *argv;
+ cmd = gs->argv[0];
- 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;
- }
+ while ((opt = getopt(gs, "+bcs:t")) > 0) {
+ switch (opt) {
+ case 'b': /* raw binary format */
+ sep = '\0';
+ fmt++;
+ break;
+ case 'c': /* external checksum format */
+ sep = '\0';
+ chk = 1;
+ fmt++;
+ break;
+ case 's': /* size given */
+ size = hextoul(gs->arg, NULL);
+ break;
+ case 't': /* text format */
+ sep = '\n';
+ fmt++;
+ break;
+ default:
+ return CMD_RET_USAGE;
}
-NXTARG: ;
}
+ if (fmt > 1)
+ goto sep_err;
- if (argc < 1)
+ if (gs->index >= gs->argc)
return CMD_RET_USAGE;
- addr = hextoul(argv[0], NULL);
+ addr = hextoul(getopt_pop(gs), NULL);
ptr = map_sysmem(addr, size);
if (size)
memset(ptr, '\0', size);
- argc--;
- argv++;
+ argc = gs->argc - gs->index;
+ argv = &gs->argv[gs->index];
if (sep) { /* export as text file */
len = hexport_r(&env_htab, sep,
@@ -699,8 +694,8 @@ NXTARG: ;
errno);
return 1;
}
- sprintf(buf, "%zX", (size_t)len);
- env_set("filesize", buf);
+ if (env_set_hex("filesize", len))
+ return 1;
return 0;
}
@@ -728,7 +723,8 @@ NXTARG: ;
envp->flags = ENV_REDUND_ACTIVE;
#endif
}
- env_set_hex("filesize", len + offsetof(env_t, data));
+ if (env_set_hex("filesize", len + offsetof(env_t, data)))
+ return 1;
return 0;
@@ -1077,7 +1073,7 @@ static struct cmd_tbl cmd_env_sub[] = {
U_BOOT_CMD_MKENT(flags, 1, 0, do_env_flags, "", ""),
#endif
#if defined(CONFIG_CMD_EXPORTENV)
- U_BOOT_CMD_MKENT(export, 4, 0, do_env_export, "", ""),
+ U_BOOT_CMD_MKENT_GETOPT(export, 4, 0, do_env_export, "", ""),
#endif
#if defined(CONFIG_CMD_GREPENV)
U_BOOT_CMD_MKENT(grep, CONFIG_SYS_MAXARGS, 1, do_env_grep, "", ""),
@@ -1127,7 +1123,7 @@ static int do_env(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
cp = find_cmd_tbl(argv[0], cmd_env_sub, ARRAY_SIZE(cmd_env_sub));
if (cp)
- return cp->cmd(cmdtp, flag, argc, argv);
+ return cmd_invoke(cp, flag, argc, argv);
return CMD_RET_USAGE;
}
--
2.43.0
More information about the U-Boot
mailing list