DE25: aarch64 stage-1 initramfs + qemu-system-aarch64 test leg (stage 1 becomes a fragment stack) - #152
Merged
Merged
Conversation
…4 (DE25) stage 1 ADR 0029 D11 made the DE10's two-stage layout the DE25-Nano's target, which means a stage-1 initramfs built for aarch64. The stage-1 config was the one standalone defconfig left (docs/buildroot-config.md §10 recorded "left standalone" on 2026-09-02, weighing six saved lines against a new stack shape for one board); a second board wants every line of it except the arch tuple, so it is now a stack like everything else: configs/fragments/initramfs-common.fragment everything but the arch configs/fragments/initramfs-de10nano.fragment BR2_arm + cortex_a9 + NEON/VFP + headers 6.18 configs/fragments/initramfs-de25nano.fragment BR2_aarch64 + cortex_a76_a55 + headers 7.1 stacks.mk: INITRAMFS_DE10NANO_FRAGMENTS / INITRAMFS_DE25NANO_FRAGMENTS configs/mister_initramfs_defconfig is deleted. The three arch-neutral files it named -- initramfs-overlay/init, initramfs-busybox.config, initramfs-post-build.sh -- move from board/mister/de10nano/ to board/mister/common/ (the linux-mister.fragment precedent): /init has no architecture-specific line, the BusyBox config names no arch, the hook only deletes files. Every live reference is updated; PLAN.md/TASKS.md and the readiness ledger keep their historical citations. Identity proof (Buildroot 2026.08, this tree): the DE10 stage-1 resolved .config from the old `make mister_initramfs_defconfig` path vs the new merge_config.sh + olddefconfig path differs in exactly BR2_DEFCONFIG (the savedefconfig output path, as at the image split), the git-describe -dirty suffix, and the three moved paths -- 5,240 lines otherwise identical (gcc 15.3.0, binutils 2.45.1, musl, headers 6.18). golden.sha256 gains lines for the two new stacks; the existing four did not move. Makefile: the stage-1 .config rules use the fragment stacks (fragments ARE file prerequisites here, as the defconfig was -- a stage-1 config is generated, not iterated on; an explicit empty rule keeps the `%:` catch-all off them). New `de25-initramfs` family (build/verify/clean/defconfig/ menuconfig/busybox-menuconfig) into output-initramfs-de25/. initramfs-verify is parameterised by three variables so de25-initramfs-verify runs the SAME applet/binary/parse assertions on the aarch64 cpio under qemu-aarch64 -- one assertion set for both boards. `de25` still depends on no initramfs target: the cpio is built and verified, NOT embedded, while the shipped card keeps D11's interim plain-ext4 root; external.mk's BR2_arm guard stands and its comment now carries the one-commit switch. scripts/check-config-fragments.sh: new check (f), stage-1 arch lockstep -- every symbol initramfs-<board>.fragment sets must be set identically in <board>.fragment, so a CPU-tuning or headers-series change in one file and not the other fails CI instead of building a stage 1 for a different target than the kernel it rides in. The initramfs stacks are picked up by (a)-(d) automatically (stacks.mk enumeration). CI: BR_INITRAMFS_HOST_KEY hashes the initramfs-de10nano stack's files through config_stack_files instead of the deleted defconfig (one cold initramfs host cache, once). lint.yml's per-board script walk already covers board/mister/common/. Built and verified in this tree on 2026.08: DE10 cpio 424,448 bytes, DE25 cpio 466,944 bytes (static aarch64 BusyBox 1.38.0; toolchain + cpio in 6 min from nothing), both initramfs-verify OK; check-config-fragments OK (6 stacks), check-kernel-defconfig-sync OK. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FYjrnzEEu4HzJSPWNAaRvm
…stem-aarch64
The harness gains a board switch (`--board de10nano|de25nano`, or
TEST_INITRAMFS_BOARD); the DE10 leg is unchanged in behaviour. The DE25 leg:
* boots output-initramfs-de25/images/rootfs.cpio on
`qemu-system-aarch64 -M virt -cpu cortex-a76` (virt has no default CPU
on aarch64; a76 is what BR2_cortex_a76_a55 tunes for -- an armv8.2
target whose LSE atomics a cortex-a53 model would SIGILL on);
* builds its test kernel from the DE25's OWN product config
(board/mister/de25nano/linux.config + board/mister/common/
linux-mister.fragment) at the DE25's pinned 7.2.3, plus the unchanged
harness fragment (every symbol in it is arch-neutral) -- arm64 has no
multi_v7_defconfig to lean on, the product config is minimal enough to
build in minutes, and this way the leg also proves the product
config's own exfat/vfat/loop/ext4 choices, which the DE10 leg cannot
do for its board;
* cross-compiles marker-init/test-symlink with the stage-1 build's own
musl toolchain (output-initramfs-de25/host/bin), so `make
de25-initramfs` is the only build prerequisite -- no `make de25`;
* keeps its own caches (work/test-initramfs-de25*).
Every case, cmdline and assertion is identical between the legs. The
kernel-tarball default now prefers dl/linux/linux-<pin>.tar.xz (where the
Buildroot kernel build actually puts it) over the work/ convention nothing
creates, which retires the always-FAIL-on-a-fresh-tree papercut. The mtools
prerequisite message no longer claims `make initramfs` builds host mtools
(it never did; the system package is what is used).
ci-tests.sh gains the DE25 leg (de25-initramfs-verify + the eight cases),
gated on the DE25 cpio existing so a DE10-only tree skips it visibly.
Results, this tree, 2026-09-06:
--board de10nano 8/8 PASS (3 m 09 s, cached kernel)
--board de25nano 7/8 PASS (4 m 16 s including the 7.2.3 kernel build;
one case re-run 5.5 s). `symlink` FAILS with a kernel
Oops in exfat_symlink -> page_symlink -> pc 0x0: board
patch 0031 relies on a_ops->write_begin, which 7.x
iomap exFAT no longer has. Not an aarch64 bug, not an
/init bug -- a 7.x carry bug in 0031 that the DE10 RT
kernel shares and nothing had ever executed. Recorded
in the next commit; the fix is a follow-up.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FYjrnzEEu4HzJSPWNAaRvm
…finding ADR 0002 §8b, ADR 0029 D11 (delivered), docs/de25-nano-tasks.md (wave 3 record; next-steps item 2 becomes the 0031 re-anchor), docs/de25-sdcard.md §2 (the one-commit switch table), docs/rt-beta-kernel.md §6 (the RT kernel carries the same broken 0031 by symlink), the DE25 patch README row 25. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FYjrnzEEu4HzJSPWNAaRvm
…_symlink() Oopses on iomap exfat Found by the previous commit's aarch64 QEMU leg, the first thing ever to EXECUTE 0031 on a 7.x kernel: exfat_symlink() -> page_symlink() -> aops->write_begin, and 7.x exfat (iomap, fs/exfat/iomap.c) has no write_begin/write_end in exfat_aops -- 6.18.49 has both. So the first `ln -s` on any 7.x kernel is a NULL function call: Oops, pc 0x0, lr page_symlink+0x178. The patch applied at -F0 and compiled, which is why every "verified" row about it was true and insufficient. Blast radius: the DE25 (7.2.3) and the DE10's RT 7.2.3 kernel -- linux-patches-beta/0031 was a symlink to the shared 6.18 file. The shipped DE10 6.18 kernel is unaffected (its QEMU leg passes `symlink` 8/8). linux-patches-beta/0031-exfat-samsung-symlinks.patch is a REAL re-anchored copy again (the fifth; the series header explains why this one is the API kind of drift, not the context kind that the 2026-07-25 trick could absorb), and board/mister/de25nano/linux-patches/0031 now links to it. The shared 6.18 patch is untouched. The delta is confined to fs/exfat/namei.c: a new exfat_symlink_write_target() allocates the clusters with 7.x's exfat_map_cluster() under s_lock, fills the sectors through buffer heads, flushes the range with sync_blockdev_range() -- page_get_link() reads via iomap bios straight from the device and never sees a dirty bdev buffer -- and does the valid_size / zeroed_size / i_size bookkeeping exfat_write_iomap_end() and the VFS write path would have done. iomap_file_buffered_write() was not an option: it dereferences iocb->ki_filp, and a ->symlink op has no struct file. Verified: applies at -F0 to pristine 7.2.3 (12/12 hunks, 6 files); compiles for arm with output-rt's own 7.2.3 .config (fs/exfat/, zero warnings) and for arm64 with the DE25 config; scripts/test-initramfs.sh --board de25nano from a fresh source tree: 8/8 PASS, the `symlink` case with its full assertion set (hot+cold round-trip, DT_LNK, the create+unlink cluster-leak tripwire via statvfs, host-side fsck-clean). Still unexecuted: 0031 on 32-bit 7.x -- the RT kernel on a real DE10 -- which the docs now say in as many words. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FYjrnzEEu4HzJSPWNAaRvm
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
ADR 0029 D11's owed pre-hardware work: the stage-1 initramfs built for aarch64, and a QEMU path that boots it. Three commits, reviewable in order.
1. Stage 1 becomes a fragment stack per board (
5849aa3)configs/mister_initramfs_defconfig→configs/fragments/initramfs-common.fragment(everything but the arch) +initramfs-de10nano.fragment/initramfs-de25nano.fragment(arch/ABI + headers series only).stacks.mkgainsINITRAMFS_DE10NANO_FRAGMENTS/INITRAMFS_DE25NANO_FRAGMENTS./init,initramfs-busybox.config,initramfs-post-build.shmove toboard/mister/common/(shared by path, likelinux-mister.fragment)./inithas no arch-specific line; the BusyBox config names no arch..configrules use the stacks (fragments stay file prerequisites — a stage-1 config is generated, not iterated on). Newmake de25-initramfsfamily intooutput-initramfs-de25/;initramfs-verifyis parameterised sode25-initramfs-verifyruns the same assertions underqemu-aarch64.de25still embeds nothing (D11 interim);external.mk's guard comment has the one-commit switch.check-config-fragments.shcheck (f): every symbolinitramfs-<board>.fragmentsets must be set identically in<board>.fragment. Golden gains two lines; the existing four did not move.BR_INITRAMFS_HOST_KEYhashes the stack viaconfig_stack_files(one cold initramfs host cache, once).lint.yml's per-board walk already coversboard/mister/common/.Identity proof (Buildroot 2026.08): DE10 stage-1 resolved config, old path vs new, differs only in
BR2_DEFCONFIG, the-dirtysuffix and the three moved paths — 5,240 lines otherwise identical. §11 ofdocs/buildroot-config.mdrecords it.2.
scripts/test-initramfs.sh --board de25nano(690af50)Boots the aarch64 cpio on
qemu-system-aarch64 -M virt -cpu cortex-a76through the DE10's eight cases, unchanged. The test kernel is built from the DE25's ownlinux.config+linux-mister.fragmentat the DE25 pin (no arm64 multi_v7 exists; the product config builds in minutes and this way its exfat/vfat/loop/ext4 choices are proven too). Cross compiler = the stage-1 build's own musl toolchain, somake de25-initramfsis the only prerequisite.ci-tests.shgains the leg (skips when no DE25 cpio was built). Kernel-tarball default now prefersdl/linux/, retiring the always-FAIL-on-a-fresh-tree papercut.3. Docs (
24c7925) — and the finding--board de10nano--board de25nanoThe
symlinkcase Oopses the guest kernel (exfat_symlink→page_symlink→pc: 0x0). Board patch 0031 (exFAT Samsung symlinks, ADR 0019) writes the link target with the VFS'spage_symlink(), which callsa_ops->write_begin— and 7.x exFAT is iomap-based with nowrite_begin/write_end(6.18.49 has both). So 0031 crashes on symlink creation on every 7.x kernel. Not an aarch64 bug, not an/initbug. The DE10's RT 7.2.3 kernel carries the same file by symlink and nothing had ever executed it — the DE10 leg only boots 6.18. The shipped DE10 image is unaffected (8/8 above includessymlinkon 6.18).Recorded in ADR 0002 §8b, ADR 0029 D11,
docs/rt-beta-kernel.md§6, the DE25 patch README, anddocs/de25-nano-tasks.md(next-steps item 2 = a 7.x re-anchor of 0031; the aarch64symlinkcase is its acceptance test). The fix is a separate PR.Verified locally (Buildroot 2026.08, gcc 15.3.0)
make de25-initramfs: toolchain + cpio in 6 min from nothing; 466,944-byte cpio, static aarch64 BusyBox; verify OK.make initramfs(DE10, rebuilt clean on 2026.08): 424,448-byte cpio; verify OK; QEMU 8/8.check-config-fragments.shOK (6 stacks, arch lockstep 6 + 3 symbols);check-kernel-defconfig-sync.shOK; shellcheck clean.🤖 Generated with Claude Code
https://claude.ai/code/session_01FYjrnzEEu4HzJSPWNAaRvm