Skip to content

DE25-Nano wave 2: U-Boot/TF-A, bootable card image, kernel diet, 7.2.3 (stacked on #137) - #138

Merged
mcfbytes merged 12 commits into
feature/config-fragmentsfrom
feature/de25-wave2
Sep 2, 2026
Merged

DE25-Nano wave 2: U-Boot/TF-A, bootable card image, kernel diet, 7.2.3 (stacked on #137)#138
mcfbytes merged 12 commits into
feature/config-fragmentsfrom
feature/de25-wave2

Conversation

@mcfbytes

@mcfbytes mcfbytes commented Sep 2, 2026

Copy link
Copy Markdown
Owner

Summary

Wave 2 of the DE25-Nano bring-up, stacked on #137 (config fragments). Everything a machine without the board can do toward a card that is safe to put in a borrowed DE25-Nano. make de25 is green end to end and emits sdcard-de25.img. Nothing here has run on hardware.

Track What landed
U-Boot + TF-A mainline U-Boot v2026.07 and TF-A v2.15.0 through Buildroot; u-boot.itb built by binman, dumpimage-verified against the factory SPL contract (crc32 only, no keys, addresses disjoint). QSPI write paths compiled out (CMD_SF/MTD/UBI/ENV_IS_IN_UBI absent from the resolved config, confirmed in the binary's strings). Stock's default boot command carried a saveenv && ubi part root leg; gone with CMD_SF. HANDOFF and BLOBLIST off because the factory SPL, not ours, runs first. SD PHY: SoCDK-validated delays, default-speed 25 MHz for first contact. docs/de25-uboot.md.
SD card image MBR, p1 FAT32 DE25BOOT (u-boot.itb, Image, dtb, extlinux/extlinux.conf), p2 = ext4 rootfs written directly (interim p2 decision). scripts/check-sdcard-de25.sh opens the FIT, allow-lists p1, and rejects the DE10 card and every mutated card. docs/de25-sdcard.md.
Kernel diet + shared fragment board/mister/common/linux-mister.fragment (the arch-neutral MiSTer driver set) + minimal de25nano/linux.config. 1,481 → 92 modules, Image 41.9 → 20.7 MB; installed module name set identical to the DE10's. The fragment is proven a no-op on the DE10 kernel by scripts/check-kernel-fragment-noop.sh. docs/de25-kernel-config.md.
Kernel pin 7.2.2 → 7.2.3, following the shared hash registry after the rt bump; 34/34 patches apply at -F0, 460/460 config symbols survive.
Fragment port The DE25 defconfig edits live in configs/fragments/de25nano.fragment; rationale in docs/buildroot-config.md §6. Only the de25nano golden line changed.

Reviews already applied

Two Fable adversarial passes ran before this PR: the boot path (no brick-class or boot-blocking finding; QSPI surfaces verified closed in the built U-Boot, TF-A and kernel) and the config refactor (in #137). Their fixes are in the commits.

For the borrowed-board owner

The QSPI must be at the factory image (our card relies on the factory SPL). First-boot notes: no NOTICE: BL31 lines will appear on the header UART (TF-A prints on UART0); capture the SPL's DDR: lines; if Retrieving file: /Image stalls, the SD PHY timing is the first knob (de25-uboot.md §5.1). Full checklist in docs/de25-nano-tasks.md → "Testing on a borrowed board".

Open owner decisions

p2 filesystem / two-stage layout; DE25 linux-firmware selection (the shared fragment builds the Wi-Fi/BT drivers that will request it); patch 0002 (audio); a Renovate manager for the DE25 kernel pin; upstream submission of 0101/0102.

🤖 Generated with Claude Code

https://claude.ai/code/session_01FYjrnzEEu4HzJSPWNAaRvm

Copilot AI lite review requested due to automatic review settings September 2, 2026 16:11

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

There are concrete correctness issues in the new DE10 fragment no-op checker (missing Kconfig path) and in the Makefile’s DE25_ALLOW_NO_UBOOT behavior (currently ineffective/inconsistent with the documented post-image escape hatch).

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR advances the DE25-Nano bring-up (“wave 2”) by adding a Buildroot-built TF-A + U-Boot FIT, generating a bootable SD card image, and restructuring the DE25 kernel config to use a minimal base plus a shared MiSTer driver fragment (while bumping the DE25 kernel pin to 7.2.3).

Changes:

  • Add DE25 SD-card image assembly + a fail-closed image verifier (sdcard-de25.img, with strict FAT allow-listing and FIT validation).
  • Introduce DE25 bootloader build inputs (TF-A BL31 + U-Boot u-boot.itb) plus U-Boot DTS/fragment configuration emphasizing “no QSPI write” posture.
  • Replace DE25 “arm64 defconfig + delta” with a pinned minimal linux.config and new shared board/mister/common/linux-mister.fragment, plus a no-op enforcement script.
File summaries
File Description
scripts/check-sdcard-de25.sh New static verifier for sdcard-de25.img (partitioning, FAT allow-list, FIT contents, extlinux args, ext4 sanity).
scripts/check-kernel-fragment-noop.sh New enforcement script intended to prove the shared kernel fragment is a no-op on the DE10 kernel tree.
README.md Documentation update clarifying portability/maintenance aspects of the loop/attach rewrite discussion.
Makefile DE25 build target now asserts boot artifacts (BL31/FIT) and card image creation; help text updated.
docs/de25-sdcard.md New documentation for DE25 SD layout, build/write process, and first-boot checklist.
docs/de25-nano-tasks.md Wave-2 status recording, updated remaining task list.
docs/buildroot-config.md DE25 kernel-pin bump notes + updated DE25 section reflecting bootloader/card/kernel-config changes.
configs/fragments/golden.sha256 Update golden hash for the de25nano fragment stack.
configs/fragments/de25nano.fragment Extend DE25 Buildroot fragment with TF-A/U-Boot/card/host-tooling + kernel config switch.
board/mister/de25nano/uboot.fragment New U-Boot config fragment focusing on FAT env, disabling QSPI/MTD/UBI paths, and avoiding SPL handoff dependencies.
board/mister/de25nano/uboot-dts/* New U-Boot board DTS + -u-boot.dtsi for console/MMC/FIT/binman shaping.
board/mister/de25nano/post-image.sh New post-image script generating extlinux.conf, running genimage, and invoking the SD-card checker.
board/mister/de25nano/patches/uboot/* New U-Boot hash and local patch to guard MTD env vars when MTD is compiled out.
board/mister/de25nano/patches/arm-trusted-firmware/* New TF-A hash for the Buildroot-generated archive.
board/mister/de25nano/linux.fragment Removed DE25 kernel delta fragment (replaced by pinned base config + shared fragment).
board/mister/de25nano/linux.config New pinned minimal DE25 kernel base config.
board/mister/de25nano/linux-patches/README.md Update patch-series docs for 7.2.3 re-verification notes.
board/mister/de25nano/genimage-sdcard.cfg New genimage config for DE25 SD layout (MBR, FAT32 boot, ext4 rootfs).
board/mister/common/linux-mister.fragment New shared, arch-neutral MiSTer driver/feature kernel fragment (intended to be DE10-no-op).
.github/workflows/lint.yml Include per-board post-image.sh in shellcheck + executable-bit checks.
Review details
  • Files reviewed: 24/24 changed files
  • Comments generated: 3
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread Makefile Outdated
Comment thread Makefile Outdated
Comment thread scripts/check-kernel-fragment-noop.sh
mcfbytes added a commit that referenced this pull request Sep 2, 2026
… exists

Copilot review on #138: the bl31.bin/u-boot.itb assertions ran
unconditionally, so the documented kernel/rootfs-only escape hatch
could never succeed, and the card branch reported 'no u-boot.itb'
whenever the variable was set even if a FIT had been built. Now the
env var only matters when u-boot.itb is absent: with a FIT present the
recipe behaves exactly as without the variable. check-kernel-fragment-
noop.sh: comment explaining that exported srctree is what lets conf
find Kconfig from the scratch dirs (the check runs and passes).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FYjrnzEEu4HzJSPWNAaRvm
mcfbytes and others added 12 commits September 2, 2026 11:24
board/mister/de25nano/genimage-sdcard.cfg: MBR, p1 FAT32 'DE25BOOT'
(u-boot.itb, Image, dtb, extlinux/extlinux.conf), p2 = rootfs.ext4
verbatim, no 0xA2 partition (that is the Cyclone V BootROM contract).
MBR chosen fail-closed: the only observed DE25 boot is from an MBR
card; the factory SPL contract names no partition-table symbol.
post-image.sh generates extlinux.conf, runs genimage, fails without
u-boot.itb unless DE25_ALLOW_NO_UBOOT=1. scripts/check-sdcard-de25.sh
asserts table type, partition types/sizes/labels, the four p1 files,
extlinux directives and kernel args, ext4 label/features/fsck, and the
absence of any QSPI reference; dry run passes, the DE10 card is
rejected with nine failures. docs/de25-sdcard.md records the interim
p2 decision (ext4 rootfs directly), write procedure and first-boot
checklist. lint.yml's shipped-script lists gain post-image.sh (covers
the DE10's too, which was unlisted).

Defconfig/Makefile wiring lands with the U-Boot track, which owns
those files.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FYjrnzEEu4HzJSPWNAaRvm
board/mister/common/linux-mister.fragment (409 lines): the arch-neutral
MiSTer driver/feature set lifted from the DE10's resolved config — HID
and gamepads, USB, Bluetooth, the Wi-Fi driver set, sound, filesystems,
netfilter, loop/overlay. Proven a NO-OP on the DE10 6.18.48 tree
(zero redefinitions, resolved config identical) by the new
scripts/check-kernel-fragment-noop.sh, which also passes on the 7.2.2
DE25 tree. board/mister/de25nano/linux.config (51 lines): minimal
arm64 + Agilex 5 base in the DE10 style. Base and fragment share no
symbol; all 460 lines survive olddefconfig.

Measured on a kernel-only build in a scratch output dir:
=m symbols 1,481 -> 92 (DE10: 92); installed modules 90 MB -> 2.4 MiB;
Image 41.9 MB -> 20.7 MB. The two boards' installed module name sets
are identical. The wave-1 arm64-defconfig kernel had joydev, uinput,
hidraw, HID_NINTENDO/PLAYSTATION, xpad and HZ_1000 all OFF — invisible
in a green build.

docs/de25-kernel-config.md: per-subsystem rationale, what is
deliberately off, the symbols not shared and why (FB_MISTER, audio,
CMA, cpufreq...), the per-bump re-check list, and two obligations:
openssh needs BR2_PACKAGE_OPENSSH_SANDBOX off once added (SECCOMP is
off as on the DE10), and the DE25 selects no linux-firmware yet.

The defconfig switch (custom config + fragment, delete
de25nano/linux.fragment) lands with the U-Boot track's defconfig edit.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FYjrnzEEu4HzJSPWNAaRvm
… wired; kernel diet switched in

u-boot.itb built by binman from mainline, shape-verified with dumpimage
against the factory SPL contract: uboot @0x80200000, atf (BL31)
@0x80000000 = entry, fdt-0, config board-0 default, crc32 only — no
rsa, no required keys, addresses disjoint from the 0x82000000 FIT
staging area. Reproducible: two runs byte-identical.

QSPI cannot be written from this U-Boot: ENV_IS_IN_UBI, CMD_SF, CMD_MTD,
DM_SPI_FLASH, MTD_UBI, ENV_IS_IN_SPI_FLASH/NAND are absent from the
resolved config (deps unmet); CADENCE_QSPI, MTD, CMD_UBI, HANDOFF off;
ENV_IS_IN_FAT 0:1 is the only env location. Notably stock's
BOOTENV_DEV_QSPI contains 'saveenv && ubi part root' inside the
default boot command — gated on CMD_SF, which is off, so the target
and the string are gone; boot_targets=mmc0 only. HANDOFF off because
dram_init would otherwise require a bloblist from OUR SPL at OUR
BLOBLIST_ADDR, but the factory SPL runs; /memory declared 1 GiB.

Board DTS for U-Boot (uboot-dts/): socdk aliases serial0 to uart0 and
the DE25 console is uart1, so a minimal board dts + -u-boot.dtsi;
mmc0 alias pinned; conservative mmc (4-bit, 50 MHz, no UHS). One
carried, upstreamable patch guards CFG_EXTRA_ENV_SETTINGS's
mtdids/mtdparts reference for MTD-less configs. §8 Q6 closes negative:
'# CONFIG_SPL is not set' removes BINMAN and the FIT; SPL is compiled
but nothing of it ships. Hashes: U-Boot tarball .sig verified (Tom
Rini); TF-A tag anchored TOFU on its commit from two clones.

Defconfig: also switches the kernel to board/mister/de25nano/
linux.config + board/mister/common/linux-mister.fragment (c2ab0c9) and
deletes de25nano/linux.fragment; wires the card image (host genimage/
mtools/dosfstools, post-image.sh). make de25 asserts Image, dtb,
rootfs.ext4, bl31.bin, u-boot.itb and sdcard-de25.img; stat follows
symlinks. Verified: make de25 green, check-sdcard-de25.sh all
assertions passed on the real artefacts. docs/de25-uboot.md has the
fragment rationale, dumpimage listing, QSPI audit table, boot flow and
first-boot serial expectations.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FYjrnzEEu4HzJSPWNAaRvm
…k one is not

Compile-verified: 0100 applied to pristine 6.18.48, ARCH=arm64 with the
DE25 toolchain, init/do_mounts.o and drivers/block/loop.o build clean.
It does not apply to 7.2.2 (one context hunk: load_ramdisk= removed),
which is version drift, not an architecture problem.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FYjrnzEEu4HzJSPWNAaRvm
…ct, bloblist off

Fable boot-path review: with no cdns,phy-* values, U-Boot proper drove
the SD PHY with sdhci-cadence6.c's built-in defaults, which no Agilex 5
board has been validated with, at 50 MHz high-speed — the factory SPL
reads u-boot.itb with vendor timing and our driver then re-inits the
PHY. Now: the socdk-u-boot.dtsi sd-ds/sd-hs PHY delays (SoC-level, not
the board vqmmc fact) copied verbatim, cap-sd-highspeed dropped,
max-frequency 25 MHz. de25-uboot.md §5.1 gives the symptoms, the
diagnosis order and the one-line lift once dd of the card is clean.

CONFIG_BLOBLIST off: its fixed 0x7e000+0x1000 window overlapped TF-A's
secondary-CPU handshake words at 0x7EFF0/0x7EFF8; unused with HANDOFF
off; build verified, u-boot.itb still produced (728,176 B, crc32-only,
addresses unchanged). Docs: linux_qspi_enable IS run by
board_prep_linux() — the argument is the CADENCE_QSPI gate; card ships
no uboot.env; BL31 prints on UART0, so no NOTICE: BL31 lines are
expected on the header UART.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FYjrnzEEu4HzJSPWNAaRvm
Fable boot-path review: a FIT recompiled with sha256,rsa2048 + required
keys passed the checker, as did 4 KiB of urandom named u-boot.itb, and
a stray boot.scr (which distro boot executes the moment extlinux
fails) or uboot.env was merely 'informational'. Now: p1's u-boot.itb
must be byte-identical to images/u-boot.itb, dumpimage must show
uboot @0x80200000, atf @0x80000000, fdt-0, a default config and a
crc32 signature algo, and the decompiled FIT must contain no
rsa/required/sha<n>; p1 may hold nothing beyond the four expected
entries. dumpimage/dtc resolved from the Buildroot host dir, exit 2 if
absent. Real card passes; m1 (uboot.env), m2 (rsa FIT), m3 (garbage
FIT) and m5 (boot.scr with sf erase) all fail. docs/de25-sdcard.md:
extlinux search path settled [V], BL31 silence on uart1 expected,
uboot.env question settled: no.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FYjrnzEEu4HzJSPWNAaRvm
… the diet

Renovate's rt bump moved board/mister/de10nano/patches/linux/linux.hash from
7.2.2 to 7.2.3. That file is the DE25's hash registry too (the board's
patches/linux/linux.hash is a relative symlink into it), and the sync script
REPLACES the 7.2.y line rather than adding one -- so the hazard
docs/buildroot-config.md filed as a "known follow-up" stopped being
hypothetical. configs/fragments/de25nano.fragment already carries 7.2.3 from
the rebase base; this commit makes the rest of the tree say so and, more to the
point, re-runs the evidence at the new pin instead of assuming it carried over.

Re-verified on a linux-dirclean rebuild against a freshly downloaded,
hash-verified linux-7.2.3.tar.xz (make de25, green, card checker included):

  - carried patch series: 34/34 applied at Buildroot's patch -F0, zero fuzz,
    zero rejects. 79 hunks relocated by line OFFSET only, which -F0 permits
    (-F caps context fuzz, not displacement).
  - kernel diet: 460 asked-for symbols (51 base + 409 shared fragment), ZERO
    dropped from the resolved config; zero merge_config redefinitions.
  - 92 =m symbols / 91 installed .ko.xz / 2,565,868 B of modules -- unchanged,
    and the installed module NAME SET is still exactly the DE10's (91 vs 91,
    empty diff both directions against output/build/linux-6.18.48).
  - check-kernel-fragment-noop.sh still PASSes on the DE10 tree.
  - u-boot.itb and bl31.bin are byte-identical to the 7.2.2 build, as they must
    be: nothing in the bootloader half depends on the kernel version. The board
    .dtb is byte-identical too, so mainline's socfpga_agilex5.dtsi did not move
    in the point release. Image differs (a stable-tree release changes code)
    while coincidentally keeping the same length.

All four golden hashes are unchanged: the normalisation deliberately drops the
two kernel-version symbols, so a pin bump must not move them, and does not.

Doc changes are the pin statements only. Dated measurements keep their 7.2.2
provenance and say so; the dtbs_check warning count was NOT re-run at 7.2.3 and
is labelled accordingly. Nothing here has been on hardware at 7.2.3.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FYjrnzEEu4HzJSPWNAaRvm
The shared kernel fragment sets MODULE_COMPRESS_XZ but the DE25 stack
did not set BR2_PACKAGE_HOST_KMOD_XZ, so build-time depmod silently
produced a 0-line modules.dep and a 1-line modules.alias — the exact
trap docs/buildroot-config.md §3.5 records for the DE10. Found by the
rebase pass. After host-kmod-dirclean + make de25: modules.dep 91
lines, modules.alias 1,204, card checker passes. Golden refreshed for
the de25nano stack only.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FYjrnzEEu4HzJSPWNAaRvm
… exists

Copilot review on #138: the bl31.bin/u-boot.itb assertions ran
unconditionally, so the documented kernel/rootfs-only escape hatch
could never succeed, and the card branch reported 'no u-boot.itb'
whenever the variable was set even if a FIT had been built. Now the
env var only matters when u-boot.itb is absent: with a FIT present the
recipe behaves exactly as without the variable. check-kernel-fragment-
noop.sh: comment explaining that exported srctree is what lets conf
find Kconfig from the scratch dirs (the check runs and passes).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FYjrnzEEu4HzJSPWNAaRvm
The previous commit's if-block began with a literal '@' inside a
continued shell chain, which make passed through as a command (exit 2).
Verified: make -n de25 | bash -n clean for both variants, make de25
green end to end. Adds the srctree comment the previous message
described.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FYjrnzEEu4HzJSPWNAaRvm
echo "" \ + fi parsed as one command; now echo ""; \ then fi.
Proven: make -n de25 | bash -n clean for both variants, make de25 green
end to end (bl31, FIT, card all reported; checker passes).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FYjrnzEEu4HzJSPWNAaRvm
@mcfbytes
mcfbytes merged commit 0e241d7 into feature/config-fragments Sep 2, 2026
5 checks passed
@mcfbytes
mcfbytes deleted the feature/de25-wave2 branch September 2, 2026 16:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants