Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,53 @@ jobs:
cp -f "output/images/$img.xz" dist/
ls -la dist/

# docs/uboot-tasks.md U5: the DE10's mainline U-Boot ships nowhere and
# `scripts/ci-tests.sh` (the "Run parity suite" step above) only has
# the offline structural/built-SPL-only subset of check-uboot-parity.sh
# / check-uboot-handoff.sh -- the stock uboot.img does not exist on
# disk until the sdcard step just above fetches and verifies it. This
# is the one place that download is already paid for, so every tagged
# release proves FULL parity (environment + command table + handoff
# tables against the real stock blob) without a second fetch and
# without any PR paying for it.
#
# This step is ALSO the only place the "ships nowhere" half of owner
# decision 1 can actually be enforced in CI: dist/ is created by
# scripts/mk-release.sh, which runs AFTER verify-image, so ci-tests.sh's
# own release-stage assertion can only ever SKIP on a runner. Here dist/
# is fully populated (mk-release.sh's assets plus the sdcard image the
# step above copied in), so the grep has teeth.
- name: Verify U-Boot (DE10) parity against the stock blob (docs/uboot-tasks.md U5)
env:
STOCK_UBOOT_IMG: ${{ github.workspace }}/output-sdcard-stage/mister-payload/linux/uboot.img
run: |
set -eu
shopt -s nullglob # so an unmatched glob counts 0, not 1 literal
uboot_trees=(output/build/uboot-*)
[ "${#uboot_trees[@]}" -eq 1 ] ||
{ echo "::error::expected exactly one output/build/uboot-*, found ${#uboot_trees[@]}"; exit 1; }
uboot_tree=${uboot_trees[0]}
[ -f "$STOCK_UBOOT_IMG" ] ||
{ echo "::error::no stock uboot.img at $STOCK_UBOOT_IMG -- the sdcard step above should have staged it"; exit 1; }

# "ships nowhere", asserted against the real, finished release stage.
echo "--- release stage (dist/) must carry no bootloader artifact ---"
ls -la dist/
stage_hits=$(find dist -maxdepth 1 \( -name 'uboot.img' -o -name '*.sfp' \))
[ -z "$stage_hits" ] ||
{ echo "::error::owner decision 1 says the DE10's mainline U-Boot ships nowhere, but the release stage carries: $(echo "$stage_hits" | tr '\n' ' ')"; exit 1; }
echo "ok: no uboot.img/*.sfp in dist/"

spl_limit=$("$uboot_tree/tools/spl_size_limit")
SPL_SIZE_LIMIT="$spl_limit" scripts/check-uboot-parity.sh \
output/images/u-boot-with-spl.sfp \
"$STOCK_UBOOT_IMG" \
"$uboot_tree/u-boot"
scripts/check-uboot-handoff.sh \
"$uboot_tree/board/terasic/de10-nano/qts" \
output/images/u-boot-with-spl.sfp \
"$STOCK_UBOOT_IMG"

- name: Release overview (job summary)
env:
RELEASE_DATE: ${{ steps.release.outputs.release_date }}
Expand Down
10 changes: 6 additions & 4 deletions PLAN.md
Original file line number Diff line number Diff line change
Expand Up @@ -545,7 +545,7 @@ mister-linux/
│ │ ├── 0012-hid-fanatec.patch
│ │ ├── 0013-hid-flydigi-vader.patch
│ │ └── 0020-usb-storage-blacklist-realtek-cdrom.patch
│ ├── uboot-patches/ # empty in v1; P5: build fixes ONLY, never
│ ├── patches/uboot/ # empty in v1; P5: build fixes ONLY, never
│ │ # behaviour changes (ADR 0017)
│ ├── rootfs-overlay/
│ │ ├── etc/init.d/S??… # BusyBox init scripts (parity with stock)
Expand Down Expand Up @@ -677,7 +677,9 @@ one-line change, and CI tells us immediately if a patch stopped applying.

> **[2026-07-28] This section is superseded from "Phase 5 path" onward by
> [ADR 0024](docs/decisions/0024-mainline-uboot-capability-artifact.md).** The from-source
> bootloader is now built from **mainline U-Boot 2026.04**, not the 2017.03 fork, as a
> bootloader is now built from **mainline U-Boot 2026.07** (2026.04 when first decided;
> re-pinned to 2026.07 on 2026-09-14 — see `docs/uboot-mainline-port.md`'s revision note),
> not the 2017.03 fork, as a
> non-shipping capability artifact — the mainline port surface has been measured rather
> than estimated, and it is smaller than this section assumed. **Do not add the `u-boot/`
> submodule.** Design and evidence: [`docs/uboot-mainline-port.md`](docs/uboot-mainline-port.md).
Expand Down Expand Up @@ -731,7 +733,7 @@ so the full-image build stays reproducible even if the upstream branch moves or
* Buildroot builds it from the submodule: `BR2_TARGET_UBOOT` + `UBOOT_OVERRIDE_SRCDIR`
pointing at `u-boot/` (via `BR2_PACKAGE_OVERRIDE_FILE`), starting from the fork's own
`MiSTer_defconfig`; output `u-boot-with-spl.sfp`, renamed `uboot.img`. The
`uboot-patches/` directory mirrors the kernel model but is reserved for **build fixes
`patches/uboot/` directory mirrors the kernel model but is reserved for **build fixes
only** — a 2017 codebase may need coaxing under a 2026 toolchain — never behaviour changes.
* **A byte-identical rebuild is impossible and is not the goal** (`docs/boot-chain.md`
§3.2: compiled-in non-UTC timestamp, exact 2020 Arm toolchain). The default Downloader
Expand Down Expand Up @@ -968,7 +970,7 @@ criteria — lives in `TASKS.md`.
|Rootfs exceeds the image budget|Medium|Grow `linux.img` to 512 MiB; audit assumptions about 400 MB.|
|Boot regression from the initramfs|Low|Measurable; budget in §11.|
|Bricking via U-Boot|**Critical**|Deferred to P5, opt-in, recovery documented **and drilled**. ADR 0017 shrinks the exposure: P5 builds the same source commit stock already runs, not a mainline port.|
|**[ADR 0017] 2017-era U-Boot fails to build under a 2026 toolchain**|Medium|Expected and contained: build fixes only in `uboot-patches/` (provenance-documented, never behaviour changes); worst case, pin the Arm GNU 10.2-2020.11 toolchain the stock binary used (`docs/boot-chain.md` §3.2).|
|**[ADR 0017] 2017-era U-Boot fails to build under a 2026 toolchain**|Medium|Expected and contained: build fixes only in `patches/uboot/` (provenance-documented, never behaviour changes); worst case, pin the Arm GNU 10.2-2020.11 toolchain the stock binary used (`docs/boot-chain.md` §3.2).|
|Community fragmentation / abandonment|**High**|Be strictly drop-in. Ship a working artifact before making an argument. **If nobody will commit to tracking 6.18.y stable for years, do not start.**|

That last one is not a joke. A stale fork is worse than no fork, because it splits the
Expand Down
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ document records what changed and which rows here it dates).
| **2 — Rootfs & testing** | ✅ Complete | Buildroot 2026.08, glibc 2.44, reproducible ext4 image with full SBOM; menu and cores load on hardware — the ABI contract holds *in practice*, not just on paper |
| **3 — Module packages & HW matrix** | ✅ Complete | Wi-Fi, Bluetooth, controllers and special devices packaged; hardware-validated **for the chips actually present on the one test board**. The v10/v10.1/v10.2 driver + firmware expansion (Broadcom, Wi-Fi 6/6E, MediaTek, Atheros USB, Redpine) is packaged and mostly CI-asserted but **not** hardware-validated — see the [ledger](#hardware-validation-ledger) and the [chipset table](#wi-fi-and-bluetooth-hardware-support). The remaining matrix rows (Samba, MIDI) are build/CI-verified only |
| **4 — Release & sustainability** | 🔄 In progress | CI/CD, `db.json` distribution, beta program, governance, publication gate |
| **5 — Full SD image & U-Boot** | 🔄 Partially landed | `sdcard.img` builds, and `release.yml` verifies it with `scripts/check-sdcard.sh` ([ADR 0020](docs/decisions/0020-sdcard-exfat-reformat-installer.md)); U-Boot-from-source is planned but not started — now targeting **mainline U-Boot**, not the 2017.03 fork ([ADR 0024](docs/decisions/0024-mainline-uboot-capability-artifact.md), [plan](docs/uboot-mainline-port.md), [tasks](docs/uboot-tasks.md)) — and the SD image has not been flashed to a fresh card on hardware (P5.4) |
| **5 — Full SD image & U-Boot** | 🔄 Partially landed | `sdcard.img` builds, and `release.yml` verifies it with `scripts/check-sdcard.sh` ([ADR 0020](docs/decisions/0020-sdcard-exfat-reformat-installer.md)); U-Boot from source is now building on every DE10 build, **mainline 2026.07**, ships nowhere ([ADR 0024](docs/decisions/0024-mainline-uboot-capability-artifact.md), [plan](docs/uboot-mainline-port.md), [tasks](docs/uboot-tasks.md), [verification](docs/verification/uboot-mainline.md)) — and the SD image has not been flashed to a fresh card on hardware (P5.4) |

### Hardware validation ledger

Expand Down Expand Up @@ -1019,8 +1019,10 @@ Start here if you want to run it: [**one-command install**](#install-it-on-a-rea
|---|---|
| [`docs/abi-contract.md`](docs/abi-contract.md) | What the kernel and rootfs must honor for the stock binary to run |
| [`docs/boot-chain.md`](docs/boot-chain.md) | U-Boot contract and its kernel-config implications |
| [`docs/uboot-mainline-port.md`](docs/uboot-mainline-port.md) | The plan for a mainline U-Boot built to behave like stock's — design, measured port surface, brick modes. Ships nowhere |
| [`docs/uboot-tasks.md`](docs/uboot-tasks.md) | Execution tasks for the above (U0–U7), split out of `TASKS.md` |
| [`docs/uboot-mainline-port.md`](docs/uboot-mainline-port.md) | The plan for a mainline U-Boot (2026.07) built to behave like stock's — design, measured port surface, brick modes; in progress, ships nowhere |
| [`docs/de25-nano-overview.md`](docs/de25-nano-overview.md) | **DE25-Nano, start here** — how the board boots, what we build for it, what is verified, what could still stop it; links to every DE25 document |
| [`docs/uboot-tasks.md`](docs/uboot-tasks.md) | Execution tasks for both boards (U0–U9 for the DE10, DU1–DU7 for the DE25), split out of `TASKS.md` |
| [`docs/verification/uboot-mainline.md`](docs/verification/uboot-mainline.md) | Mainline U-Boot 2026.07 for the DE10-Nano: built artifact measurements, structural checks against stock, allowed diffs, and verification evidence |
| [`docs/downloader-contract.md`](docs/downloader-contract.md) | How the on-device Downloader decides to update |
| [`docs/package-manifest.md`](docs/package-manifest.md) | All 251 stock SONAMEs mapped to a package, with major-bump flags |
| [`docs/stock-inventory/`](docs/stock-inventory/) | The audited inventory of the stock image everything above is measured against |
Expand Down
7 changes: 4 additions & 3 deletions TASKS.md
Original file line number Diff line number Diff line change
Expand Up @@ -1072,7 +1072,7 @@ the U-Boot half re-decided 2026-07-28 per
Phase 5 adds a **full flashable SD-card image** (kernel + `linux.img` + bootloader +
mr-fusion-parity payload) so a fresh card can be written without mr-fusion or the Windows
SD installer. That is what remains here. **The from-source bootloader moved out of this
phase entirely** — it is now built from **mainline U-Boot 2026.04** (not the 2017.03 fork,
phase entirely** — it is now built from **mainline U-Boot 2026.07** (not the 2017.03 fork,
and with no `u-boot/` submodule) and tracked in
[`docs/uboot-tasks.md`](docs/uboot-tasks.md). §8's posture is unchanged: highest blast
radius, everything here is opt-in, separate from `linux.img` updates, gated on a
Expand All @@ -1081,12 +1081,13 @@ drilled recovery procedure. **The default channel keeps shipping the stock

- [ ] **P5.1 / P5.2 — the from-source U-Boot → moved to [`docs/uboot-tasks.md`](docs/uboot-tasks.md)**
**Superseded by [ADR 0024](docs/decisions/0024-mainline-uboot-capability-artifact.md).**
The from-source bootloader is now built from **mainline U-Boot 2026.04**, not the 2017.03
The from-source bootloader is now built from **mainline U-Boot 2026.07**, not the 2017.03
fork, and it is a non-shipping capability artifact. **Do not add the `u-boot/`
submodule** — the mainline build uses Buildroot's own hash-verified tarball, and
`UBOOT_OVERRIDE_SRCDIR` (which the old P5.1 specified) would have silently skipped the
patch step. Design and evidence: [`docs/uboot-mainline-port.md`](docs/uboot-mainline-port.md).
Execution: [`docs/uboot-tasks.md`](docs/uboot-tasks.md), tasks U0–U7.
Execution: [`docs/uboot-tasks.md`](docs/uboot-tasks.md), tasks U0–U9 for the DE10-Nano
(and DU1–DU7 for the DE25-Nano's own `u-boot.itb`).
**Unchanged:** the default channel keeps shipping the stock `uboot.img` byte-identical
(P4.4), and `sdcard.img` keeps embedding that same stock blob (ADR 0017 §Decision 4/5
still stand). P5.3 and P5.4 below are unaffected.
Expand Down
2 changes: 1 addition & 1 deletion board/mister/de10nano/linux-rt.fragment
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ CONFIG_UIO_PDRV_GENIRQ=y
#
# This fragment is also the RT line's ONLY bootargs surface. There is no
# per-line U-Boot environment in this repo: U-Boot is stock and unmodified for
# both kernels (uboot-patches/ is empty; docs/rt-beta-kernel.md §5), and
# both kernels (patches/uboot/ is empty; docs/rt-beta-kernel.md §5), and
# /media/fat/linux/u-boot.txt selects only WHICH zImage loads — it carries no
# command-line content. The real cmdline arrives via U-Boot's stock
# `setenv bootargs` plus its /chosen FDT fixup (docs/boot-chain.md §4.2).
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
From: Michael C. Ferguson <michael.christopher.ferguson@gmail.com>
Date: Mon, 14 Sep 2026 00:00:00 +0000
Subject: [PATCH] arm: socfpga: fix dead raw-sector hook guard after the
TARGET->ARCH rename

board_spl_mmc_get_uboot_raw_sector() is the hook that adds the +0x200
sector offset a `u-boot-with-spl.sfp` image needs when U-Boot proper is
loaded from a raw MMC partition (CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_
PARTITION_TYPE=y, boot-chain.md section 2.1): the image is four 64 KiB
SPL copies followed by U-Boot proper, and SPL loads U-Boot proper from
that fixed offset inside the partition rather than from its start.

The hook has been compiled out since 2026-02-13 for every Gen5/Arria10
SoCFPGA board, DE10-Nano included, and nothing has noticed because the
fallback it silently leaves in place -- common/spl/spl_mmc.c's __weak
board_spl_mmc_get_uboot_raw_sector(), which just returns raw_sect
unchanged -- still lets SPL locate *a* U-Boot proper image; it is just
the wrong one (SPL copy 0 instead of the real payload after it), which
is a boot-time brick, not a build-time failure.

The break: commit 62f7a94602 ("Replace TARGET namespace and cleanup
properly", 2026-02-13) renamed the SoCFPGA family Kconfig symbols from
CONFIG_TARGET_SOCFPGA_* to CONFIG_ARCH_SOCFPGA_* across the tree, but
missed the #if guard added ten weeks earlier by commit 1cf1b504f4
("arch: arm: mach-socfpga: Adjust a raw sectors for MMC loading of
U-Boot from SPL", 2025-12-11), which still reads:

#if (defined(CONFIG_TARGET_SOCFPGA_ARRIA10) || \
defined(CONFIG_TARGET_SOCFPGA_GEN5)) && defined(CONFIG_XPL_BUILD)

CONFIG_TARGET_SOCFPGA_ARRIA10 and CONFIG_TARGET_SOCFPGA_GEN5 are gone
from Kconfig -- these two lines are the only remaining references to
either symbol in the whole tree -- so the #if is permanently false and
board_spl_mmc_get_uboot_raw_sector() never compiles for any Gen5 or
Arria10 target. Confirmed still present, byte-for-byte, at this
repo's mainline-board-support mirror of u-boot/u-boot.git HEAD
5c215cb75c3723cbf77c36cbac3e60b001721c79 (2026-07-27); the wider plan
research (docs/uboot-mainline-port.md section 3.1 row 2) independently
found it unfixed at v2026.10-rc1 too. One-line-per-symbol rename fix:
s/CONFIG_TARGET_SOCFPGA_/CONFIG_ARCH_SOCFPGA_/ on both lines.

Verified by rebuild against u-boot-2026.07 (socfpga_de10_nano_defconfig
+ CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION_TYPE=y, this repo's
arm-buildroot-linux-gnueabihf- cross toolchain), task U2a:

* Without this patch: `nm spl/u-boot-spl` still lists the symbol --
the __weak fallback chain (spl_mmc_get_uboot_raw_sector :322 ->
board_spl_mmc_get_uboot_raw_sector :316 ->
arch_spl_mmc_get_uboot_raw_sector :310, all three __weak, all in
common/spl/spl_mmc.c) means the *name* is never absent -- but as
type W (weak). objdump shows
board_spl_mmc_get_uboot_raw_sector as a single `b.w` tail-branch
into arch_spl_mmc_get_uboot_raw_sector, whose body is `mov r0, r1;
bx lr`: raw_sect passes straight through unmodified and no +0x200
is ever added.
* With this patch: `nm spl/u-boot-spl` lists it as type T (this
board.c definition, strong, overriding the weak default) --
alongside the still-weak `W spl_mmc_get_uboot_raw_sector`, so an
assertion must match `T board_spl_mmc_get_uboot_raw_sector`
exactly, never a bare grep for "raw_sector" -- and
objdump of the function is `add.w r0, r1, #0x200; bx lr` --
(CONFIG_SPL_PAD_TO * 4) / 512 = (0x10000 * 4) / 512 = 0x200 with
this defconfig, matching boot-chain.md section 2.1 exactly.

Provenance
----------
Origin: No existing upstream commit -- this is a follow-up fix to
a gap left by 62f7a94602 and 1cf1b504f4 (both cited above
and unmodified by this patch). Written against
u-boot-2026.07 (dl/uboot/u-boot-2026.07.tar.bz2) for this
task; not derived from any other tree.
Author: Michael C. Ferguson <michael.christopher.ferguson@gmail.com>
Copyright: The surrounding file (arch/arm/mach-socfpga/board.c) is
upstream U-Boot, SPDX GPL-2.0+; this hunk carries no new
copyright claim, it corrects two macro names.
Upstream status: Not in mainline. Two U-Boot commits away from being a
trivial fix (see "The break" above) that a socfpga
maintainer could merge in one line-for-line review. To be
submitted upstream (U7): a submission is drafted under
docs/verification/uboot-upstream/ by task U7-prep but, per
owner decision 4, deliberately NOT sent to any mailing
list -- U7 itself is "send, on the owner's go only".
Disposition: Bug fix, brick-class (docs/uboot-mainline-port.md section
3.1 row 2: "With #1 applied, raw_sect is 0 and the SPL
would load from the *start* of the 0xA2 partition -- i.e.
SPL copy 0"). Required for this repo's mainline U-Boot
build artifact (task U2g) to boot at all; carried until
upstream picks it up.

Signed-off-by: Michael C. Ferguson <michael.christopher.ferguson@gmail.com>
---
arch/arm/mach-socfpga/board.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-socfpga/board.c b/arch/arm/mach-socfpga/board.c
index 4d7f0b9..fd7f15b 100644
--- a/arch/arm/mach-socfpga/board.c
+++ b/arch/arm/mach-socfpga/board.c
@@ -211,8 +211,8 @@ void lmb_arch_add_memory(void)
}
#endif

-#if (defined(CONFIG_TARGET_SOCFPGA_ARRIA10) || \
- defined(CONFIG_TARGET_SOCFPGA_GEN5)) && defined(CONFIG_XPL_BUILD)
+#if (defined(CONFIG_ARCH_SOCFPGA_ARRIA10) || \
+ defined(CONFIG_ARCH_SOCFPGA_GEN5)) && defined(CONFIG_XPL_BUILD)
unsigned long board_spl_mmc_get_uboot_raw_sector(struct mmc *mmc,
unsigned long raw_sect)
{
Loading
Loading