Signing the kernel, clean on the first try
The bootloader half of this is done and proven. This post covers the other half — the kernel itself — and something that genuinely surprised me a little: it…
The bootloader half of this is done and proven. This post covers the other half — the kernel itself — and something that genuinely surprised me a little: it worked cleanly the very first time, which is not how the equivalent step went in series one at all.
A real difference this build has, found by checking rather than assuming
Series one had to physically pull the running kernel off the lab unit's storage before it could sign it, because it was working with the actual, already-deployed file. This build is different in a nice way: the kernel is something the production toolchain compiles fresh from source as part of the normal firmware build, so it was already sitting right there, finished, the moment that build completed. No extra extraction step needed.
One real number did need double-checking rather than reusing from series one, though: the exact memory address this kernel expects to be loaded at. I read it straight out of this build's own environment configuration rather than assuming it matched the lab unit's — and it didn't. Different build, genuinely different address. A small thing, but exactly the kind of detail this whole project has trained me to check rather than guess.
The padding, and a familiar-shaped gap
Same process as series one: read the real kernel file's own declared size out of its header, compare that against the actual file size on disk, pad the difference. The gap this time was a different number than series one's own kernel had, but the same kind of gap — a real several-hundred-kilobyte difference between what the file claims and what's actually there, so the padding step was doing genuine work again, not just going through motions.
Applying the lesson instead of relearning it
This is the part I actually want to write about. Series one's kernel signing hit a real, confusing failure on its first attempt — the chip rejected it outright, and figuring out why took real digging through the failure's own raw output before finding the actual cause: the signed region needs to cover a little more than it looks like it should, reaching through one extra small structure appended right at the end, not stopping right before it.
This time, I built that fix into the signing instructions from the very start, instead of writing it the "obvious" way and finding out the hard way again. And it worked: a completely clean signature on the first real attempt, no failure, no debugging detour.
That's a genuinely satisfying kind of validation — not just "the fix worked once," but "the fix generalizes, and remembering it saved real time the second time it mattered." Every field in the chip's own diagnostic dump matched exactly what I'd built too, an independent confirmation the file made it onto the board completely intact.
Where this leaves Track B
Both halves of the chain — the bootloader and the kernel — are now independently proven on real hardware: signed, checked by the chip itself, and confirmed genuinely clean. That's the same milestone series one reached, just now inside the actual production toolchain instead of a one-off lab build.
What's left is less about cryptography and more about plumbing: making the normal, everyday firmware-build command produce a signed image by default, instead of this being a separate manual pass — and then an actual full boot test, not just a signature check, to prove the signed kernel doesn't just pass inspection but genuinely runs.