[PATCH] tools: binman: add build key directory option

James Hilliard james.hilliard1 at gmail.com
Mon Jul 6 21:43:10 CEST 2026


On Mon, Jul 6, 2026 at 2:51 AM Quentin Schulz <quentin.schulz at cherry.de> wrote:
>
> Hi James,
>
> On 7/3/26 11:33 PM, James Hilliard wrote:
> > U-Boot's Makefile passes KEYDIR to direct mkimage invocations, but
> > internal binman builds only received the generic BINMAN_INDIRS search
> > path. FIT entries with fit,sign or fit,encrypt therefore had to infer
> > the key directory from include directories before invoking mkimage -k.
> >
>
> You don't explain why that is an issue? Simply add KEYDIR to BINMAN_INDIRS?

I think for consistency it's better to separate KEYDIR since adding
KEYDIR to BINMAN_INDIRS doesn't actually mean KEYDIR will
be the KEYDIR that gets passed to mkimage due to BINMAN_INDIRS
only acting as a searchpath for keys.

IMO if KEYDIR has been explicitly passed then no other directories
should be searched for keys.

>
> > Add a binman build -k/--keydir option and pass KEYDIR through with
> > that option from the top-level Makefile. FIT entries prefer this key
> > directory over include-dir discovery and then pass it to mkimage -k.
> >
> > Signed-off-by: James Hilliard <james.hilliard1 at gmail.com>
> > ---
> >   Makefile                  |  1 +
> >   tools/binman/binman.rst   | 10 +++++++-
> >   tools/binman/cmdline.py   |  2 ++
> >   tools/binman/control.py   |  1 +
> >   tools/binman/etype/fit.py | 24 +++++++++++-------
> >   tools/binman/ftest.py     | 51 ++++++++++++++++++++++++++++++++++++---
> >   tools/binman/state.py     | 21 ++++++++++++++++
> >   7 files changed, 97 insertions(+), 13 deletions(-)
> >
> > diff --git a/Makefile b/Makefile
> > index d8287323c43..27be2a81e83 100644
> > --- a/Makefile
> > +++ b/Makefile
> > @@ -1689,6 +1689,7 @@ cmd_binman = $(srctree)/tools/binman/binman $(if $(BINMAN_DEBUG),-D) \
> >               -I . -I $(srctree)/board/$(BOARDDIR) -I $(srctree) \
> >               $(foreach f,$(of_list_dirs),-I $(f)) -a of-list=$(of_list) \
> >               $(foreach f,$(BINMAN_INDIRS),-I $(f)) \
> > +             $(if $(KEYDIR),-k $(KEYDIR)) \
> >               -a atf-bl1-path=${BL1} \
> >               -a atf-bl31-path=${BL31} \
> >               -a tee-os-path=${TEE} \
> > diff --git a/tools/binman/binman.rst b/tools/binman/binman.rst
> > index 366491089ad..8770b279ff8 100644
> > --- a/tools/binman/binman.rst
> > +++ b/tools/binman/binman.rst
> > @@ -1711,7 +1711,7 @@ Usage::
> >
> >       binman build [-h] [-a ENTRY_ARG] [-b BOARD] [-d DT] [--fake-dtb]
> >           [--fake-ext-blobs] [--force-missing-bintools FORCE_MISSING_BINTOOLS]
> > -        [-i IMAGE] [-I INDIR] [-m] [-M] [-n] [-O OUTDIR] [-p] [-u]
> > +        [-i IMAGE] [-I INDIR] [-k KEYDIR] [-m] [-M] [-n] [-O OUTDIR] [-p] [-u]
> >           [--update-fdt-in-elf UPDATE_FDT_IN_ELF] [-W]
> >
> >   Options:
> > @@ -1738,6 +1738,9 @@ Options:
> >       Add a path to the list of directories to use for input files. This can be
> >       specified multiple times to add more than one path.
> >
> > +-k KEYDIR, --keydir KEYDIR
> > +    Directory containing keys for signing/encryption.
> > +
> >   -m, --map
> >       Output a map file for each image. See `Map files`_.
> >
> > @@ -2161,6 +2164,11 @@ BINMAN_INDIRS
> >       Sets the search path for input files used by binman by adding one or more
> >       `-I` arguments. See :ref:`External blobs`.
> >
> > +KEYDIR
> > +    Sets the key directory passed to FIT entries by adding a `-k` argument.
> > +    FIT entries use this directory for mkimage's `-k` argument when `fit,sign`
> > +    or `fit,encrypt` is enabled.
> > +
> >   BINMAN_TOOLPATHS
> >       Sets the search path for external tool used by binman by adding one or more
> >       `--toolpath` arguments. See :ref:`External tools`.
> > diff --git a/tools/binman/cmdline.py b/tools/binman/cmdline.py
> > index 9632ec115e5..cd4d05dfb69 100644
> > --- a/tools/binman/cmdline.py
> > +++ b/tools/binman/cmdline.py
> > @@ -128,6 +128,8 @@ controlled by a description in the board device tree.'''
> >               help='Image filename to build (if not specified, build all)')
> >       build_parser.add_argument('-I', '--indir', action='append',
> >               help='Add a path to the list of directories to use for input files')
> > +    build_parser.add_argument('-k', '--keydir', type=str,
> > +            help='Directory containing keys for signing/encryption')
> >       build_parser.add_argument('-m', '--map', action='store_true',
> >           default=False, help='Output a map file for each image')
> >       build_parser.add_argument('-M', '--allow-missing', action='store_true',
> > diff --git a/tools/binman/control.py b/tools/binman/control.py
> > index 816f7c1eba2..84586d1baf1 100644
> > --- a/tools/binman/control.py
> > +++ b/tools/binman/control.py
> > @@ -923,6 +923,7 @@ def Binman(args):
> >               tools.set_input_dirs(args.indir)
> >               tools.prepare_output_dir(args.outdir, args.preserve)
> >               state.SetEntryArgs(args.entry_arg)
> > +            state.SetKeydir(args.keydir)
> >               state.SetThreads(args.threads)
> >
> >               images = PrepareImagesAndDtbs(dtb_fname, args.image,
> > diff --git a/tools/binman/etype/fit.py b/tools/binman/etype/fit.py
> > index f28b1e6b4cb..404e33d3022 100644
> > --- a/tools/binman/etype/fit.py
> > +++ b/tools/binman/etype/fit.py
> > @@ -14,6 +14,7 @@ import os
> >   from binman.entry import Entry, EntryArg
> >   from binman.etype.section import Entry_section
> >   from binman import elf
> > +from binman import state
> >   from dtoc import fdt_util
> >   from dtoc.fdt import Fdt
> >   from u_boot_pylib import tools
> > @@ -105,18 +106,20 @@ class Entry_fit(Entry_section):
> >           fit,sign
> >               Enable signing FIT images via mkimage as described in
> >               verified-boot.rst.
> > -            If the property is found and fit,engine is not set, the private
> > -            keys path is detected among binman include directories and passed to
> > -            mkimage via -k flag. All the keys required for signing FIT must be
> > -            available at time of signing and must be located in single include
> > -            directory.
> > +            If the property is found and fit,engine is not set, the key
> > +            directory passed with binman build -k is passed to mkimage via the
> > +            -k flag. If no key directory is provided, the private keys path is
> > +            detected among binman include directories. All the keys required for
> > +            signing FIT must be available at time of signing and must be
> > +            located in a single directory.
> >
> >           fit,encrypt
> >               Enable data encryption in FIT images via mkimage. If the property
> > -            is found, the keys path is detected among binman include
> > -            directories and passed to mkimage via  -k flag. All the keys
> > +            is found, the key directory passed with binman build -k is passed
> > +            to mkimage via the -k flag. If no key directory is provided, the
> > +            keys path is detected among binman include directories. All the keys
> >               required for encrypting the FIT must be available at the time of
> > -            encrypting and must be located in a single include directory.
> > +            encrypting and must be located in a single directory.
> >
> >               Incompatible with fit,engine.
> >
> > @@ -485,6 +488,8 @@ class Entry_fit(Entry_section):
> >                   includes 'generator' entries which are used to create the FIT,
> >                   but should not be processed as real entries. This is set up once
> >                   we have the entries
> > +            _keydir (str): Key directory from the binman build -k option, if
> > +                provided
> >               _loadables (list of str): List of generated split-elf nodes, each
> >                   a node name
> >               _remove_props (list of str): Value of of-spl-remove-props EntryArg,
> > @@ -500,6 +505,7 @@ class Entry_fit(Entry_section):
> >           self._fit_list_prop = None
> >           self._fit_default_dt = None
> >           self._priv_entries = {}
> > +        self._keydir = state.GetKeydir()
> >           self._loadables = []
> >           self._remove_props = []
> >           props = self.GetEntryArgsOrProps(
> > @@ -701,7 +707,7 @@ class Entry_fit(Entry_section):
> >               args.update({'engine': engine})
> >               # If no engine, keys must exist locally, find them
> >               if engine is None:
> > -                keydir = self._get_keys_dir(data)
> > +                keydir = self._keydir or self._get_keys_dir(data)
>
> Then we don't even check if the keys exist in _keydir anymore.

That was intentional since keydir here is designed to explicitly override
any directory autodetection logic. Missing keys will still result in errors
when mkimage is invoked which I think should be sufficient.

>
> Cheers,
> Quentin


More information about the U-Boot mailing list