[RFC PATCH 00/11] Tidy command option parsing and use it a bit

Simon Glass sjg at chromium.org
Fri May 15 22:32:51 CEST 2026


We have had getopt() for over five years but it is not much used. It is
much easier to understand arg-parsing using getopt() and it avoids
common errors. As the named maintainer I decided to look at how to make
more use of it.

So this series explores the impact of converting a few commands to use
getopt() instead of ad-hoc parsing. It updates getopt() to handle flags
anywhere in the cmdline and provides a few helpers to reduce
boilerplate.

The chosen commands are:

- echo: very simple with no flags
- hash: fairly simple with just one flag
- env grep/export/import - fuller examples

The series also adds a recommendation to use getopt() for new commands.

To try to reduce the code-size increase, a lower-case function is added
and called from a few places. The difference is fairly marginal.

Overall, the result is not pretty (see below) with about a 1.1K size
increase on arm64:

   01: Prepare v2026.07-rc2
      aarch64:  w+   firefly-rk3399
   02: lib: string: Add strlower()
      aarch64: (for 1/1 boards) all +40.0 rodata +40.0 spl/u-boot-spl:all
         +20.0 spl/u-boot-spl:rodata +20.0 tpl/u-boot-tpl:all +20.0
         tpl/u-boot-tpl:rodata +20.0
   03: cmd: ini: Use strlower() to normalise case
   04: fs: fat: Use strlower() to normalise case
      aarch64: (for 1/1 boards) all -24.0 text -24.0
   05: boot: pxe_utils: Use strlower() in get_string()
      aarch64: (for 1/1 boards) all -56.0 text -56.0
   06: doc: commands: Recommend getopt() for option parsing
   07: lib: getopt: Permute by default with inline reorder
   08: lib: getopt: Add getopt_pop() helper
   09: cmd: echo: Use getopt() with '+' prefix for option parsing
      aarch64: (for 1/1 boards) all +1235.0 rodata +175.0 text +1060.0
   10: cmd: hash: Use getopt() for option parsing
   11: cmd: nvedit: Use getopt() in env grep
   12: cmd: nvedit: Use getopt() in env export and env import
      aarch64: (for 1/1 boards) all +176.0 rodata +12.0 text +164.0

Ideally we would use getopt() everywhere, but at least with these
examples it does seem to produce at least a small increase in each case,
even ignoring the 'hit' of about 1K for the function itself.

One option would be to make the getopt_init_state() in command.c and
pass struct getopt_state to the commands. This would reduce code size at
each size, but obviously requires a different command signature, unless
a global is used.

Another small improvement could be to include a getopt function to
return the next arg as hex.

Ideas are welcome!


Simon Glass (11):
  lib: string: Add strlower()
  cmd: ini: Use strlower() to normalise case
  fs: fat: Use strlower() to normalise case
  boot: pxe_utils: Use strlower() in get_string()
  lib: getopt: Permute by default with inline reorder
  lib: getopt: Add getopt_pop() helper
  cmd: echo: Use getopt() with '+' prefix for option parsing
  cmd: hash: Use getopt() for option parsing
  cmd: nvedit: Use getopt() in env grep
  cmd: nvedit: Use getopt() in env export and env import
  doc: commands: Recommend getopt() for option parsing

 boot/pxe_utils.c         |  12 +--
 cmd/Kconfig              |   5 +
 cmd/bdinfo.c             |   4 +-
 cmd/echo.c               |  23 ++--
 cmd/hash.c               |  37 ++++---
 cmd/ini.c                |  21 ++--
 cmd/log.c                |  12 +--
 cmd/nvedit.c             | 219 +++++++++++++++++++--------------------
 doc/develop/commands.rst |  62 +++++++++++
 fs/fat/fat.c             |  20 +---
 fs/fat/fat_write.c       |   2 +-
 include/getopt.h         | 169 +++++++++++++++++-------------
 include/linux/string.h   |  12 +++
 lib/getopt.c             |  67 +++++++++---
 lib/string.c             |  10 ++
 test/cmd/test_echo.c     |  10 ++
 test/lib/getopt.c        |   6 +-
 test/lib/string.c        |  27 +++++
 18 files changed, 441 insertions(+), 277 deletions(-)

---
base-commit: 215496fec59b3fa09256b4fb62f92af46e2ec7f9
branch: clid

-- 
2.43.0



More information about the U-Boot mailing list