This is the other gnarly hand-rolled parser in nvedit.c The code walks each -prefixed argv element by hand, opens an inner while (*++arg) to split grouped flags, and tracks a fmt counter to catch a second -b / -c / -t
getopt() collapses all of that. The mutex check for the format flags is done after the option loop (it is a per-command rule, not an option-parsing rule) and the trailing positional list is read from argv + gs.index. Adjust CMD_IMPORTENV to select GETOPT so the parser is linked in on boards that did not already enable it. Also redo the sep_err logic and error message, along with a fmt tweak to reduce code size. Signed-off-by: Simon Glass <[email protected]> --- cmd/Kconfig | 1 + cmd/nvedit.c | 95 ++++++++++++++++++++++++---------------------------- env/common.c | 2 +- 3 files changed, 46 insertions(+), 52 deletions(-) diff --git a/cmd/Kconfig b/cmd/Kconfig index a5a20bde4b5..72ff4dbfe60 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -711,6 +711,7 @@ config CMD_EXPORTENV config CMD_IMPORTENV bool "env import" default y + select GETOPT help Import environments. diff --git a/cmd/nvedit.c b/cmd/nvedit.c index 5dca1b804fd..ce1f0e9bd2c 100644 --- a/cmd/nvedit.c +++ b/cmd/nvedit.c @@ -752,64 +752,64 @@ static int do_env_export(struct cmd_tbl *cmdtp, int flag, static int do_env_import(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { + struct getopt_state gs; ulong addr; - char *cmd, *ptr; + char *ptr, *tok; char sep = '\n'; int chk = 0; int fmt = 0; int del = 0; int crlf_is_lf = 0; - int wl = 0; + int wl; size_t size; + int opt; - 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; - } + getopt_init_state(&gs); + while ((opt = getopt(&gs, argc, argv, "bctrd")) > 0) { + fmt++; + switch (opt) { + case 'b': /* raw binary format */ + sep = '\0'; + break; + case 'c': /* external checksum format */ + sep = '\0'; + chk = 1; + break; + case 't': /* text format (default) */ + break; + case 'r': /* handle CRLF like LF */ + crlf_is_lf = 1; + fmt--; + break; + case 'd': + del = 1; + fmt--; + break; + default: + return CMD_RET_USAGE; } } - if (argc < 1) + if (gs.index >= argc) + return CMD_RET_USAGE; + if (fmt > 1) { + printf("## Error: %s: only one of -b/c/t allowed\n", argv[0]); + return CMD_RET_USAGE; + } if (!fmt) printf("## Warning: defaulting to text format\n"); - if (sep != '\n' && crlf_is_lf ) + 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); + tok = gs.index < argc ? argv[gs.index++] : NULL; + if (tok && strcmp(tok, "-")) { + size = hextoul(tok, NULL); } else if (chk) { puts("## Error: external checksum format must pass size\n"); return CMD_RET_FAILURE; @@ -825,22 +825,19 @@ static int do_env_import(struct cmd_tbl *cmdtp, int flag, ++size; } if (size == MAX_ENV_SIZE) { - printf("## Warning: Input data exceeds %d bytes" + printf("## Warning: Input exceeds %d bytes" " - truncated\n", MAX_ENV_SIZE); } size += 2; - printf("## Info: input data size = %zu = 0x%zX\n", size, size); + printf("## Info: input size = %zu = %#zX\n", size, size); } - if (argc > 2) - wl = 1; - if (chk) { uint32_t crc; env_t *ep = (env_t *)ptr; if (size <= offsetof(env_t, data)) { - printf("## Error: Invalid size 0x%zX\n", size); + printf("## Error: Invalid size %#zX\n", size); return 1; } @@ -854,20 +851,16 @@ static int do_env_import(struct cmd_tbl *cmdtp, int flag, ptr = (char *)ep->data; } + wl = argc - 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)) { - pr_err("## Error: Environment import failed: errno = %d\n", + crlf_is_lf, wl, wl ? &argv[gs.index] : NULL)) { + pr_err("## Error: Environment import failed (err %dE)\n", errno); return 1; } gd->flags |= GD_FLG_ENV_READY; return 0; - -sep_err: - printf("## %s: only one of \"-b\", \"-c\" or \"-t\" allowed\n", - cmd); - return 1; } #endif diff --git a/env/common.c b/env/common.c index b2adbe93dbe..986400f912f 100644 --- a/env/common.c +++ b/env/common.c @@ -402,7 +402,7 @@ void env_set_default(const char *s, int flags) if (himport_r(&env_htab, default_environment, sizeof(default_environment), '\0', flags, 0, 0, NULL) == 0) { - pr_err("## Error: Environment import failed: errno = %d\n", + pr_err("## Error: Environment import failed (err %dE)\n", errno); return; } -- 2.43.0

