[PATCH v4 00/14] cmd: Convert command option parsing to getopt()

Simon Glass sjg at chromium.org
Wed Jul 1 13:42:20 CEST 2026


Most U-Boot commands open-code their option parsing, scanning argv[] for
"-x" strings by hand. That only recognises options in fixed positions
(so e.g. 'echo foo -n' misbehaves) and duplicates the same code in
every command.

This series introduces a getopt-based command signature: a command
marked CMDF_GETOPT receives a single 'struct getopt_state *' and parses
options with getopt(), while commands without the flag keep the classic
(cmdtp, flag, argc, argv) signature, so commands move over one at a
time.

It starts with the getopt groundwork - optional argv permutation, a
getopt_pop() helper, dropping the printed error messages and the silent
variant - then adds the U_BOOT_CMD_GETOPT() signature support and a
strlower() helper, and converts the first commands: hash, env
export/import/grep, fastboot and echo.

The signature change itself is code-size-neutral; commands parse in
POSIX mode (a '+' optstring prefix), so CONFIG_GETOPT_PERMUTE - which
would make every getopt command carry a writable argv copy - stays off
by default and is kept only as an opt-in.

The earlier RFCs grew arm64 by about 1.1K, not ideal for a series that
mainly benefits readability. To fix that, this series also restructures
struct cmd_tbl so that adding getopt() support does not cost size: the
rarely-useful ->cmd_rep function pointer is replaced by a
CMDF_REPEATABLE flag, dropping a pointer from every command entry.

Because that pointer is removed from every command on every board, the
net result is now a size reduction. On qcom (arm64, ~120 commands) the
whole series is about 6.9K smaller than mainline.

Previous attempts:
v3 just had a simple convert for env input/export
   https://lore.kernel.org/u-boot/20260520201218.3752042-1-sjg@chromium.org/

v2 included the full series
   https://lore.kernel.org/u-boot/20260520000630.GJ1858239@bill-the-cat/

v1 started the effort
   https://lore.kernel.org/u-boot/CAFLszTiSxcKyD1MWP+2p2zBbDzLoC5Z=wnxVNHO31DGQHCrLcA@mail.gmail.com/

Changes in v4:
- Add a Kconfig to control permuting
- Reword the commit message a little
- Fix the getopt_silent() kernel-doc and the bdinfo help test
- Add new patch to narrow maxargs to a short, freeing space in
  struct cmd_tbl for the flags byte
- Guard cmd_invoke() with CONFIG_IS_ENABLED(GETOPT) so boards without
  GETOPT still link
- Add new patch to replace the ->cmd_rep pointer with a
  CMDF_REPEATABLE flag, dropping a pointer from every command entry
- Make hash parse in POSIX mode so nothing selects GETOPT_PERMUTE
- Update commit message to mention himport_r()
- Add new patch to convert fastboot
- Rebased on us/next

Changes in v2:
- Use "permute" terminology in docs and comments
- Move the working argv array to the top of struct getopt_state and
  rename it from @args to @argv (drops inter-field padding too)
- Refine kerneldoc for @index
- Restore the original worked example in getopt()'s kerneldoc
- Add tests for permuted argv, a required argument missing after a
  leading non-option, and the '+' prefix
- Redo the sep_err logic to reduce code size

Simon Glass (14):
  lib: getopt: Add optional argv permutation with inline reorder
  lib: getopt: Add getopt_pop() helper
  lib: getopt: Drop printed error messages and the silent variant
  command: Narrow cmd_tbl.maxargs to a short
  command: Support a getopt-based command signature
  command: Replace the cmd_rep pointer with a CMDF_REPEATABLE flag
  hash: Drop unused cmdtp and flag args from hash_command()
  lib: string: Add strlower()
  cmd: hash: Use getopt() for option parsing
  cmd: nvedit: Use getopt() in env export
  cmd: nvedit: Use getopt() in env import
  cmd: nvedit: Use getopt() in env grep
  cmd: fastboot: Use getopt() for option parsing
  cmd: echo: Use getopt() for option parsing

 cmd/Kconfig            |   6 ++
 cmd/bdinfo.c           |   4 +-
 cmd/echo.c             |  26 ++---
 cmd/fastboot.c         |  48 +++++-----
 cmd/hash.c             |  42 +++++----
 cmd/help.c             |   2 +-
 cmd/log.c              |  12 +--
 cmd/md5sum.c           |   2 +-
 cmd/mem.c              |   2 +-
 cmd/nvedit.c           | 210 ++++++++++++++++++++---------------------
 cmd/sha1sum.c          |   2 +-
 cmd/sm3sum.c           |   2 +-
 cmd/sound.c            |   4 +-
 cmd/test.c             |   2 +-
 cmd/x86/zboot.c        |   2 +-
 common/command.c       |  46 ++++-----
 common/hash.c          |   4 +-
 include/command.h      | 167 +++++++++++++++++++++++---------
 include/getopt.h       | 116 ++++++++++++++++-------
 include/hash.h         |   6 +-
 include/linux/string.h |  12 +++
 lib/Kconfig            |  17 ++++
 lib/getopt.c           |  93 ++++++++++++++----
 lib/string.c           |  10 ++
 test/cmd/bdinfo.c      |   1 -
 test/cmd/test_echo.c   |   7 ++
 test/lib/getopt.c      |  54 ++++++++++-
 test/lib/string.c      |  27 ++++++
 28 files changed, 614 insertions(+), 312 deletions(-)

---
base-commit: 5602e89a834ccbedc686053b14206c062a144107
branch: clid-us4

-- 
2.43.0



More information about the U-Boot mailing list