Building an unsigned imx-boot for the IOT-DIN-IMX8PLUS

The first real build: a completely unsigned bootloader, on purpose, so that any problem is a build problem and not a signing problem. Two errors on the way, one of which is caused by a modern setuptools removing pkg_resources.

Sources pinned, keys generated, backups verified. Now an actual build — unsigned, on purpose. If signing goes in at the same time as the first build, every failure afterwards is ambiguous, and you spend your time deciding which half broke.

A nice surprise: ATF did not need building

I had budgeted time for compiling ARM Trusted Firmware separately. It turned out not to be necessary — the prebuilt binary matching the pinned commit was available, so the assembly step had one fewer moving part than the plan assumed.

Worth checking before you build something you do not have to.

Configure and build

export CROSS_COMPILE=aarch64-linux-gnu-
export ARCH=arm64
make iotdin-imx8p_defconfig
make -j24

defconfig is ordinary Kconfig vocabulary, not something specific to this board: it seeds .config from a named preset. Take CompuLab's authoritative one and add to it, as part 5 argues.

Configuring went fine. The build failed twice.

Error one: swig

swig: command not found

swig generates bindings between C and other languages. U-Boot needs it here to build the Python bindings for libfdt, the flattened-device-tree library that binman uses to assemble the final image.

The fix was less interesting than the lesson: the repository already had a .venv/ at its root with a working swig in .venv/bin/, put there weeks earlier for exactly this kind of project-local tooling and then forgotten. It just was not on PATH for this shell.

export PATH="$PWD/.venv/bin:$PATH"

Check what your project already provides before installing anything. I nearly apt installed a second copy of a tool I already had.

Error two: pkg_resources, and why installing the newest version makes it worse

ModuleNotFoundError: No module named 'pkg_resources'

This one is a genuine rabbit hole, and the obvious fix is the wrong one.

pkg_resources is provided by setuptools. So the instinct is to install the newest setuptools — and that does not fix it, because recent releases removed pkg_resources deliberately, as the end of a long-flagged deprecation.

U-Boot's build tooling still expects the old-style module. So the real fix is to pin an older — but still perfectly current — setuptools into the same virtual environment, rather than grabbing the newest one blindly:

.venv/bin/pip install 'setuptools<81'

The general shape is worth remembering, because it is not rare: when a missing module is provided by a package you already have at its newest version, check whether the module was removed rather than assuming your install is broken. Upgrading is the reflex, and here upgrading is what caused it.

And then it worked

LD spl/u-boot-spl
OBJCOPY spl/u-boot-spl-nodtb.bin
SYM spl/u-boot-spl.sym
CAT spl/u-boot-spl-dtb.bin
COPY spl/u-boot-spl.bin
BINMAN .binman_stamp
OFCHK .config

Exit code zero, and a real flash.bin a little over 2 MB.

Two things worth doing immediately, both cheap:

make -j24 # run it again — should report nothing to do, instantly
sha256sum flash.bin # record it

A second build that finishes instantly with nothing to do is what a genuinely complete build looks like. One that redoes work quietly did not finish the first time. And recording the hash means that months later you can tell whether the file in front of you is the one you think it is — which matters more than it sounds, as part 7 demonstrates when I nearly flashed a backup belonging to a different device.

Building is one claim. Booting is a different one.

A clean build proves the toolchain agreed with itself. It proves nothing about the board.

Before going to the bench, one piece of vocabulary that has cost me real time on this project, and which matters more here than anywhere else:

[DBG] micro-USB, front → serial console. Safe to leave connected. Always.
[OTG] micro-USB, bottom → programming port: SDP recovery, ums, fastboot.

Never have the OTG cable connected to a powered-on computer when the board powers up. The boot ROM checks for a waiting USB host before it does anything else, and if it finds one it jumps straight into serial-download recovery mode instead of booting what you just flashed.

You then sit watching a console that prints nothing, concluding your build is broken, when the chip is simply waiting for you to push it an image. Plug in DBG, power on, then connect OTG if you need it.

Next: I flashed it, and the board stopped booting — for a reason that had nothing to do with this build, and everything to do with a Kconfig default.