diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2a37c03..04a3df4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,26 +1,20 @@ ################################################################################ # -# release.yml — tag-triggered release workflow + build provenance (TASKS.md -# P4.4, PLAN.md §9 "Build", docs/downloader-contract.md P0.6). +# release.yml — tag-triggered release: build, verify, package, attest, publish. # -# Builds via the same recipe as build.yml (.github/actions/buildroot-build), -# then assembles a GitHub Release for three downstream consumers: a human -# downloading assets from the Release page, the on-device Downloader_MiSTer -# (which never talks to GitHub Releases directly), and a human opting into -# the PREEMPT_RT beta kernel. See docs/ci.md#release-consumers. +# Four jobs: +# build `make` (the shared buildroot-build action) + ci-tests, then +# scripts/mk-release.sh turns output/ into a verified dist/ +# (stock archive fetched + verified, release_YYYYMMDD.7z +# assembled and round-tripped under the on-device 7za, +# SHA256SUMS), then scripts/mk-sdcard.sh adds the installer +# card image. Every step is a script you can run locally. +# build-azcopy the optional azcopy download, built as a separate config +# publish attest provenance, create a DRAFT GitHub Release +# dependency-graph submit the SBOM to GitHub's dependency graph # -# Rebuilds from the tagged commit and re-runs the full non-hardware -# verification suite rather than trusting build.yml's run or artifacts. -# See docs/ci.md#rebuild-not-adopt. -# -# Fetches (never vendors — G6) the stock uboot.img / files/linux/ payload -# from a commit-pinned third-party archive, verified before extraction. -# See docs/ci.md#stock-payload-sourcing, #stock-payload-verification, and -# the open provenance question at #stock-payload-open-decision. -# -# Tag convention (`v*`) is unratified, and the release filename / db.json -# version is deliberately decoupled from the git tag. See -# docs/ci.md#tag-convention and docs/ci.md#mister-version-coupling. +# Rationale, measurements and incident history: docs/ci.md. The STOCK_* pins +# below are Renovate-managed (docs/renovate.md). # ################################################################################ @@ -30,68 +24,33 @@ on: push: tags: - 'v*' - # Manual dispatch builds ONLY the opt-in full sdcard variant (tagged pushes - # always build the minimal one). MUST be dispatched against a tag ref, not - # a branch — the publish job is guarded to tag refs regardless, but a - # branch dispatch still burns a full build for nothing. See - # docs/ci.md#manual-full-sdcard-dispatch. + # Manual dispatch builds ONLY the opt-in full sdcard variant; dispatch it + # against a TAG ref (the publish job is guarded to tag refs regardless). workflow_dispatch: inputs: build_full_sdcard: - description: 'Also build + publish sdcard-full.img.xz (bundles _Console cores). Off by default; the minimal sdcard.img.xz is always built.' + description: 'Also build + publish sdcard-full.img.xz (bundles _Console cores). Off by default; the minimal sdcard.img.xz is always built on a tag push.' type: boolean default: false -# A re-pushed (corrected) tag should supersede an in-flight run for the same -# tag; distinct tags already get distinct concurrency groups via github.ref, -# so this never cancels a run for a DIFFERENT release. concurrency: group: release-${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true -# Least privilege at the workflow level; the `publish` job elevates its own -# permissions block (contents: write, id-token: write, attestations: write) -# only for the steps that actually need them (attest + create the release). permissions: contents: read jobs: - # ============================================================================ - # build — produces every release asset and the pinned-7za-verified archive. - # Runs after the kernel matrix so it can merge each leg's module tree into - # linux.img. No `container:` — see docs/ci.md#no-container-disk-reclaim. - # ============================================================================ build: name: Build image + assemble release_YYYYMMDD.7z runs-on: ubuntu-26.04 - - # Cold build measured at 3h19m (run 29300460591) plus stock-archive fetch, - # archive assembly, and the sdcard steps' installer build + kernel relink - # (the relink REUSES output/, no second from-scratch build — do not - # reintroduce one; an earlier from-scratch design overran the runner's - # hard 360-min cap and the release never published). See - # docs/ci.md#sdcard-timing-6h-cap. + # Cold build ~3h20m plus packaging and the sdcard installer relink; the + # runner's hard cap is 360. See docs/ci.md#sdcard-timing-6h-cap. timeout-minutes: 355 - outputs: - release_date: ${{ steps.mister_version.outputs.release_date }} - + release_date: ${{ steps.release.outputs.release_date }} env: DEBIAN_FRONTEND: noninteractive - - # --- Pinned stock reference archive -------------------------------- - # The ONLY source in this pipeline for uboot.img and the files/linux/ - # payload we do not vendor (G6). See docs/ci.md#stock-payload-sourcing. - # - # release_20260907 is committed upstream as TWO split 7z volumes - # (.7z.001 + .7z.002 -- consecutive byte slices of one archive, not - # two archives). STOCK_RELEASE_URL is therefore a whitespace-separated - # list, in volume order; `fetch-stock` downloads each and concatenates - # them into the single stock_release.7z every later step verifies, so - # MD5/SHA-256/SIZE below are those of the JOINED file -- the same bytes - # Distribution_MiSTer's own joiner mirrors as linux_release_20260907.7z - # and the only form the on-device 7za ever sees. Verified byte-identical - # to that mirror: docs/verification/stock-release-20260907.md §1/§6. STOCK_RELEASE_URL: >- https://raw.githubusercontent.com/MiSTer-devel/SD-Installer-Win64_MiSTer/76fd6f4ced6350b0ad56a7013b41526f47e3a2fb/release_20260907.7z.001 https://raw.githubusercontent.com/MiSTer-devel/SD-Installer-Win64_MiSTer/76fd6f4ced6350b0ad56a7013b41526f47e3a2fb/release_20260907.7z.002 @@ -111,379 +70,63 @@ jobs: STOCK_7ZA_GZ_URL: https://github.com/MiSTer-devel/SD-Installer-Win64_MiSTer/raw/master/7za.gz STOCK_7ZA_GZ_MD5: ed1ad5185fbede55cd7fd506b3c6c699 STOCK_7ZA_GZ_SIZE: "465600" - steps: - name: Checkout uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - # MUST run before the build: post-build.sh reads MISTER_VERSION to bake - # /MiSTer.version into the image (ADR 0018). Derived from the tagged - # commit's UTC date, not SOURCE_DATE_EPOCH, so distinct tags produce - # distinct versions. See docs/ci.md#mister-version-coupling. + # /MiSTer.version is YYMMDD of the tagged commit (UTC); post-build.sh + # bakes $MISTER_VERSION into the image and mk-release.sh reads it back. - name: Derive release version (YYMMDD) from the tagged commit run: | set -eu v="${MISTER_VERSION:-$(TZ=UTC git show -s --format=%cd --date=format-local:%y%m%d HEAD)}" - case "$v" in - [0-9][0-9][0-9][0-9][0-9][0-9]) : ;; - *) echo "::error::derived MISTER_VERSION '$v' is not 6 digits YYMMDD" >&2; exit 1 ;; - esac + case "$v" in [0-9][0-9][0-9][0-9][0-9][0-9]) ;; *) echo "::error::derived MISTER_VERSION '$v' is not 6 digits YYMMDD" >&2; exit 1 ;; esac echo "MISTER_VERSION=$v" >> "$GITHUB_ENV" echo "Release version (YYMMDD) = $v -> /MiSTer.version, release_20${v}.7z, db.json" - - # Shared recipe (disk reclaim, caches, apt, defconfig, `make all`). - # p7zip-full here is a DIFFERENT 7za than the pinned ARM dynamic one - # fetched below — this one only creates/inspects the archive on the - # x86_64 runner. See docs/ci.md#stock-payload-verification. - name: Build the image uses: ./.github/actions/buildroot-build with: - # extra-apt-packages: p7zip-full assembles release_YYYYMMDD.7z; the - # rest are host-only tools scripts/mk-sdcard.sh needs (genimage, - # mtools, dosfstools, xz-utils, jq) — none enter the shipped rootfs. - # See docs/ci.md#release-apt-packages. + # p7zip-full packs the 7z; the rest are host tools mk-sdcard.sh needs. extra-apt-packages: p7zip-full genimage mtools dosfstools xz-utils jq run-legal-info: "true" - - # Re-runs build.yml's non-hardware parity suite (ci-tests.sh) and ABI/ - # SONAME checker (check-abi.sh) against THIS EXACT rootfs — the tagged - # commit may not be one build.yml ever validated. See - # docs/ci.md#rebuild-not-adopt. skip-qemu-system matches build.yml; - # see .github/actions/verify-image for the full rationale. - name: Run parity suite + ABI/SONAME checker uses: ./.github/actions/verify-image with: skip-qemu-system: "true" - ########################################################################## - # Assemble dist/. See docs/ci.md#dist-layout for the asset contract. - ########################################################################## - - - name: Stage dist/ and copy the two image assets - run: | - set -eu - mkdir -p dist - cp -f output/images/linux.img dist/linux.img - cp -f output/images/zImage_dtb dist/zImage_dtb - - - name: Copy buildroot.config and linux.config - run: | - set -eu - # nullglob keeps a zero-match glob's count truthful for the guard - # below. See - # docs/ci.md#dist-layout. - shopt -s nullglob - cp -f output/.config dist/buildroot.config - trees=(output/build/linux-[0-9]*/) - if [ "${#trees[@]}" -ne 1 ] || [ ! -d "${trees[0]}" ]; then - echo "::error::expected exactly one kernel tree at output/build/linux-[0-9]*/ but found ${#trees[@]} -- cannot stage linux.config (zero: the build produced no kernel tree; more than one: a stale sibling from a version bump, e.g. linux-headers-*/linux-firmware-* are excluded by the glob but another linux-/ would not be)" >&2 - exit 1 - fi - cp -f "${trees[0]}.config" dist/linux.config - - # patches-only: ship our applied patches + the SBOM (manifest.csv with - # each package's pinned upstream URL+hash, license texts, buildroot.config) - # but NOT the upstream *.tar.* source archives. Each archive is the - # freely-available, hash-pinned upstream manifest.csv points to and this - # public repo rebuilds byte-for-byte, so bundling ~1.4 GiB of it into - # every release (591 MiB of that the linux-firmware blob alone) only - # duplicated what the repo + upstream already provide and left ~664 MiB - # under GitHub's 2 GiB per-asset cap as firmware grows each release. The - # complete corresponding source is this repo at the tag + that referenced - # upstream; the release notes below carry the GPLv2 written offer. - # host-sources/ (the build-time toolchain) is dropped in every mode - # regardless. See docs/ci.md#legal-info-2gib-cap. - - name: Archive legal-info as legal-info.tar.gz - run: | - set -eu - # shellcheck source=scripts/ci-lib.sh - source scripts/ci-lib.sh - if [ ! -d output/legal-info ]; then - echo "::error::output/legal-info does not exist -- did 'make legal-info' run?" >&2 - exit 1 - fi - ci_lib_package_legal_info output dist/legal-info.tar.gz patches-only - - # GitHub's hard per-asset ceiling is 2 GiB. Fail here, with a clear - # message, rather than at the upload. - ci_lib_check_release_asset_size dist/legal-info.tar.gz legal-info.tar.gz \ - ". The package set has outgrown a single source bundle -- split it (e.g. sources/ as its own asset, or publish sources to a separate host and reference them from manifest.csv)." - - # The per-variant release extras, straight from the leg artifacts (the - # legs already applied the uniqueness guards and the legal-info size - # guard). Copied by glob so a future matrix entry needs no edit here; - # each glob must match at least once — zero matches means the download - # step above silently changed shape, and cp's own failure catches that. - # Since ADR 0030 Phase C the RT kernel is package/linux-rt inside this - # same build: its zImage_dtb-rt and linux-rt.config land in output/images/ - # and its module tree is in linux.img by construction. Its licence texts - # and patches are part of the ONE legal-info bundle above (the package - # is in output/legal-info/manifest.csv), so there is no legal-info-rt. - - name: Stage the RT kernel variant's assets into dist/ - run: | - set -eu - for f in output/images/zImage_dtb-rt output/images/linux-rt.config; do - [ -f "$f" ] || { echo "::error::$f is missing -- package/linux-rt did not produce it (BR2_PACKAGE_LINUX_RT unset?)" >&2; exit 1; } - done - cp -f output/images/zImage_dtb-rt output/images/linux-rt.config dist/ - ls -la dist/ - - ########################################################################## - # /MiSTer.version -> RELEASE_DATE. LOAD-BEARING: db.json's linux.version - # must equal, byte-for-byte, this baked value (docs/downloader-contract.md - # §3/§12) — see docs/ci.md#mister-version-coupling. - ########################################################################## - - name: Extract and validate /MiSTer.version from the built image - id: mister_version - run: | - set -eu - workdir=$(mktemp -d ./mister-version.XXXXXX) - debugfs -R "rdump /MiSTer.version ${workdir}" output/images/linux.img >/dev/null 2>"${workdir}.debugfs.log" || true - verfile="${workdir}/MiSTer.version" - if [ ! -f "$verfile" ]; then - echo "::error::debugfs could not extract /MiSTer.version from output/images/linux.img" >&2 - sed 's/^/ /' "${workdir}.debugfs.log" >&2 || true - exit 1 - fi - n=$(wc -c < "$verfile") - if [ "$n" -ne 6 ]; then - echo "::error::/MiSTer.version is ${n} bytes, expected exactly 6 (docs/downloader-contract.md §3/§12)" >&2 - exit 1 - fi - last_byte_hex=$(tail -c1 "$verfile" | od -An -tx1 | tr -d ' ') - if [ "$last_byte_hex" = "0a" ]; then - echo "::error::/MiSTer.version ends in a newline -- this permanently breaks the Downloader's version-equality check (docs/downloader-contract.md §3)" >&2 - exit 1 - fi - yymmdd=$(cat "$verfile") - case "$yymmdd" in - [0-9][0-9][0-9][0-9][0-9][0-9]) : ;; - *) - echo "::error::/MiSTer.version content '$yymmdd' is not 6 ASCII digits" >&2 - exit 1 - ;; - esac - # Verify the build honored the MISTER_VERSION override (ADR 0018): - # /MiSTer.version must equal what we asked post-build.sh to bake. - if [ "$yymmdd" != "${MISTER_VERSION:-}" ]; then - echo "::error::built /MiSTer.version '$yymmdd' != requested MISTER_VERSION '${MISTER_VERSION:-}' -- post-build.sh did not honor the override" >&2 - exit 1 - fi - # Assumption, flagged: century is hardcoded "20" (valid until the - # year 2100). /MiSTer.version itself only ever carries YYMMDD, same - # as stock's own convention (e.g. "250402" for release_20250402.7z). - release_date="20${yymmdd}" - echo "release_date=${release_date}" >> "$GITHUB_OUTPUT" - echo "Resolved /MiSTer.version='${yymmdd}' -> RELEASE_DATE=${release_date}" - - ########################################################################## - # Fetch + verify the pinned stock archive — MUST fully verify (MD5+size, - # then a separate 7z internal-CRC test) before extracting a byte. These - # four steps call scripts/verify-stock-payload.sh (runnable standalone); - # the STOCK_* pins live only in this job's env: block above. See - # docs/ci.md#stock-payload-verification. - ########################################################################## - - name: Fetch pinned stock release archive - run: scripts/verify-stock-payload.sh fetch-stock stock_release.7z - - - name: Verify stock archive integrity (MD5, SHA-256, size) - run: scripts/verify-stock-payload.sh verify-stock stock_release.7z - - - name: Extract files/linux/* from the verified stock archive - run: scripts/verify-stock-payload.sh extract-stock stock_release.7z stock-extract - - - name: Re-verify stock uboot.img and updateboot hashes (defense in depth) - run: scripts/verify-stock-payload.sh verify-uboot stock-extract - - ########################################################################## - # Overlay our freshly built linux.img/zImage_dtb onto the verified stock - # files/linux/ tree — mirrors the real Downloader's own on-device rsync. - # See docs/ci.md#stock-payload-verification. - ########################################################################## - - name: Assemble release tree (files/linux/*) + - name: Stage, package and verify the release assets (scripts/mk-release.sh) + id: release run: | set -eu - mkdir -p release-stage - cp -a stock-extract/files release-stage/files - cp -f output/images/linux.img release-stage/files/linux/linux.img - cp -f output/images/zImage_dtb release-stage/files/linux/zImage_dtb - # ADD (not overlay) the statically-linked 7-Zip 26.03 that - # package/7zip builds. The stock archive has NO 7za of any kind -- - # which is exactly why a stock device downloads p7zip 16.02 (2016) - # from SD-Installer-Win64_MiSTer the first time it needs to extract - # an update. The Downloader's own flash-phase rsync has no --delete - # but DOES overwrite files present in the source, so shipping it here - # replaces whatever /media/fat/linux/7za a device already has, on - # every update. ADR 0023, docs/downloader-contract.md §4. - # - # This does NOT relax the hard constraint that our archive must stay - # extractable by that old pinned binary: the very update that - # installs our 7za is itself unpacked by whatever 7za was already - # there. The qemu-arm round-trip step further down still runs the - # 2016 binary against this archive, and must keep passing. - cp -f output/images/7za release-stage/files/linux/7za - echo "release-stage/files/linux/ contents:" - find release-stage/files/linux -maxdepth 1 -printf '%f\n' | sort + scripts/mk-release.sh output dist + echo "release_date=$(cat dist/RELEASE_DATE)" >> "$GITHUB_OUTPUT" - - name: Create release_${RELEASE_DATE}.7z (plain solid LZMA2, no BCJ2) - env: - RELEASE_DATE: ${{ steps.mister_version.outputs.release_date }} - run: | - set -eu - # Plain solid LZMA2, not stock's BCJ2 (a Windows-7-Zip-GUI artifact, - # irrelevant here) — see docs/ci.md#stock-payload-verification. - # - # -mf=off IS LOAD-BEARING, added 2026-07-27 with ADR 0023's files/linux/7za. - # 7-Zip auto-detects an executable filter from the CONTENT it is given, so - # the moment the payload gained an ARM ELF the encoding silently changed: - # reproduced with this exact command, `Method = LZMA2 ARM` and Blocks = 2, - # where the same command over an ELF-free payload gives plain - # `Method = LZMA2`, Blocks = 1. That contradicts the "no BCJ/BCJ2/ARM - # filter" guarantee docs/downloader-contract.md §4 makes, which the - # pinned-2016-extractor constraint rests on. The ARM filter happens to be - # readable by p7zip 16.02 (checked: `t` exit 0, extraction byte-identical), - # so this is determinism and keeping a documented invariant TRUE, not a bug - # fix — but the point of that invariant is precisely not to gamble on which - # filters a decade-old extractor implements, and auto-detection is exactly a - # gamble: a future payload member could trip a filter 16.02 lacks. The - # roundtrip step below would catch that after the fact; -mf=off means it - # cannot arise. - # - # NOT passing -snl, deliberately: upstream 7-Zip DEREFERENCES symlinks when - # writing unless told otherwise (p7zip 16.02 stored them as links by - # default — the defaults differ). release-stage/files/ holds no symlinks - # today so there is nothing to preserve, and enabling it would add an - # untested archive shape. If a symlink is ever added to the payload, revisit - # this line: it would otherwise be silently flattened into a copy. - ( cd release-stage && 7z a -mx=9 -m0=lzma2 -mf=off -ms=on "../dist/release_${RELEASE_DATE}.7z" files/ ) - echo "Created dist/release_${RELEASE_DATE}.7z" - - ########################################################################## - # Verify with the EXACT pinned ARM 7za the real Downloader uses, - # under qemu-arm — not a modern host 7z. See - # docs/ci.md#stock-payload-verification. - ########################################################################## - - name: Fetch and verify the pinned ARM 7za - run: scripts/verify-stock-payload.sh fetch-7za 7za - - # The pinned 7za is dynamically linked (glibc), not static -- qemu-arm - # needs -L pointed at an ARM sysroot to resolve its loader/shared libs. - # output/target (this job's own build) already has a matching glibc - # sysroot, so it's reused here rather than installing armhf multiarch - # packages on the runner. See docs/ci.md#stock-payload-verification. - - name: Verify our archive extracts under the pinned ARM 7za (qemu-arm) - env: - RELEASE_DATE: ${{ steps.mister_version.outputs.release_date }} - run: scripts/verify-stock-payload.sh roundtrip "dist/release_${RELEASE_DATE}.7z" ./7za downloader-extract output/target - - - name: Re-verify uboot.img/updateboot after the ARM-7za round trip - run: scripts/verify-stock-payload.sh verify-uboot downloader-extract --hash-only - - - name: Verify archive layout matches the assembled contract tree - env: - RELEASE_DATE: ${{ steps.mister_version.outputs.release_date }} - run: scripts/verify-stock-payload.sh verify-layout "dist/release_${RELEASE_DATE}.7z" release-stage - - # Generated ONCE, covering every asset (main seven + kernel-variant - # extras) — no publish-side append step anymore. See - # docs/ci.md#old-two-image-design-retired. - - name: Generate SHA256SUMS - env: - RELEASE_DATE: ${{ steps.mister_version.outputs.release_date }} - run: | - set -eu - ( cd dist && sha256sum "release_${RELEASE_DATE}.7z" linux.img zImage_dtb buildroot.config linux.config legal-info.tar.gz \ - zImage_dtb-* linux-*.config > SHA256SUMS ) - cat dist/SHA256SUMS - - ########################################################################## - # sdcard installer image (TASKS.md P5.3, ADR 0017 §4 amended by ADR 0020). - # Standalone flashable assets — never in release_YYYYMMDD.7z, never - # referenced by db.json. See docs/ci.md#sdcard-contract. - ########################################################################## - - # Reuses the stock archive already verified above by seeding - # fetch-sdcard-payload.sh's own cache (it re-checks size+MD5+SHA-256, so - # this is a hand-off of verified bytes, not a bypass). Skipped only on - # an opt-in full-sdcard dispatch, where it would be pure redundancy. See - # docs/ci.md#sdcard-contract and docs/ci.md#manual-full-sdcard-dispatch. - - name: Build sdcard.img.xz (minimal installer image) - if: ${{ !inputs.build_full_sdcard }} - env: - STAGE_DIR: ${{ github.workspace }}/output-sdcard-stage - run: | - set -eu - mkdir -p "$STAGE_DIR/.fetch-cache" - cp -f stock_release.7z "$STAGE_DIR/.fetch-cache/stock_release.7z" - scripts/mk-sdcard.sh - ls -la output/images/sdcard.img output/images/sdcard.img.xz - - # Static, offline contract check (partition table, uboot.img head, FAT32 - # payload inventory vs docs/verification/sdcard-payload.md). STOCK_UBOOT_* - # come from the job env for the default uboot head compare. Same skip - # condition as the build step it verifies. - - name: Verify sdcard.img (scripts/check-sdcard.sh) - if: ${{ !inputs.build_full_sdcard }} - run: scripts/check-sdcard.sh output/images/sdcard.img - - # Opt-in only: the full variant bundles _Console cores (much larger, needs - # the GitHub Contents API). Runs only on a workflow_dispatch with the input - # set. Reuses the same warm STAGE_DIR (stock archive + installer builds - # already there), just adds the cores; fetch-sdcard-payload.sh reconciles. - - name: Build + verify sdcard-full.img.xz (opt-in _Console cores) - if: ${{ inputs.build_full_sdcard }} + # Reuses the stock archive mk-release.sh already verified by seeding + # mk-sdcard.sh's fetch cache (it re-checks size/MD5/SHA-256 itself). + - name: Build + verify the sdcard installer image env: STAGE_DIR: ${{ github.workspace }}/output-sdcard-stage - SDCARD_CORES: "1" + SDCARD_CORES: ${{ inputs.build_full_sdcard && '1' || '0' }} GITHUB_TOKEN: ${{ github.token }} run: | set -eu mkdir -p "$STAGE_DIR/.fetch-cache" - cp -f stock_release.7z "$STAGE_DIR/.fetch-cache/stock_release.7z" + cp -f release-work/stock_release.7z "$STAGE_DIR/.fetch-cache/stock_release.7z" scripts/mk-sdcard.sh - scripts/check-sdcard.sh output/images/sdcard-full.img - ls -la output/images/sdcard-full.img output/images/sdcard-full.img.xz - - # Into dist/ so the existing "Upload release asset bundle" step carries them - # to the publish job. sdcard-full.img.xz is only present when the opt-in - # step above ran. - - name: Stage sdcard image(s) into dist/ - run: | - set -eu - # Stage whichever variant(s) this run actually built. A tag push builds - # the minimal image; an opt-in full dispatch (which SKIPS the minimal - # build above, since the tag already carries it) builds only the full - # one. The publish job's `gh release upload --clobber` then adds/refreshes - # exactly what landed in dist/, leaving any already-attached asset intact. - if [ -f output/images/sdcard.img.xz ]; then - cp -f output/images/sdcard.img.xz dist/sdcard.img.xz - fi - if [ -f output/images/sdcard-full.img.xz ]; then - cp -f output/images/sdcard-full.img.xz dist/sdcard-full.img.xz - fi + img=sdcard.img; [ "$SDCARD_CORES" = 1 ] && img=sdcard-full.img + scripts/check-sdcard.sh "output/images/$img" + cp -f "output/images/$img.xz" dist/ ls -la dist/ - # --- Release overview on the run's Summary page ------------------------ - # The tag, the internal version, the archive + image sizes, the full - # SHA256SUMS, and -- most importantly -- the draft/db.json coupling a - # human needs to understand before clicking Publish. - name: Release overview (job summary) env: - RELEASE_DATE: ${{ steps.mister_version.outputs.release_date }} + RELEASE_DATE: ${{ steps.release.outputs.release_date }} TAG: ${{ github.ref_name }} run: | set -u - # shellcheck source=scripts/ci-lib.sh - # Explicit fallback if ci-lib.sh is missing, rather than a silent - # abort. See docs/ci.md#ci-lib-source-fallback. - source scripts/ci-lib.sh || { - echo "::warning::scripts/ci-lib.sh not found -- size facts below will read n/a" >&2 - ci_lib_sz() { echo "n/a"; } - } - arc="dist/release_${RELEASE_DATE}.7z" - assets=$(find dist -maxdepth 1 -type f | wc -l) + source scripts/ci-lib.sh { echo "## 🚀 Release build summary" echo "" @@ -491,42 +134,27 @@ jobs: echo "|---|---|" echo "| Tag | \`${TAG}\` |" echo "| Internal version (\`/MiSTer.version\`) | \`${RELEASE_DATE}\` |" - echo "| Archive | \`release_${RELEASE_DATE}.7z\` ($(ci_lib_sz "$arc")) |" + echo "| Archive | \`release_${RELEASE_DATE}.7z\` ($(ci_lib_sz "dist/release_${RELEASE_DATE}.7z")) |" echo "| linux.img | $(ci_lib_sz dist/linux.img) |" - echo "| zImage_dtb | $(ci_lib_sz dist/zImage_dtb) |" - echo "| Assets staged | ${assets} |" - echo "" - echo "**Verified before packaging:** stock archive MD5/SHA-256/size + 7z CRC · \`uboot.img\`/\`updateboot\` byte-identical to stock (before *and* after the archive round-trip) · our \`.7z\` extracts under the pinned ARM \`7za\` (qemu-arm) · archive member list matches docs/downloader-contract.md · rootfs passes the non-hardware parity suite (\`ci-tests.sh\`) and the ABI/SONAME checker (section above)." + echo "| zImage_dtb / zImage_dtb-rt | $(ci_lib_sz dist/zImage_dtb) / $(ci_lib_sz dist/zImage_dtb-rt) |" + echo "| Assets staged | $(find dist -maxdepth 1 -type f | wc -l) |" echo "" - echo "**Next:** the \`publish\` job attests build provenance and creates a **DRAFT** GitHub Release. A draft is not public and does **not** trigger db.json publication (\`publish-db.yml\` gates on a *published, non-draft* release) until a human clicks **Publish**." + echo "**Verified before packaging:** stock archive MD5/SHA-256/size + 7z CRC · \`uboot.img\`/\`updateboot\` byte-identical to stock before *and* after the round trip · our \`.7z\` extracts under the pinned ARM \`7za\` (qemu-arm) · archive member list matches the assembled tree · rootfs passes \`ci-tests.sh\` and the ABI/SONAME checker." echo "" - echo "
SHA256SUMS" + echo "**Next:** \`publish\` attests provenance and creates a **DRAFT** release; db.json is published only after a human clicks **Publish** (\`publish-db.yml\` gates on a non-draft release)." echo "" - echo '```' - cat dist/SHA256SUMS 2>/dev/null || echo "(SHA256SUMS not found)" - echo '```' - echo "" - echo "
" + echo "
SHA256SUMS"; echo ""; echo '```'; cat dist/SHA256SUMS; echo '```'; echo ""; echo "
" } >> "$GITHUB_STEP_SUMMARY" - # A second, differently-timed disk/cache sample than the build action's - # own (action.yml, if: always()) — taken AFTER the stock-archive - # re-fetch, archive assembly, and sdcard builds, which are what's most - # likely to exhaust the runner's disk. Not a duplicate; do not remove. - # See docs/ci.md#disk-usage-double-sample. - name: Report disk & cache usage if: always() run: | echo "--- disk free ---"; df -h . echo "--- dl/ ---"; du -sh dl 2>/dev/null || true - echo "--- output/host ---"; du -sh output/host 2>/dev/null || true - echo "--- output (total) ---"; du -sh output 2>/dev/null || true + echo "--- output ---"; du -sh output 2>/dev/null || true echo "--- ccache ---"; du -sh "$GITHUB_WORKSPACE/.ccache" 2>/dev/null || true echo "--- dist/ ---"; ls -la dist/ 2>/dev/null || true - # sha-named, not ref_name: upload-artifact REJECTS '/' in names, and a - # branch dispatch's ref_name can contain one. See - # docs/ci.md#artifact-naming-slash-trap. - name: Upload release asset bundle uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: @@ -535,34 +163,6 @@ jobs: if-no-files-found: error retention-days: 14 - # ============================================================================ - # build-azcopy — builds the optional azcopy download (docs/azcopy.md). - # - # A SEPARATE JOB, AND THAT IS THE WHOLE POINT. azcopy is deliberately NOT in - # the image (BR2_PACKAGE_AZCOPY is unset; 39 MiB, see docs/azcopy.md §1), so - # the one thing this must never do is leak into linux.img. Building it in the - # `build` job's output/ would do exactly that, and not hypothetically: - # scripts/mk-sdcard.sh REGENERATES linux.img from that same output/ after the - # image has already been staged ("snapshots that image BEFORE its own step-2 - # relink regenerates it" -- its own header). Anything sitting in output/target - # at that moment ships. A different runner with a different checkout cannot - # make that mistake, at any point in the step order, no matter what is added - # to `build` later. - # - # It also costs nothing on the critical path. `build` is budgeted at 355 min - # against a hard 360-min cap and has already overrun it once (see that job's - # timeout comment); this runs concurrently instead of eating that ~36 min of - # slack. The trade is one extra runner: measured ~4-5 min for host-go plus - # ~12 s for azcopy itself, on top of the target toolchain. - # - # STATIC (CGO_ENABLED=0), for the same reason package/7zip ships a static - # /media/fat/linux/7za: a downloaded binary OUTLIVES the rootfs that put it - # there. It has to survive a rollback to an older linux.img, or to a stock - # image whose glibc is years behind ours. A dynamic build dies at exec with - # GLIBC_2.xx-not-found; static removes the failure mode. Costs the pure-Go - # DNS resolver instead of glibc NSS, which is not a difference anyone will - # notice here. - # ============================================================================ build-azcopy: name: Build azcopy (optional download) runs-on: ubuntu-26.04 @@ -680,156 +280,65 @@ jobs: # ============================================================================ publish: name: Attest provenance + create GitHub Release - # build-azcopy is a hard dependency, not a soft one: a release that - # silently dropped the optional azcopy download because that job failed - # would look identical to a release that never carried it. Fail the - # publish instead. See docs/ci.md#azcopy-release-asset. needs: [build, build-azcopy] runs-on: ubuntu-26.04 - - # Only ever create a Release for a TAG. On a tag push this is always true, so - # existing behaviour is unchanged; it exists so a workflow_dispatch on a - # NON-tag ref (used to build the opt-in full sdcard variant) still runs the - # `build` job's build+verify but does NOT mint a branch-named release here. if: startsWith(github.ref, 'refs/tags/') - permissions: contents: write # create the Release and upload its assets id-token: write # attest-build-provenance's OIDC token exchange attestations: write # publish the attestation to this repo - steps: - # ONE bundle now — build stages everything (main seven, variant extras, - # sdcard images, SHA256SUMS) — nothing to merge/append here anymore. - # See docs/ci.md#old-two-image-design-retired. - name: Download release asset bundle uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: release-dist-${{ github.sha }} path: dist - # Into the same dist/ the main bundle landed in, so the assets array - # below stays one flat list. Separate artifact because it comes from a - # separate job -- see build-azcopy's header for why that job is separate. - name: Download azcopy asset uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: azcopy-dist-${{ github.sha }} path: dist - - name: List downloaded assets - run: ls -la dist/ - - # Re-derives the variant registry from dist/SHA256SUMS (this checkout- - # less job derives the variant list from SHA256SUMS — see - # docs/ci.md#variants) and asserts BY NAME that all three files exist - # for EVERY variant. A glob-and-count check could only ever notice the - # ALL-missing case; this backstops the attestation step below, which - # cannot police itself either. See docs/ci.md#attest-provenance-scope. - - name: Verify every kernel variant's assets survived the artifact round trip + # The asset list is fixed; a file that did not survive the artifact + # round trip fails here rather than producing a release with a hole. + - name: Check every asset survived the artifact round trip + env: + RELEASE_DATE: ${{ needs.build.outputs.release_date }} run: | - set -euo pipefail - if [ ! -f dist/SHA256SUMS ]; then - echo "::error::dist/SHA256SUMS is missing -- the build job's 'Generate SHA256SUMS' step should have produced it; refusing to publish a release whose asset manifest did not survive the release-dist-${{ github.sha }} round trip" >&2 - exit 1 - fi - # `hash name` (two spaces; a leading '*' if it was ever hashed in - # binary mode) -- take field 2, keep only the zImage_dtb- - # rows, and strip the prefix to leave the variant names. - mapfile -t variants < <(awk '{ sub(/^\*/, "", $2); print $2 }' dist/SHA256SUMS | sed -n 's/^zImage_dtb-\(.*\)$/\1/p' | sort -u) - if [ "${#variants[@]}" -eq 0 ]; then - echo "::error::dist/SHA256SUMS records no zImage_dtb- entries (expected at least \`rt\`) -- package/linux-rt is part of every build that reaches this job, so zero variants is a bug, not a valid empty state" >&2 - exit 1 - fi - echo "kernel variants recorded in SHA256SUMS: ${variants[*]}" - missing=0 - : > "$RUNNER_TEMP/variant-assets.txt" - for v in "${variants[@]}"; do - for f in "dist/zImage_dtb-$v" "dist/linux-$v.config"; do - if [ ! -f "$f" ]; then - echo "::error::kernel-variant asset $f is missing from dist/ although SHA256SUMS records variant \`$v\` -- it went missing between the build job staging it and this job downloading release-dist-${{ github.sha }}" >&2 - missing=1 - continue - fi - printf '%s\n' "$f" >> "$RUNNER_TEMP/variant-assets.txt" - done + set -eu + ls -la dist/ + for f in "release_${RELEASE_DATE}.7z" linux.img zImage_dtb zImage_dtb-rt SHA256SUMS buildroot.config linux.config linux-rt.config legal-info.tar.gz; do + [ -f "dist/$f" ] || { echo "::error::dist/$f is missing -- it went missing between the build job and this one" >&2; exit 1; } done - if [ "$missing" -ne 0 ]; then - echo "::error::refusing to publish a release missing one or more kernel-variant assets" >&2 - exit 1 - fi - cat "$RUNNER_TEMP/variant-assets.txt" + ( cd dist && sha256sum -c SHA256SUMS ) + azc=(dist/azcopy-*-armv7.xz dist/azcopy-*-armv7.xz.sha256) + [ "${#azc[@]}" -eq 2 ] && [ -f "${azc[0]}" ] && [ -f "${azc[1]}" ] || { echo "::error::expected dist/azcopy--armv7.xz and its .sha256 from the build-azcopy job" >&2; exit 1; } - # Attests only the shipped binaries; the zImage_dtb-* glob covers - # whatever the kernel-variant matrix built. Do NOT rely on this action - # to catch a missing variant asset itself — the verify step above is - # what does that. See docs/ci.md#attest-provenance-scope. - name: Attest build provenance for the image assets uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2 with: subject-path: | dist/linux.img dist/zImage_dtb - dist/zImage_dtb-* + dist/zImage_dtb-rt - # Created as a DRAFT, deliberately: publish-db.yml only fires on a - # published (non-draft) release — this is the human-approval gate - # between "CI built an image" and "every subscribed MiSTer is offered - # it." See docs/ci.md#release-draft-gate. - name: Create draft GitHub Release env: GITHUB_TOKEN: ${{ github.token }} - # GH_REPO required: no checkout here, and gh ignores - # $GITHUB_REPOSITORY — without it every `gh release` call dies at - # repo-resolution and a green ~9h build silently produces NO - # release. Inherited from origin/master's publish job; fixed here. - # See docs/ci.md#gh-repo-bug. GH_REPO: ${{ github.repository }} RELEASE_DATE: ${{ needs.build.outputs.release_date }} TAG: ${{ github.ref_name }} run: | set -eu - # sdcard*.img.xz — standalone assets, never in the 7z, never in - # db.json (ADR 0017 §4 / ADR 0020). See docs/ci.md#sdcard-contract. assets=( dist/"release_${RELEASE_DATE}.7z" - dist/linux.img - dist/zImage_dtb - dist/SHA256SUMS - dist/buildroot.config - dist/linux.config + dist/linux.img dist/zImage_dtb dist/zImage_dtb-rt + dist/SHA256SUMS dist/buildroot.config dist/linux.config dist/linux-rt.config dist/legal-info.tar.gz ) - # Per-variant assets are read back from - # $RUNNER_TEMP/variant-assets.txt (written by the verify step - # above), not named or globbed here — a glob-and-count could only - # ever notice the ALL-missing case. See - # docs/ci.md#release-assets-array. - mapfile -t variant_assets < "$RUNNER_TEMP/variant-assets.txt" - if [ "${#variant_assets[@]}" -eq 0 ]; then - echo "::error::no kernel-variant assets listed in \$RUNNER_TEMP/variant-assets.txt (expected at least zImage_dtb-rt, linux-rt.config) -- the 'Verify every kernel variant's assets survived the artifact round trip' step should have written them and failed the job if it could not; refusing to publish a release missing its kernel-variant assets" >&2 - exit 1 - fi - assets+=("${variant_assets[@]}") - [ -f dist/sdcard.img.xz ] && assets+=(dist/sdcard.img.xz) - [ -f dist/sdcard-full.img.xz ] && assets+=(dist/sdcard-full.img.xz) - # azcopy: globbed rather than named because the filename carries the - # package's version (azcopy--armv7.xz), and this job has no - # checkout to read AZCOPY_VERSION from. Unlike the sdcard lines above - # this is NOT optional -- build-azcopy is in `needs:` and uploads with - # if-no-files-found: error, so an empty glob here means something - # upstream lied and the release must not go out half-assembled. - mapfile -t azcopy_assets < <(ls dist/azcopy-*-armv7.xz dist/azcopy-*-armv7.xz.sha256 2>/dev/null || true) - if [ "${#azcopy_assets[@]}" -ne 2 ]; then - echo "::error::expected dist/azcopy--armv7.xz and its .sha256 from the build-azcopy job, found ${#azcopy_assets[@]} file(s); refusing to publish a release missing the optional azcopy download" >&2 - exit 1 - fi - assets+=("${azcopy_assets[@]}") - # Added unconditionally (package/linux-rt is in every build, so at least one - # variant is guaranteed — the verify step above already failed the - # job otherwise). The release-notes prose below is a hand-edit per - # variant, same as mk-sdcard.sh's single bonus-kernel slot — see - # docs/ci.md#variants for the full accounting. + for f in dist/sdcard.img.xz dist/sdcard-full.img.xz; do [ -f "$f" ] && assets+=("$f"); done + assets+=(dist/azcopy-*-armv7.xz dist/azcopy-*-armv7.xz.sha256) notes="Automated release build. Internal linux version (baked \`/MiSTer.version\`): ${RELEASE_DATE}. See SHA256SUMS for asset hashes and the attached build-provenance attestation (verify with \`gh attestation verify --owner ${{ github.repository_owner }}\`). The \`sdcard*.img.xz\` assets are standalone flashable installer images (ADR 0020); they are NOT part of release_${RELEASE_DATE}.7z and are not referenced by db.json. **Complete corresponding source (GPL/LGPL):** every binary here is built from free/open-source software with Buildroot. \`legal-info.tar.gz\` (the main image AND the RT kernel, which is a package of the same build) ships the SBOM — \`manifest.csv\` listing each package's exact version, license, and pinned upstream source URL+hash — plus every license text, all local patches we apply, and \`buildroot.config\`. The upstream source archives themselves are deliberately NOT bundled: they are the freely-available, hash-pinned upstreams \`manifest.csv\` points to, and re-bundling ~1.4 GiB of them (591 MiB of that the linux-firmware blob alone) into every release only duplicated what upstream + this repo already provide. The complete corresponding source for every GPL/LGPL component is (a) the upstream archives at the exact versions/URLs in \`manifest.csv\`, byte-verifiable against their recorded hashes, plus (b) this repository at tag \`${{ github.ref_name }}\`, which carries the full Buildroot configuration and all applied patches and rebuilds the identical images with \`make\`. **Written offer:** for at least three years from this release, we will additionally provide a complete machine-readable copy of the corresponding source for any component on request — open an issue at https://github.com/${{ github.repository }}. @@ -844,11 +353,7 @@ jobs: if gh release view "$TAG" >/dev/null 2>&1; then gh release upload "$TAG" --clobber "${assets[@]}" else - gh release create "$TAG" \ - --draft \ - --title "$TAG" \ - --notes "$notes" \ - "${assets[@]}" + gh release create "$TAG" --draft --title "$TAG" --notes "$notes" "${assets[@]}" fi - name: Publish summary (job summary) @@ -859,25 +364,11 @@ jobs: { echo "## 📦 Draft release created" echo "" - echo "Draft GitHub Release **${TAG}** created (internal version \`${RELEASE_DATE}\`); build provenance attested for \`linux.img\`, \`zImage_dtb\` and \`zImage_dtb-rt\`. The two \`*-rt\` assets are the PREEMPT_RT beta kernel (ADR 0021 as amended — its MODULES ride inside the one \`linux.img\`) — separate downloads, never in the 7z, never in db.json." + echo "Draft GitHub Release **${TAG}** (internal version \`${RELEASE_DATE}\`); provenance attested for \`linux.img\`, \`zImage_dtb\` and \`zImage_dtb-rt\`." echo "" - echo "> ⚠️ **This is a draft.** It is not public, and db.json is **not** published while it stays a draft." - echo "> Clicking **Publish release** — whether as a full release *or* a pre-release — fires \`publish-db.yml\`, which regenerates and publishes db.json to opted-in devices. **The pre-release flag does not prevent that** (the guard there checks draft, not pre-release). For a smoke test, leave it a draft and delete it when done." + echo "> ⚠️ **This is a draft.** Publishing it — as a release *or* a pre-release — fires \`publish-db.yml\`, which publishes db.json to opted-in devices. For a smoke test, leave it a draft and delete it when done." } >> "$GITHUB_STEP_SUMMARY" - # ============================================================================ - # dependency-graph — re-publishes the release's SBOM through GitHub's - # dependency submission API so it lands in /network/dependencies (and, for - # anything the advisory database can match, Dependabot). The SBOM itself is - # not regenerated here: the input is the manifest.csv inside the - # legal-info*.tar.gz assets the release actually shipped, so the graph and - # the tarball cannot disagree. - # - # RELEASE ONLY, deliberately — build.yml never submits. A dependency graph - # is a claim about what is published, and build.yml's manifest-only SBOM - # describes an image that is distributed to nobody. See - # docs/ci.md#dependency-graph-submission. - # ============================================================================ dependency-graph: name: Publish SBOM to the dependency graph # publish, not build: nothing should appear in the graph for a release @@ -914,65 +405,20 @@ jobs: name: release-dist-${{ github.sha }} path: dist - # ci_lib_package_legal_info archives with `-C legal-info`, - # so every bundle carries its manifest at exactly legal-info/manifest.csv. - # Each is unpacked under the Buildroot output dir it came from - # (legal-info.tar.gz -> output/; since ADR 0030 Phase C there is no per-variant bundle) and - # named that way in the snapshot, which is both stable across releases - # and self-describing in the graph UI. - # - # The variant glob is safe to trust here in a way it would not be in - # `publish`: `needs: publish` means that job's by-name check for - # legal-info-.tar.gz has already passed for EVERY variant in - # SHA256SUMS. Only the main bundle is re-asserted by name below. - - name: Extract each shipped legal-info bundle's manifest.csv + # One bundle since ADR 0030: legal-info.tar.gz covers the image, the RT + # kernel and the stage-1 packages (all packages of the one build). The + # snapshot names its manifest output/legal-info/manifest.csv, stable across + # releases and self-describing in the graph UI. + - name: Extract the SBOM manifest from legal-info.tar.gz id: manifests run: | set -euo pipefail - if [ ! -f dist/legal-info.tar.gz ]; then - echo "::error::dist/legal-info.tar.gz is missing from the release-dist bundle -- the main image's SBOM is what this job exists to publish; refusing to submit a dependency snapshot without it" >&2 - exit 1 - fi - shopt -s nullglob - : > "$RUNNER_TEMP/manifest-args.txt" - for tgz in dist/legal-info.tar.gz dist/legal-info-*.tar.gz; do - base=$(basename "$tgz" .tar.gz) - case "$base" in - legal-info) outdir=output ;; - legal-info-*) outdir="output-${base#legal-info-}" ;; - *) - echo "::error::unexpected legal-info bundle name '$tgz'" >&2 - exit 1 - ;; - esac - dest="$RUNNER_TEMP/sbom/$outdir" - mkdir -p "$dest" - # One member, named explicitly: a bundle that somehow lost its - # manifest must fail here, not silently contribute nothing. - if ! tar -xzf "$tgz" -C "$dest" legal-info/manifest.csv; then - echo "::error::$tgz does not contain legal-info/manifest.csv -- ci_lib_package_legal_info's archive layout changed, or the bundle is truncated" >&2 - exit 1 - fi - printf -- '--manifest\n%s\n' \ - "${outdir}/legal-info/manifest.csv=${dest}/legal-info/manifest.csv" \ - >> "$RUNNER_TEMP/manifest-args.txt" - echo "staged ${tgz} -> ${outdir}/legal-info/manifest.csv ($(wc -l < "${dest}/legal-info/manifest.csv") lines)" - done + [ -f dist/legal-info.tar.gz ] || { echo "::error::dist/legal-info.tar.gz is missing from the release-dist bundle" >&2; exit 1; } + mkdir -p "$RUNNER_TEMP/sbom/output" + tar -xzf dist/legal-info.tar.gz -C "$RUNNER_TEMP/sbom/output" legal-info/manifest.csv + printf -- '--manifest\n%s\n' "output/legal-info/manifest.csv=$RUNNER_TEMP/sbom/output/legal-info/manifest.csv" > "$RUNNER_TEMP/manifest-args.txt" + echo "manifest: $(wc -l < "$RUNNER_TEMP/sbom/output/legal-info/manifest.csv") lines (covers the image, the RT kernel and the stage-1 packages)" - # THE load-bearing step. GitHub only updates a repository's dependency - # results from a snapshot whose `ref` is the DEFAULT BRANCH: a - # refs/tags/... ref is accepted with a 201 and then quietly ignored - # ("The snapshot was accepted, but it is not for the default branch"), - # which is exactly the shape of failure this whole job was added to fix. - # Since a release tag is cut from master, the tagged commit IS on the - # default branch and submitting under refs/heads/ is accurate, - # not a fiction -- but that has to be CHECKED, not assumed, so a tag cut - # from an unmerged branch never claims to describe master. - # - # compare/...: `identical` = the tag is the branch tip, - # `behind` = the tagged commit is an ancestor of it. `ahead`/`diverged` - # mean the commit is not on the default branch at all. - # See docs/ci.md#dependency-graph-default-branch. - name: Resolve the ref to submit the snapshot under id: ref env: diff --git a/.gitignore b/.gitignore index 5035050..314dad3 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ work/ output*/ dl/ dist/ +release-work/ *.img *.7z venv/ diff --git a/docs/ci.md b/docs/ci.md index a47a002..238e318 100644 --- a/docs/ci.md +++ b/docs/ci.md @@ -33,7 +33,7 @@ Nine workflows, two composite actions, one Buildroot recipe. A build is |---|---|---| | `build.yml` | push to master, PRs | `gate` (skip doc-only changes) → `lint-config` (kernel patch headers, `scripts/check-defconfigs.sh`) → `build` (the action below, then `scripts/ci-tests.sh` via `verify-image`) → `status` | | `lint.yml` | push, PRs | actionlint on the workflows, shellcheck on every script and on the composite actions' `run:` bodies | -| `release.yml` | `v*` tags | the same build, then: stage assets, fetch + verify the pinned stock archive, assemble `release_YYYYMMDD.7z` and round-trip it under the pinned ARM `7za`, build `sdcard.img.xz`, publish a draft release with provenance, submit the SBOM to the dependency graph | +| `release.yml` | `v*` tags | the same build, then `scripts/mk-release.sh` (stage assets, fetch + verify the pinned stock archive, assemble `release_YYYYMMDD.7z` and round-trip it under the pinned ARM `7za`, `SHA256SUMS`) and `scripts/mk-sdcard.sh`; then a draft release with provenance and the SBOM to the dependency graph. Runs locally: `MISTER_VERSION=… scripts/mk-release.sh` with the `STOCK_*` pins in the environment | | `reproducibility.yml` | manual | two independent builds of one commit, hashes compared | | `renovate-hash-sync.yml` | Renovate PRs | refresh the companion hash of whatever pin the PR bumped (each case is one `scripts/hash-sync-*.sh`) | | `renovate-validate.yml` | push, PRs | `renovate.json` validates | diff --git a/docs/de25-nano-tasks.md b/docs/de25-nano-tasks.md index ec24255..20808ed 100644 --- a/docs/de25-nano-tasks.md +++ b/docs/de25-nano-tasks.md @@ -402,7 +402,11 @@ Remaining, in unblock order: pointed to from the DE25 series; the aarch64 leg's `symlink` case is the acceptance test — it is the ONLY place 0031-on-7.x is executed rather than compiled.~~ **DONE 2026-09-06:** beta-local copy, DE25 series relinked, aarch64 leg 8/8, arm compile clean on the RT config. - Remaining: the first `ln -s` on an RT-booted DE10 (32-bit 7.x is still compile-only). + ~~Remaining: the first `ln -s` on an RT-booted DE10 (32-bit 7.x is still compile-only).~~ + **2026-09-11:** executed as 32-bit ARM by `scripts/test-initramfs.sh --kernel rt` (7.2.4, + `symlink`/`exfat`/`fsck-request` pass; the 6.18-form patch on 7.2.4 reproduces the Oops), + after the rig, still on a pre-rewrite RT 7.2.3, panicked on the Arcade Organizer's first + symlink (ADR 0002 §8b). Hardware boot of the fixed RT kernel still owed. 3. **Owner decisions still open**: a Renovate manager for the DE25 kernel pin; upstream submission of 0101/0102; patch 0002 (audio). Hardware is expected after the owner's vacation (ordered on return). diff --git a/docs/decisions/0002-initramfs.md b/docs/decisions/0002-initramfs.md index 2c74811..8b9f1e7 100644 --- a/docs/decisions/0002-initramfs.md +++ b/docs/decisions/0002-initramfs.md @@ -372,8 +372,19 @@ device directly and never sees a dirty bdev buffer), and does the `valid_size` / `zeroed_size` / `i_size` bookkeeping the write path would have done. Applies at `-F0` to pristine 7.2.3; compiles for arm with the RT `.config` and for arm64 with the DE25's; the aarch64 leg is **8/8** with the `symlink` case's full assertion set (hot+cold round-trip, -`DT_LNK`, the create+unlink cluster-leak tripwire via `statvfs`, host-side fsck-clean). What -remains unexecuted is 0031 on 32-bit 7.x — the RT kernel on a real board. +`DT_LNK`, the create+unlink cluster-leak tripwire via `statvfs`, host-side fsck-clean). + +**2026-09-11 — the 32-bit gap closed, the hard way first.** The maintainer's rig was still on +an RT 7.2.3 kernel built 2026-09-05, before the rewrite shipped there; `update_all.sh`'s +Arcade Organizer created its first `.mra` symlink on `/media/fat` and the board Oopsed +exactly as above (`PC is at 0x0`, `LR is at page_symlink+0x90`, from `exfat_symlink`; captured +by netconsole) and, with `CONFIG_PANIC_ON_OOPS=y` + `panic=15`, rebooted 17 s later. The +same day `scripts/test-initramfs.sh --kernel rt` was added: the DE10 leg built at the RT pin +(`BR2_PACKAGE_LINUX_RT_VERSION`) with `linux-patches-beta/0031`, on `qemu-system-arm`, so the +rewrite is executed as 32-bit ARM. Result at 7.2.4: `symlink`, `exfat`, `fsck-request` pass; +the negative control (the 6.18-form patch on the same 7.2.4 source) reproduces the rig's +Oops in QEMU, so the leg detects the bug it exists for. `ci-tests.sh` runs it after the +DE10 leg. What remains is the ordinary hardware claim: a board boot of the fixed RT kernel. ## 8c. Amendment 2026-09-11 — stage 1 becomes a package of the main build (ADR 0030) diff --git a/docs/rt-beta-kernel.md b/docs/rt-beta-kernel.md index a4db4cf..a6d6f6e 100644 --- a/docs/rt-beta-kernel.md +++ b/docs/rt-beta-kernel.md @@ -249,7 +249,7 @@ card, and nothing on the card referenced it), and deliberately NOT inside | **Module-tree merge into the one linux.img** | ✅ **green** — the row's "first green run pending" was overtaken by CI run 29758320422 (2026-07-20, rc4: `build-kernel` + `build` both green, so the merge assert ran). Re-verified locally on rc5 (2026-07-28): after `make rt`, a `make all` produced `output/target/usr/lib/modules/` holding exactly `6.18.40` and `7.2.0-rc5` — two trees, no stale third — and `linux.img` passed every `check-linux-img.sh` assertion (512 MiB, pinned UUID/hash-seed, the 14-feature stock-derived set, ADR 0015 ssh-key checks) | | **RT kernel boots on the DE10-Nano** | ⚠️ **NOT on the currently pinned 7.2 — re-opened 2026-08-17 by the rc7 → 7.2 bump.** ✅ **CONFIRMED 2026-07-20 on 7.2-rc4**, which booted and ran MiSTer on real hardware. That retired the single biggest open risk on the variant, and it is how the `0037` DualSense regression was caught: booting far enough to use a controller is what exposed the shifted PS5 button map (§7 item 3). ✅ **RE-CONFIRMED 2026-08-14 on 7.2-rc7** — the Wave-1 hardware pass ran on a `7.2.0-rc7 SMP PREEMPT_RT` kernel carrying `0043`, and the doorbell nodes enumerated and delivered events (that pass is also where H-1 and H-2 were found). Boot is a **per-version claim** and every bump re-opens it, which is exactly the state this row is in now: 7.2 final is patch-verified (**40/40** at `-F0`), DTS-verified, and **built on the whole 40-entry series** (`make rt` green from clean, 2026-08-17 — see the build rows above), but it has **not been booted**. Everything that can be checked without hardware has been checked and passed; none of it is a boot. This ✅ covers rc4 and rc7 and nothing else. It also does **not** cover `0044`, `0045`, `0046` or the re-added `0038`–`0042`: none were in the series when the rc7 kernel was built, and all six have since been built but never booted — §2, §8, §9 | | **vsync/IRQ-40 latency under RT threaded IRQs** | ❌ **unproven** (the point of the exercise) — boot and general operation are confirmed, but the latency measurement that motivates RT has not been taken | -| **Patch 0031 (exFAT Samsung symlinks) on 7.x** | ✅ **FIXED 2026-09-06 — after being found BROKEN the same day**, not by this variant but by the DE25's aarch64 initramfs QEMU leg (`scripts/test-initramfs.sh --board de25nano`), the first thing ever to EXECUTE 0031 on a 7.x kernel: `exfat_symlink()` → `page_symlink()` → `a_ops->write_begin` is NULL on 7.x exFAT (iomap; no `write_begin`/`write_end`) → Oops, `pc: 0x0`, on the first symlink created. `linux-patches-beta/0031` WAS a symlink to the shared 6.18 file, so this kernel had the same crash on any `ln -s` on `/media/fat` (reading existing links was fine). The "applies at -F0" and "compiles" rows above were true and insufficient. Now a **beta-local re-anchored copy** (the fifth): `exfat_symlink_write_target()` allocates clusters via 7.x's `exfat_map_cluster()`, writes the sectors through buffer heads, `sync_blockdev_range()`s them (iomap reads go straight to the device), and does the `valid_size`/`zeroed_size`/`i_size` bookkeeping; the DE25 series links to this copy. Verified: applies at `-F0` to pristine 7.2.3 (12/12 hunks), **compiles for arm with this variant's own `output-rt` `.config`** (`fs/exfat/`, zero warnings), and the aarch64 leg's `symlink` case passes — hot+cold round-trip, `DT_LNK`, the create+unlink cluster-leak tripwire, fsck-clean (ADR 0002 §8b). Still not executed on 32-bit ARM: the DE10 leg boots 6.18 only, so the first `ln -s` on an RT-booted board is the remaining proof. | +| **Patch 0031 (exFAT Samsung symlinks) on 7.x** | ✅ **FIXED 2026-09-06 — after being found BROKEN the same day**, not by this variant but by the DE25's aarch64 initramfs QEMU leg (`scripts/test-initramfs.sh --board de25nano`), the first thing ever to EXECUTE 0031 on a 7.x kernel: `exfat_symlink()` → `page_symlink()` → `a_ops->write_begin` is NULL on 7.x exFAT (iomap; no `write_begin`/`write_end`) → Oops, `pc: 0x0`, on the first symlink created. `linux-patches-beta/0031` WAS a symlink to the shared 6.18 file, so this kernel had the same crash on any `ln -s` on `/media/fat` (reading existing links was fine). The "applies at -F0" and "compiles" rows above were true and insufficient. Now a **beta-local re-anchored copy** (the fifth): `exfat_symlink_write_target()` allocates clusters via 7.x's `exfat_map_cluster()`, writes the sectors through buffer heads, `sync_blockdev_range()`s them (iomap reads go straight to the device), and does the `valid_size`/`zeroed_size`/`i_size` bookkeeping; the DE25 series links to this copy. Verified: applies at `-F0` to pristine 7.2.3 (12/12 hunks), **compiles for arm with this variant's own `output-rt` `.config`** (`fs/exfat/`, zero warnings), and the aarch64 leg's `symlink` case passes — hot+cold round-trip, `DT_LNK`, the create+unlink cluster-leak tripwire, fsck-clean (ADR 0002 §8b). Still not executed on 32-bit ARM: the DE10 leg boots 6.18 only, so the first `ln -s` on an RT-booted board is the remaining proof. **2026-09-11: executed as 32-bit ARM** — the rig (still on a pre-rewrite RT 7.2.3 from 2026-09-05) panicked on `update_all.sh`'s first Arcade Organizer symlink (netconsole: `PC is at 0x0`, `LR is at page_symlink+0x90`; `CONFIG_PANIC_ON_OOPS=y` + `panic=15` rebooted it), and `scripts/test-initramfs.sh --kernel rt` now builds the DE10 QEMU leg at the RT pin with `linux-patches-beta/0031`: 7.2.4 passes `symlink`/`exfat`/`fsck-request`; the 6.18-form patch on the same source reproduces the Oops. Only a hardware boot of the fixed kernel remains. | | `rtw88_8814au` firmware (`rtw88/rtw8814a_fw.bin`) present | ✅ ships via `BR2_PACKAGE_LINUX_FIRMWARE_RTL_RTW88` | ## 7. What is left diff --git a/mk-release.log b/mk-release.log new file mode 100644 index 0000000..bee077c --- /dev/null +++ b/mk-release.log @@ -0,0 +1,130 @@ + +==> mk-release: reading /MiSTer.version from /mnt/source/Buildroot_MiSTer-vanilla/output/images/linux.img + /MiSTer.version=260904 -> RELEASE_DATE=20260904 + +==> mk-release: staging image assets into /mnt/source/Buildroot_MiSTer-vanilla/dist +legal-info.tar.gz: 6923165 bytes (6 MiB) + +==> mk-release: fetching + verifying the pinned stock release + % Total % Received % Xferd Average Speed Time Time Time Current + Dload Upload Total Spent Left Speed + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00:01 0 100 80.00M 100 80.00M 0 0 56.07M 0 00:01 00:01 56.10M 100 80.00M 100 80.00M 0 0 56.07M 0 00:01 00:01 56.10M 100 80.00M 100 80.00M 0 0 56.07M 0 00:01 00:01 56.10M +fetch-stock: fetched volume 1: https://raw.githubusercontent.com/MiSTer-devel/SD-Installer-Win64_MiSTer/76fd6f4ced6350b0ad56a7013b41526f47e3a2fb/release_20260907.7z.001 + % Total % Received % Xferd Average Speed Time Time Time Current + Dload Upload Total Spent Left Speed + 0 0 0 0 0 0 0 0 0 100 32.47M 100 32.47M 0 0 35.98M 0 0 100 32.47M 100 32.47M 0 0 35.97M 0 0 100 32.47M 100 32.47M 0 0 35.97M 0 0 +fetch-stock: fetched volume 2: https://raw.githubusercontent.com/MiSTer-devel/SD-Installer-Win64_MiSTer/76fd6f4ced6350b0ad56a7013b41526f47e3a2fb/release_20260907.7z.002 +fetch-stock: 2 volume(s) joined -> /mnt/source/Buildroot_MiSTer-vanilla/release-work/stock_release.7z +verify-stock: /mnt/source/Buildroot_MiSTer-vanilla/release-work/stock_release.7z verified -- size/MD5/SHA-256/internal-CRC all match. + +7-Zip 26.00 (x64) : Copyright (c) 1999-2026 Igor Pavlov : 2026-02-12 + 64-bit locale=C.UTF-8 Threads:32 OPEN_MAX:1048576, ASM + +Scanning the drive for archives: +1 file, 117936766 bytes (113 MiB) + +Extracting archive: /mnt/source/Buildroot_MiSTer-vanilla/release-work/stock_release.7z +-- +Path = /mnt/source/Buildroot_MiSTer-vanilla/release-work/stock_release.7z +Type = 7z +Physical Size = 117936766 +Headers Size = 765 +Method = LZMA2:26 LZMA:20 BCJ2 +Solid = + +Blocks = 2 + +Everything is Ok + +Folders: 3 +Files: 13 +Size: 402464951 +Compressed: 117936766 +extract-stock: extracted files/linux/* from /mnt/source/Buildroot_MiSTer-vanilla/release-work/stock_release.7z -> /mnt/source/Buildroot_MiSTer-vanilla/release-work/stock-extract +verify-uboot: uboot.img and updateboot confirmed byte-identical to stock. + +==> mk-release: assembling files/linux and packing release_20260904.7z + 7za + MidiLink.INI + _samba.sh + _user-startup.sh + _wpa_supplicant.conf + gamecontrollerdb + linux + linux.img + mt32-rom-data + ppp_options + soundfonts + u-boot.txt_example + uboot.img + updateboot + zImage_dtb + wrote /mnt/source/Buildroot_MiSTer-vanilla/dist/release_20260904.7z (84632824 bytes) + +==> mk-release: round-tripping the archive under the pinned ARM 7za (qemu-arm) + % Total % Received % Xferd Average Speed Time Time Time Current + Dload Upload Total Spent Left Speed + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 100 454.6k 100 454.6k 0 0 578.2k 0 0 100 454.6k 100 454.6k 0 0 578.1k 0 0 100 454.6k 100 454.6k 0 0 578.0k 0 0 +fetch-7za: pinned ARM 7za fetched and verified -> /mnt/source/Buildroot_MiSTer-vanilla/release-work/7za + +7-Zip (a) [32] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21 +p7zip Version 16.02 (locale=C.UTF-8,Utf16=on,HugeFiles=on,32 bits,32 CPUs LE) + +Scanning the drive for archives: +1 file, 84632824 bytes (81 MiB) + +Testing archive: /mnt/source/Buildroot_MiSTer-vanilla/dist/release_20260904.7z +-- +Path = /mnt/source/Buildroot_MiSTer-vanilla/dist/release_20260904.7z +Type = 7z +Physical Size = 84632824 +Headers Size = 607 +Method = LZMA2:28 +Solid = + +Blocks = 1 + +Everything is Ok + +Folders: 5 +Files: 14 +Size: 550398955 +Compressed: 84632824 + +7-Zip (a) [32] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21 +p7zip Version 16.02 (locale=C.UTF-8,Utf16=on,HugeFiles=on,32 bits,32 CPUs LE) + +Scanning the drive for archives: +1 file, 84632824 bytes (81 MiB) + +Extracting archive: /mnt/source/Buildroot_MiSTer-vanilla/dist/release_20260904.7z +-- +Path = /mnt/source/Buildroot_MiSTer-vanilla/dist/release_20260904.7z +Type = 7z +Physical Size = 84632824 +Headers Size = 607 +Method = LZMA2:28 +Solid = + +Blocks = 1 + +Everything is Ok + +Folders: 3 +Files: 14 +Size: 550398955 +Compressed: 84632824 +roundtrip: pinned ARM 7za: both 't' and 'x -y ... files/linux/*' succeeded. +verify-uboot: uboot.img/updateboot survive our archive's create+pinned-7za-extract round trip unchanged. +verify-layout: archive layout matches docs/downloader-contract.md / docs/reference-materials.md. + +==> mk-release: SHA256SUMS +cbbc891b430fec1aa4e926f6cedfd129c66e934d8c312afd482f6fbb9c26a0e1 release_20260904.7z +b10f7c33466af0f20b17b5d47062686a5f7775c4aa4053b51a4957fdcc4639ef linux.img +012a1dc459a6b3cbd3ef038abee2121eecd3b43fcc81e7c6454aaf22419d5eef zImage_dtb +d266dd5111edc581b1352c1b07847145c38686e896fadbcf898696c4eef9dd99 zImage_dtb-rt +b5e9cc0cb85f6250eaf0e150b975fab5b1466c31f27f59fe917d9c86996d9ebc buildroot.config +7c0909f0e02084951e9347f3589fe9e2228d54833681d885d24c464d8f6a8a6b linux.config +907b63c0adb62aecf3344a12958a5b45caf8e56b78498eba180d6f0991bb5a48 linux-rt.config +b6da2bf61e26858209e5936ea419bbcebe941dd4a604957c0a2f623a439c30a0 legal-info.tar.gz + +==> mk-release: done: /mnt/source/Buildroot_MiSTer-vanilla/dist ready; stock archive kept at /mnt/source/Buildroot_MiSTer-vanilla/release-work/stock_release.7z for mk-sdcard.sh +exit=0 diff --git a/scripts/ci-tests.sh b/scripts/ci-tests.sh index 1c6be23..7ae655c 100755 --- a/scripts/ci-tests.sh +++ b/scripts/ci-tests.sh @@ -300,6 +300,30 @@ else fi fi +# The same /init on the DE10's RT kernel series (7.2.y): the three cases that +# exercise the exfat driver, because 7.x exfat is iomap-based and board patch +# 0031 (Samsung-format symlinks, ADR 0019) is a separate re-anchored copy +# there (linux-patches-beta/). Its only other executions are aarch64 (the +# DE25 leg); the DE10-Nano runs it as 32-bit ARM, and the first field `ln -s` +# on an RT-booted board Oopsed (2026-09-11) on the pre-rewrite copy. Gated +# like the DE10 leg; a second multi_v7 kernel build, cached under +# work/test-initramfs-rt*. +if [ "${CI_TESTS_SKIP_QEMU_SYSTEM:-0}" = "1" ]; then + skip "test-initramfs.sh --kernel rt (32-bit QEMU boot test on the RT kernel, exfat cases)" "CI_TESTS_SKIP_QEMU_SYSTEM=1" +elif ! have qemu-system-arm; then + skip "test-initramfs.sh --kernel rt (32-bit QEMU boot test on the RT kernel, exfat cases)" "qemu-system-arm not found on PATH" +elif ! grep -q '^BR2_PACKAGE_LINUX_RT=y$' "$ROOT/configs/mister_de10nano_defconfig"; then + skip "test-initramfs.sh --kernel rt (32-bit QEMU boot test on the RT kernel, exfat cases)" "BR2_PACKAGE_LINUX_RT is not enabled in configs/mister_de10nano_defconfig" +else + printf -- '--- test-initramfs.sh --kernel rt: exfat fsck-request symlink ---\n' + printf ' (builds/reuses a second QEMU test kernel at the RT pin -- can take several minutes)\n' + if "$ROOT/scripts/test-initramfs.sh" --kernel rt exfat fsck-request symlink; then + pass "test-initramfs.sh --kernel rt (32-bit QEMU boot test on the RT kernel, 3 exfat cases)" + else + fail "test-initramfs.sh --kernel rt (32-bit QEMU boot test on the RT kernel, 3 exfat cases)" "one or more of the 3 cases failed -- see output above" + fi +fi + # The DE25-Nano's stage 1: the SAME package built for aarch64 by the DE25 # configuration -- once its stack enables BR2_LINUX_KERNEL_EXT_MISTER_INITRAMFS # (ADR 0029 D11 keeps that off until a board has booted). Gated on the cpio diff --git a/scripts/mk-release.sh b/scripts/mk-release.sh new file mode 100755 index 0000000..832684a --- /dev/null +++ b/scripts/mk-release.sh @@ -0,0 +1,99 @@ +#!/usr/bin/env bash +# mk-release.sh -- turn a finished `make` into a verified release asset set. +# +# usage: scripts/mk-release.sh [] [] (defaults: output, dist) +# +# release.yml's build job is this script plus the sdcard image. It is a plain +# sequence, and every step is one you can run at a terminal: +# +# 1. read /MiSTer.version out of the built linux.img and check the contract +# (6 ASCII digits, no newline, equal to $MISTER_VERSION when that is set); +# RELEASE_DATE = 20, written to /RELEASE_DATE for the caller +# 2. stage the image assets: linux.img, zImage_dtb, zImage_dtb-rt, +# buildroot.config, linux.config, linux-rt.config, legal-info.tar.gz +# 3. fetch, verify and extract the pinned STOCK release archive +# (scripts/verify-stock-payload.sh; the STOCK_* pins come from the +# environment -- release.yml's env block, or your shell) +# 4. assemble files/linux/ = stock's tree with OUR linux.img, zImage_dtb and +# 7za dropped in, and pack release_.7z the way the Downloader expects +# 5. prove the archive round-trips under the pinned ARM 7za (qemu-arm) and +# that its member list matches the assembled tree +# 6. SHA256SUMS over everything above +# +# Needs on the host: 7z (p7zip-full), qemu-arm, debugfs (e2fsprogs), curl. +set -euo pipefail + +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +out=${1:-$ROOT/output} +dist=${2:-$ROOT/dist} +work=$ROOT/release-work +# shellcheck source=scripts/ci-lib.sh +source "$ROOT/scripts/ci-lib.sh" +say() { printf '\n==> mk-release: %s\n' "$*"; } +die() { echo "mk-release: FATAL: $*" >&2; exit 1; } + +for t in 7z qemu-arm debugfs curl; do command -v "$t" >/dev/null 2>&1 || die "'$t' not found in PATH"; done +for f in images/linux.img images/zImage_dtb images/zImage_dtb-rt images/linux-rt.config images/7za .config; do + [ -f "$out/$f" ] || die "$out/$f is missing -- run 'make' first (zImage_dtb-rt / linux-rt.config come from package/linux-rt)" +done +[ -d "$out/legal-info" ] || die "$out/legal-info is missing -- run 'make legal-info' first" + +# --- 1. /MiSTer.version -------------------------------------------------------- +say "reading /MiSTer.version from $out/images/linux.img" +rm -rf "$work"; mkdir -p "$work/ver" "$dist" +debugfs -R "rdump /MiSTer.version $work/ver" "$out/images/linux.img" >/dev/null 2>"$work/debugfs.log" || true +verfile="$work/ver/MiSTer.version" +[ -f "$verfile" ] || { sed 's/^/ /' "$work/debugfs.log" >&2; die "debugfs could not extract /MiSTer.version"; } +[ "$(wc -c < "$verfile")" -eq 6 ] || die "/MiSTer.version is $(wc -c < "$verfile") bytes, expected exactly 6 (docs/downloader-contract.md §3)" +[ "$(tail -c1 "$verfile" | od -An -tx1 | tr -d ' ')" != "0a" ] || die "/MiSTer.version ends in a newline -- that breaks the Downloader's version-equality check" +yymmdd=$(cat "$verfile") +case "$yymmdd" in [0-9][0-9][0-9][0-9][0-9][0-9]) ;; *) die "/MiSTer.version '$yymmdd' is not 6 ASCII digits" ;; esac +if [ -n "${MISTER_VERSION:-}" ] && [ "$yymmdd" != "$MISTER_VERSION" ]; then + die "built /MiSTer.version '$yymmdd' != requested MISTER_VERSION '$MISTER_VERSION' -- post-build.sh did not honor the override" +fi +release_date="20$yymmdd" +echo "$release_date" > "$dist/RELEASE_DATE" +echo " /MiSTer.version=$yymmdd -> RELEASE_DATE=$release_date" + +# --- 2. image assets -------------------------------------------------------------- +say "staging image assets into $dist" +cp -f "$out/images/linux.img" "$out/images/zImage_dtb" "$out/images/zImage_dtb-rt" "$out/images/linux-rt.config" "$dist/" +cp -f "$out/.config" "$dist/buildroot.config" +trees=("$out"/build/linux-[0-9]*/) +[ "${#trees[@]}" -eq 1 ] && [ -d "${trees[0]}" ] || die "expected exactly one kernel tree at $out/build/linux-[0-9]*/, found ${#trees[@]} (a stale sibling from a version bump?)" +cp -f "${trees[0]}.config" "$dist/linux.config" +ci_lib_package_legal_info "$out" "$dist/legal-info.tar.gz" patches-only +ci_lib_check_release_asset_size "$dist/legal-info.tar.gz" legal-info.tar.gz \ + ". The package set has outgrown a single source bundle -- split it (e.g. sources/ as its own asset)." + +# --- 3. the stock archive --------------------------------------------------------- +say "fetching + verifying the pinned stock release" +vsp="$ROOT/scripts/verify-stock-payload.sh" +"$vsp" fetch-stock "$work/stock_release.7z" +"$vsp" verify-stock "$work/stock_release.7z" +"$vsp" extract-stock "$work/stock_release.7z" "$work/stock-extract" +"$vsp" verify-uboot "$work/stock-extract" + +# --- 4. assemble + pack ------------------------------------------------------------ +say "assembling files/linux and packing release_$release_date.7z" +mkdir -p "$work/release-stage" +cp -a "$work/stock-extract/files" "$work/release-stage/files" +cp -f "$out/images/linux.img" "$out/images/zImage_dtb" "$out/images/7za" "$work/release-stage/files/linux/" +find "$work/release-stage/files/linux" -maxdepth 1 -printf ' %f\n' | sort +# Plain solid LZMA2, no BCJ2: the on-device 7za (2016) cannot read BCJ2 streams. +( cd "$work/release-stage" && 7z a -mx=9 -m0=lzma2 -mf=off -ms=on "$dist/release_$release_date.7z" files/ >/dev/null ) +echo " wrote $dist/release_$release_date.7z ($(wc -c < "$dist/release_$release_date.7z") bytes)" + +# --- 5. round trip under the pinned ARM 7za ---------------------------------------- +say "round-tripping the archive under the pinned ARM 7za (qemu-arm)" +"$vsp" fetch-7za "$work/7za" +"$vsp" roundtrip "$dist/release_$release_date.7z" "$work/7za" "$work/downloader-extract" "$out/target" +"$vsp" verify-uboot "$work/downloader-extract" --hash-only +"$vsp" verify-layout "$dist/release_$release_date.7z" "$work/release-stage" + +# --- 6. SHA256SUMS ------------------------------------------------------------------- +say "SHA256SUMS" +( cd "$dist" && sha256sum "release_$release_date.7z" linux.img zImage_dtb zImage_dtb-rt buildroot.config linux.config linux-rt.config legal-info.tar.gz > SHA256SUMS && cat SHA256SUMS ) +# The stock archive stays for scripts/mk-sdcard.sh, which reuses it through +# fetch-sdcard-payload.sh's cache instead of downloading it again. +say "done: $dist ready; stock archive kept at $work/stock_release.7z for mk-sdcard.sh" diff --git a/scripts/test-initramfs.sh b/scripts/test-initramfs.sh index 546150f..3392bcc 100755 --- a/scripts/test-initramfs.sh +++ b/scripts/test-initramfs.sh @@ -33,7 +33,7 @@ # entry on it, so this synthetic test is the only place that regression can # ever be caught (see the case function below for the full argument). # -# Usage: scripts/test-initramfs.sh [--board de10nano|de25nano] [case ...] +# Usage: scripts/test-initramfs.sh [--board de10nano|de25nano] [--kernel default|rt] [case ...] # With no case arguments, runs all eight cases. Exit 0 iff every requested # case passed; nonzero otherwise (wired for P4.1's CI job). # @@ -58,6 +58,16 @@ # DE10 leg deliberately does not (its product kernel # cannot run under QEMU at all). # +# ONE BOARD, TWO KERNEL SERIES (2026-09-11). `--kernel rt` (de10nano only) +# runs the same DE10 leg against the RT kernel's pin (BR2_PACKAGE_LINUX_RT_VERSION, +# 7.2.y) with the RT series' own re-anchored board patch 0031 +# (board/mister/de10nano/linux-patches-beta/). 7.x exfat is iomap-based and +# 0031 had to be rewritten for it; the DE25 leg executes that rewrite on +# aarch64, but the DE10-Nano runs it as 32-bit ARM, which nothing else boots +# -- the first field `ln -s` on an RT-booted board Oopsed (page_symlink -> +# NULL write_begin, 2026-09-11, before the rewrite had shipped there). This +# leg is the 32-bit proof; its caches live under work/test-initramfs-rt*. +# # Every case, cmdline and assertion is identical between the two legs. The # cross compiler for the DE25 leg is the DE25 build's own glibc toolchain # (output-de25/host/bin), so `make de25` is the only @@ -91,11 +101,18 @@ SUPPORT="$HERE/test-initramfs" # environment is the same switch for callers that cannot pass arguments # (ci-tests.sh's per-board legs use the flag). BOARD="${TEST_INITRAMFS_BOARD:-de10nano}" +# `--kernel` picks which of the board's kernel series the QEMU test kernel is +# built at: `default` (BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE, the shipped +# kernel) or `rt` (BR2_PACKAGE_LINUX_RT_VERSION with the RT series' own patch +# 0031). TEST_INITRAMFS_KERNEL is the environment form. +KERNEL="${TEST_INITRAMFS_KERNEL:-default}" _args=() while [ "$#" -gt 0 ]; do case "$1" in --board) shift; BOARD="${1:-}" ;; --board=*) BOARD="${1#--board=}" ;; + --kernel) shift; KERNEL="${1:-}" ;; + --kernel=*) KERNEL="${1#--kernel=}" ;; *) _args+=("$1") ;; esac shift @@ -117,6 +134,7 @@ de10nano) KERNEL_BASE_DEFCONFIG=multi_v7_defconfig KERNEL_BASE_FILES=() PIN_FRAGMENT="$ROOT/configs/mister_de10nano_defconfig" + PIN_SYMBOL=BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE EXFAT_SYMLINK_PATCH="$ROOT/board/mister/de10nano/linux-patches/0031-exfat-samsung-symlinks.patch" CACHE_TAG="" ;; @@ -138,6 +156,7 @@ de25nano) KERNEL_BASE_FILES=("$ROOT/board/mister/de25nano/linux.config" "$ROOT/board/mister/common/linux-mister.fragment") PIN_FRAGMENT="$ROOT/configs/mister_de25nano_defconfig" + PIN_SYMBOL=BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE # Resolved through the DE25's own patch dir, which links to the 7.x # re-anchored copy in linux-patches-beta/ (since 2026-09-06 -- this # very case found the shared 6.18 form Oopsing on 7.x, ADR 0002 §8b). @@ -150,6 +169,23 @@ de25nano) ;; esac +case "$BOARD/$KERNEL" in +*/default) + ;; +de10nano/rt) + # The RT series: its pin, its own 7.x-anchored 0031, its own caches (a + # 7.2.y source tree and O= build must never share work/ with the 6.18 + # ones -- ensure_qemu_kernel() reuses whatever it finds there). + PIN_SYMBOL=BR2_PACKAGE_LINUX_RT_VERSION + EXFAT_SYMLINK_PATCH="$ROOT/board/mister/de10nano/linux-patches-beta/0031-exfat-samsung-symlinks.patch" + CACHE_TAG="-rt" + ;; +*) + printf 'test-initramfs.sh: FATAL: unknown --kernel %s for --board %s (known: default; rt on de10nano)\n' "'$KERNEL'" "$BOARD" >&2 + exit 2 + ;; +esac + INIT_SRC="$ROOT/board/mister/common/initramfs-overlay/init" MARKER_C="$SUPPORT/marker-init.c" TEST_SYMLINK_C="$SUPPORT/test-symlink.c" @@ -171,14 +207,14 @@ KERNEL_SRC="${TEST_INITRAMFS_KERNEL_SRC:-$ROOT/work/test-initramfs$CACHE_TAG-ker # fails the QEMU kernel build with a confusing "too few arguments". Reading the # pin keeps this test kernel on the same version the image ships, which is what # this script's header already claims it does. -KERNEL_VERSION="${TEST_INITRAMFS_KERNEL_VERSION:-$(sed -n 's/^BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="\(.*\)"$/\1/p' "$PIN_FRAGMENT")}" +KERNEL_VERSION="${TEST_INITRAMFS_KERNEL_VERSION:-$(sed -n "s/^$PIN_SYMBOL=\"\(.*\)\"\$/\1/p" "$PIN_FRAGMENT")}" # Inline, not die() -- that is defined further down, and this block runs before # it. Under `set -uo pipefail` (no -e) an undefined-function call would print # "command not found" and CARRY ON, which is exactly the silent failure this # guard exists to prevent. [ -n "$KERNEL_VERSION" ] || { printf 'test-initramfs.sh: FATAL: %s\n' \ - "could not read BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE from ${PIN_FRAGMENT#"$ROOT"/}" >&2 + "could not read $PIN_SYMBOL from ${PIN_FRAGMENT#"$ROOT"/}" >&2 exit 2 } # The pristine source tarball. Buildroot's own kernel build fetches it into @@ -1021,7 +1057,7 @@ main() { ensure_qemu_kernel build_marker_inits - log "board: $BOARD ($KARCH, $QEMU_SYSTEM ${QEMU_MACHINE[*]}, kernel $KERNEL_VERSION, cpio ${CPIO#"$ROOT"/})" + log "board: $BOARD ($KARCH, $QEMU_SYSTEM ${QEMU_MACHINE[*]}, kernel $KERNEL_VERSION [$KERNEL series, $(basename "$(dirname "$EXFAT_SYMLINK_PATCH")")/0031], cpio ${CPIO#"$ROOT"/})" log "running ${#requested[@]} case(s): ${requested[*]}" echo "" local c diff --git a/sdk.log b/sdk.log new file mode 100644 index 0000000..e3e67d5 --- /dev/null +++ b/sdk.log @@ -0,0 +1,208 @@ +==> host 'install' is not GNU; shimming /usr/bin/gnuinstall into PATH for Buildroot +PATH="/mnt/source/Buildroot_MiSTer-vanilla/work/.hostshim:$PATH" make -C /mnt/source/Buildroot_MiSTer-vanilla/work/buildroot O=/mnt/source/Buildroot_MiSTer-vanilla/output BR2_EXTERNAL=/mnt/source/Buildroot_MiSTer-vanilla sdk +make[1]: Entering directory '/mnt/source/Buildroot_MiSTer-vanilla/work/buildroot' +/mnt/source/Buildroot_MiSTer-vanilla/package/linux-rt/linux-rt.mk:119: warning: overriding recipe for target '/mnt/source/Buildroot_MiSTer-vanilla/board/mister/de10nano/linux.config' +linux/linux.mk:700: warning: ignoring old recipe for target '/mnt/source/Buildroot_MiSTer-vanilla/board/mister/de10nano/linux.config' +>>> Finalizing host directory +>>> Finalizing target directory +rm -rf /mnt/source/Buildroot_MiSTer-vanilla/output/target/usr/src/hare +mkdir -p /mnt/source/Buildroot_MiSTer-vanilla/output/host/etc/meson +sed -e "s%@TARGET_CFLAGS@%'-D_LARGEFILE_SOURCE', '-D_LARGEFILE64_SOURCE', '-D_FILE_OFFSET_BITS=64', '-O2', '-g0', '-D_FORTIFY_SOURCE=1'@PKG_TARGET_CFLAGS@%g" -e "s%@TARGET_LDFLAGS@%@PKG_TARGET_LDFLAGS@%g" -e "s%@TARGET_CXXFLAGS@%'-D_LARGEFILE_SOURCE', '-D_LARGEFILE64_SOURCE', '-D_FILE_OFFSET_BITS=64', '-O2', '-g0', '-D_FORTIFY_SOURCE=1'@PKG_TARGET_CXXFLAGS@%g" -e "s%@TARGET_FCFLAGS@%'-O2', '-g0'@PKG_TARGET_FCFLAGS@%g" -e "s%@TARGET_CC@%/mnt/source/Buildroot_MiSTer-vanilla/output/host/bin/arm-buildroot-linux-gnueabihf-gcc%g" -e "s%@TARGET_CXX@%/mnt/source/Buildroot_MiSTer-vanilla/output/host/bin/arm-buildroot-linux-gnueabihf-g++%g" -e "s%@TARGET_AR@%/mnt/source/Buildroot_MiSTer-vanilla/output/host/bin/arm-buildroot-linux-gnueabihf-gcc-ar%g" -e "s%@TARGET_FC@%/bin/false%g" -e "s%@TARGET_STRIP@%/mnt/source/Buildroot_MiSTer-vanilla/output/host/bin/arm-buildroot-linux-gnueabihf-strip%g" -e "s%@TARGET_ARCH@%arm%g" -e "s%@TARGET_CPU@%cortex-a9%g" -e "s%@TARGET_ENDIAN@%little%g" -e "s%@TARGET_FCFLAGS@%%g" -e "s%@TARGET_CFLAGS@%%g" -e "s%@TARGET_LDFLAGS@%%g" -e "s%@TARGET_CXXFLAGS@%%g" -e "s%@BR2_CMAKE@%/usr/bin/cmake%g" -e "s%@PKGCONF_HOST_BINARY@%/mnt/source/Buildroot_MiSTer-vanilla/output/host/bin/pkgconf%g" -e "s%@HOST_DIR@%/mnt/source/Buildroot_MiSTer-vanilla/output/host%g" -e "s%@STAGING_DIR@%/mnt/source/Buildroot_MiSTer-vanilla/output/host/arm-buildroot-linux-gnueabihf/sysroot%g" -e "s%@STATIC@%false%g" /mnt/source/Buildroot_MiSTer-vanilla/work/buildroot/support/misc/cross-compilation.conf.in > /mnt/source/Buildroot_MiSTer-vanilla/output/host/etc/meson/cross-compilation.conf.in +sed -e "s%@TARGET_CC@%/mnt/source/Buildroot_MiSTer-vanilla/output/host/bin/arm-buildroot-linux-gnueabihf-gcc%g" -e "s%@TARGET_CXX@%/mnt/source/Buildroot_MiSTer-vanilla/output/host/bin/arm-buildroot-linux-gnueabihf-g++%g" -e "s%@TARGET_AR@%/mnt/source/Buildroot_MiSTer-vanilla/output/host/bin/arm-buildroot-linux-gnueabihf-gcc-ar%g" -e "s%@TARGET_FC@%/bin/false%g" -e "s%@TARGET_STRIP@%/mnt/source/Buildroot_MiSTer-vanilla/output/host/bin/arm-buildroot-linux-gnueabihf-strip%g" -e "s%@TARGET_ARCH@%arm%g" -e "s%@TARGET_CPU@%cortex-a9%g" -e "s%@TARGET_ENDIAN@%little%g" -e "s%@TARGET_FCFLAGS@%'-O2', '-g0'%g" -e "s%@TARGET_CFLAGS@%'-D_LARGEFILE_SOURCE', '-D_LARGEFILE64_SOURCE', '-D_FILE_OFFSET_BITS=64', '-O2', '-g0', '-D_FORTIFY_SOURCE=1'%g" -e "s%@TARGET_LDFLAGS@%%g" -e "s%@TARGET_CXXFLAGS@%'-D_LARGEFILE_SOURCE', '-D_LARGEFILE64_SOURCE', '-D_FILE_OFFSET_BITS=64', '-O2', '-g0', '-D_FORTIFY_SOURCE=1'%g" -e "s%@BR2_CMAKE@%/usr/bin/cmake%g" -e "s%@PKGCONF_HOST_BINARY@%/mnt/source/Buildroot_MiSTer-vanilla/output/host/bin/pkgconf%g" -e "s%@HOST_DIR@%/mnt/source/Buildroot_MiSTer-vanilla/output/host%g" -e "s%@STAGING_DIR@%/mnt/source/Buildroot_MiSTer-vanilla/output/host/arm-buildroot-linux-gnueabihf/sysroot%g" -e "s%@STATIC@%false%g" /mnt/source/Buildroot_MiSTer-vanilla/work/buildroot/support/misc/cross-compilation.conf.in > /mnt/source/Buildroot_MiSTer-vanilla/output/host/etc/meson/cross-compilation.conf +grep -qsE '^/bin/bash$' /mnt/source/Buildroot_MiSTer-vanilla/output/target/etc/shells || echo "/bin/bash" >> /mnt/source/Buildroot_MiSTer-vanilla/output/target/etc/shells +/usr/bin/sed -i -e '/# GENERIC_SERIAL$/s~^.*#~console::respawn:/sbin/getty -L console 0 vt100 #~' /mnt/source/Buildroot_MiSTer-vanilla/output/target/etc/inittab +/usr/bin/sed -i -e '/^#.*-o remount,rw \/$/s~^#\+~~' /mnt/source/Buildroot_MiSTer-vanilla/output/target/etc/inittab +if grep -q CONFIG_ASH=y /mnt/source/Buildroot_MiSTer-vanilla/output/build/busybox-1.38.0/.config; then grep -qsE '^/bin/ash$' /mnt/source/Buildroot_MiSTer-vanilla/output/target/etc/shells || echo "/bin/ash" >> /mnt/source/Buildroot_MiSTer-vanilla/output/target/etc/shells; fi +if grep -q CONFIG_HUSH=y /mnt/source/Buildroot_MiSTer-vanilla/output/build/busybox-1.38.0/.config; then grep -qsE '^/bin/hush$' /mnt/source/Buildroot_MiSTer-vanilla/output/target/etc/shells || echo "/bin/hush" >> /mnt/source/Buildroot_MiSTer-vanilla/output/target/etc/shells; fi +# Remove any existing certificates under /etc/ssl/certs +rm -f /mnt/source/Buildroot_MiSTer-vanilla/output/target/etc/ssl/certs/* +# Create symlinks to certificates under /etc/ssl/certs +# and generate the bundle +cd /mnt/source/Buildroot_MiSTer-vanilla/output/target ; for i in `find usr/share/ca-certificates -name "*.crt" | LC_COLLATE=C sort` ; do ln -sf ../../../$i etc/ssl/certs/`basename ${i} .crt`.pem ; cat $i ; done >/mnt/source/Buildroot_MiSTer-vanilla/output/build/ca-certificates.crt +# Create symlinks to the certificates by their hash values +/mnt/source/Buildroot_MiSTer-vanilla/output/host/bin/c_rehash /mnt/source/Buildroot_MiSTer-vanilla/output/target/etc/ssl/certs +Doing /mnt/source/Buildroot_MiSTer-vanilla/output/target/etc/ssl/certs +# Install the certificates bundle +/mnt/source/Buildroot_MiSTer-vanilla/work/.hostshim/install -D -m 644 /mnt/source/Buildroot_MiSTer-vanilla/output/build/ca-certificates.crt /mnt/source/Buildroot_MiSTer-vanilla/output/target/etc/ssl/certs/ca-certificates.crt +/mnt/source/Buildroot_MiSTer-vanilla/output/host/bin/udevadm hwdb --update --usr --root /mnt/source/Buildroot_MiSTer-vanilla/output/target +find /mnt/source/Buildroot_MiSTer-vanilla/output/target/usr/share \( -iname "*.gir" -o -iname \*.rnc \) -delete +rm -f /mnt/source/Buildroot_MiSTer-vanilla/output/target/usr/share/glib-2.0/schemas/*.xml /mnt/source/Buildroot_MiSTer-vanilla/output/target/usr/share/glib-2.0/schemas/*.dtd +/mnt/source/Buildroot_MiSTer-vanilla/output/host/bin/glib-compile-schemas /mnt/source/Buildroot_MiSTer-vanilla/output/host/arm-buildroot-linux-gnueabihf/sysroot/usr/share/glib-2.0/schemas --targetdir=/mnt/source/Buildroot_MiSTer-vanilla/output/target/usr/share/glib-2.0/schemas +No schema files found: doing nothing. +find /mnt/source/Buildroot_MiSTer-vanilla/output/target/usr/lib/python3.14 -name '*.py' -print0 | xargs -0 --no-run-if-empty touch -d @1788535000 +PYTHONPATH="/mnt/source/Buildroot_MiSTer-vanilla/output/host/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/python3.14/" /mnt/source/Buildroot_MiSTer-vanilla/output/host/bin/python3.14 /mnt/source/Buildroot_MiSTer-vanilla/output/build/python3-3.14.7/Lib/compileall.py -q -b -s /mnt/source/Buildroot_MiSTer-vanilla/output/target -p / /mnt/source/Buildroot_MiSTer-vanilla/output/target/usr/lib/python3.14 +find /mnt/source/Buildroot_MiSTer-vanilla/output/target/usr/lib/python3.14 -name '*.py' -print0 | xargs -0 --no-run-if-empty rm -f +find /mnt/source/Buildroot_MiSTer-vanilla/output/target/usr/lib/python3.14 -name '*.opt-1.pyc' -print0 -o -name '*.opt-2.pyc' -print0 | xargs -0 --no-run-if-empty rm -f +mkdir -p /mnt/source/Buildroot_MiSTer-vanilla/output/target/etc +echo "buildroot" > /mnt/source/Buildroot_MiSTer-vanilla/output/target/etc/hostname +/usr/bin/sed -i -e '$a \127.0.1.1\tbuildroot' -e '/^127.0.1.1/d' /mnt/source/Buildroot_MiSTer-vanilla/output/target/etc/hosts +mkdir -p /mnt/source/Buildroot_MiSTer-vanilla/output/target/etc +echo "Welcome to Buildroot" > /mnt/source/Buildroot_MiSTer-vanilla/output/target/etc/issue +/usr/bin/sed -i -e s,^root:[^:]*:,root::, /mnt/source/Buildroot_MiSTer-vanilla/output/target/etc/shadow +grep -qsE '^/bin/sh$' /mnt/source/Buildroot_MiSTer-vanilla/output/target/etc/shells || echo "/bin/sh" >> /mnt/source/Buildroot_MiSTer-vanilla/output/target/etc/shells +ln -sf bash /mnt/source/Buildroot_MiSTer-vanilla/output/target/bin/sh +/usr/bin/sed -i -e '/^root:/s,[^/]*$,bash,' /mnt/source/Buildroot_MiSTer-vanilla/output/target/etc/passwd +if [ -x /mnt/source/Buildroot_MiSTer-vanilla/output/target/sbin/swapon -a -x /mnt/source/Buildroot_MiSTer-vanilla/output/target/sbin/swapoff ]; then /usr/bin/sed -i -e '/^#.*\/sbin\/swap/s/^#\+[[:blank:]]*//' /mnt/source/Buildroot_MiSTer-vanilla/output/target/etc/inittab; else /usr/bin/sed -i -e '/^[^#].*\/sbin\/swap/s/^/#/' /mnt/source/Buildroot_MiSTer-vanilla/output/target/etc/inittab; fi +grep -qsE '^/usr/bin/tmux$' /mnt/source/Buildroot_MiSTer-vanilla/output/target/etc/shells || echo "/usr/bin/tmux" >> /mnt/source/Buildroot_MiSTer-vanilla/output/target/etc/shells +if test -d /mnt/source/Buildroot_MiSTer-vanilla/output/target/lib/modules/`MAKEFLAGS='' /usr/bin/make -j33 HOSTCC="/usr/bin/gcc -O2 -isystem /mnt/source/Buildroot_MiSTer-vanilla/output/host/include -L/mnt/source/Buildroot_MiSTer-vanilla/output/host/lib -Wl,-rpath,/mnt/source/Buildroot_MiSTer-vanilla/output/host/lib" ARCH=arm KCFLAGS="-Wno-attribute-alias" INSTALL_MOD_PATH=/mnt/source/Buildroot_MiSTer-vanilla/output/target CROSS_COMPILE="/mnt/source/Buildroot_MiSTer-vanilla/output/host/bin/arm-buildroot-linux-gnueabihf-" WERROR=0 REGENERATE_PARSERS=1 DEPMOD=true INSTALL_MOD_STRIP=1 -C /mnt/source/Buildroot_MiSTer-vanilla/output/build/linux-6.18.50 --no-print-directory -s kernelrelease 2>/dev/null` && grep -q "CONFIG_MODULES=y" /mnt/source/Buildroot_MiSTer-vanilla/output/build/linux-6.18.50/.config; then /mnt/source/Buildroot_MiSTer-vanilla/output/host/sbin/depmod -a -b /mnt/source/Buildroot_MiSTer-vanilla/output/target `MAKEFLAGS='' /usr/bin/make -j33 HOSTCC="/usr/bin/gcc -O2 -isystem /mnt/source/Buildroot_MiSTer-vanilla/output/host/include -L/mnt/source/Buildroot_MiSTer-vanilla/output/host/lib -Wl,-rpath,/mnt/source/Buildroot_MiSTer-vanilla/output/host/lib" ARCH=arm KCFLAGS="-Wno-attribute-alias" INSTALL_MOD_PATH=/mnt/source/Buildroot_MiSTer-vanilla/output/target CROSS_COMPILE="/mnt/source/Buildroot_MiSTer-vanilla/output/host/bin/arm-buildroot-linux-gnueabihf-" WERROR=0 REGENERATE_PARSERS=1 DEPMOD=true INSTALL_MOD_STRIP=1 -C /mnt/source/Buildroot_MiSTer-vanilla/output/build/linux-6.18.50 --no-print-directory -s kernelrelease 2>/dev/null`; fi +>>> linux-rt 7.2.4: module tree depmod'd in /mnt/source/Buildroot_MiSTer-vanilla/output/target/lib/modules/7.2.4 +/usr/bin/make -j33 -f support/misc/gen-glibc-locales.mk ENDIAN="little" LOCALES="en_US.UTF-8" Q=@ +make[2]: Entering directory '/mnt/source/Buildroot_MiSTer-vanilla/work/buildroot' +Generating locale en_US.UTF-8 +Adding /mnt/source/Buildroot_MiSTer-vanilla/output/target/usr/lib/locale/en_US.utf8 +make[2]: Leaving directory '/mnt/source/Buildroot_MiSTer-vanilla/work/buildroot' +printf '%s\n' C en_US locale-archive > /mnt/source/Buildroot_MiSTer-vanilla/output/build/locales.nopurge +for dir in /mnt/source/Buildroot_MiSTer-vanilla/output/target/usr/share/locale /mnt/source/Buildroot_MiSTer-vanilla/output/target/usr/share/X11/locale /mnt/source/Buildroot_MiSTer-vanilla/output/target/usr/lib/locale; do if [ ! -d $dir ]; then continue; fi; for langdir in $dir/*; do if [ -e "${langdir}" ]; then grep -qx "${langdir##*/}" /mnt/source/Buildroot_MiSTer-vanilla/output/build/locales.nopurge || rm -rf $langdir; fi done; done +if [ -d /mnt/source/Buildroot_MiSTer-vanilla/output/target/usr/share/X11/locale ]; then for lang in C en_US; do if [ -f /mnt/source/Buildroot_MiSTer-vanilla/output/target/usr/share/X11/locale/$lang/XLC_LOCALE ]; then echo "$lang/XLC_LOCALE: $lang"; fi done > /mnt/source/Buildroot_MiSTer-vanilla/output/target/usr/share/X11/locale/locale.dir; fi +rm -rf /mnt/source/Buildroot_MiSTer-vanilla/output/target/usr/include /mnt/source/Buildroot_MiSTer-vanilla/output/target/usr/share/aclocal \ + /mnt/source/Buildroot_MiSTer-vanilla/output/target/usr/lib/pkgconfig /mnt/source/Buildroot_MiSTer-vanilla/output/target/usr/share/pkgconfig \ + /mnt/source/Buildroot_MiSTer-vanilla/output/target/usr/lib/cmake /mnt/source/Buildroot_MiSTer-vanilla/output/target/usr/share/cmake \ + /mnt/source/Buildroot_MiSTer-vanilla/output/target/usr/lib/rpm /mnt/source/Buildroot_MiSTer-vanilla/output/target/usr/doc +find /mnt/source/Buildroot_MiSTer-vanilla/output/target/usr/{lib,share}/ -name '*.cmake' -print0 | xargs -0 rm -f +find /mnt/source/Buildroot_MiSTer-vanilla/output/target/lib/ /mnt/source/Buildroot_MiSTer-vanilla/output/target/usr/lib/ /mnt/source/Buildroot_MiSTer-vanilla/output/target/usr/libexec/ \ + \( -name '*.a' -o -name '*.la' -o -name '*.prl' \) -print0 | xargs -0 rm -f +rm -rf /mnt/source/Buildroot_MiSTer-vanilla/output/target/usr/share/zsh +rm -rf /mnt/source/Buildroot_MiSTer-vanilla/output/target/usr/man /mnt/source/Buildroot_MiSTer-vanilla/output/target/usr/share/man +rm -rf /mnt/source/Buildroot_MiSTer-vanilla/output/target/usr/info /mnt/source/Buildroot_MiSTer-vanilla/output/target/usr/share/info +rm -rf /mnt/source/Buildroot_MiSTer-vanilla/output/target/usr/doc /mnt/source/Buildroot_MiSTer-vanilla/output/target/usr/share/doc +rm -rf /mnt/source/Buildroot_MiSTer-vanilla/output/target/usr/share/gtk-doc +rmdir /mnt/source/Buildroot_MiSTer-vanilla/output/target/usr/share 2>/dev/null || true +rm -rf /mnt/source/Buildroot_MiSTer-vanilla/output/target/lib/debug /mnt/source/Buildroot_MiSTer-vanilla/output/target/usr/lib/debug +find /mnt/source/Buildroot_MiSTer-vanilla/output/target -type f \( -perm /111 -o -name '*.so*' \) -not \( -name 'libpthread*.so*' -o -name 'ld-*.so*' -o -name '*.ko' \) -print0 | xargs -0 /mnt/source/Buildroot_MiSTer-vanilla/output/host/bin/arm-buildroot-linux-gnueabihf-strip --remove-section=.comment --remove-section=.note 2>/dev/null || true +find /mnt/source/Buildroot_MiSTer-vanilla/output/target \( -name 'ld-*.so*' -o -name 'libpthread*.so*' \) -print0 | xargs -0 -r /mnt/source/Buildroot_MiSTer-vanilla/output/host/bin/arm-buildroot-linux-gnueabihf-strip --remove-section=.comment --remove-section=.note --strip-debug 2>/dev/null || true +test -f /mnt/source/Buildroot_MiSTer-vanilla/output/target/etc/ld.so.conf && \ + { echo "ERROR: we shouldn't have a /etc/ld.so.conf file"; exit 1; } || true +test -d /mnt/source/Buildroot_MiSTer-vanilla/output/target/etc/ld.so.conf.d && \ + { echo "ERROR: we shouldn't have a /etc/ld.so.conf.d directory"; exit 1; } || true +mkdir -p /mnt/source/Buildroot_MiSTer-vanilla/output/target/etc +( \ + echo "NAME=Buildroot"; \ + echo "VERSION=v2026.09.11-beta-11-g4118964"; \ + echo "ID=buildroot"; \ + echo "VERSION_ID=2026.08"; \ + echo "PRETTY_NAME=\"Buildroot 2026.08\"" \ +) > /mnt/source/Buildroot_MiSTer-vanilla/output/target/usr/lib/os-release +ln -sf ../usr/lib/os-release /mnt/source/Buildroot_MiSTer-vanilla/output/target/etc +>>> Sanitizing RPATH in target tree +PARALLEL_JOBS=33 \ + PER_PACKAGE_DIR=/mnt/source/Buildroot_MiSTer-vanilla/output/per-package \ + /mnt/source/Buildroot_MiSTer-vanilla/work/buildroot/support/scripts/fix-rpath target +>>> Sanity check in overlays /mnt/source/Buildroot_MiSTer-vanilla/board/mister/de10nano/rootfs-overlay +support/scripts/check-merged \ + -t overlay \ + -u \ + \ + /mnt/source/Buildroot_MiSTer-vanilla/board/mister/de10nano/rootfs-overlay +>>> Copying overlay /mnt/source/Buildroot_MiSTer-vanilla/board/mister/de10nano/rootfs-overlay +>>> Executing post-build script ../../board/mister/de10nano/post-build.sh +post-build.sh: pinned root password (stock-parity '1', fixed salt) +post-build.sh: wrote /MiSTer.version = 260904 (6 bytes, no newline) +touch /mnt/source/Buildroot_MiSTer-vanilla/output/target/usr +>>> Generating root filesystems common tables +rm -rf /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs +mkdir -p /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs +printf ' dbus -1 dbus -1 * /run/dbus - dbus DBus messagebus user\n dhcpcd -1 dhcpcd -1 * - - - dhcpcd user\n ntp -1 ntp -1 * - - - ntpd user\n sshd -1 sshd -1 * /var/empty - - SSH drop priv user\n ftp -1 ftp -1 * /home/ftp - - Anonymous FTP User\n - - sudo -1 - - - -\n - - input -1 * - - - Input device group\n - - kvm -1 * - - - kvm nodes\n - - sgx -1 * - - - SGX device nodes\n\n' >> /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/full_users_table.txt +printf ' /bin/busybox f 4755 0 0 - - - - -\n /usr/libexec/dbus-daemon-launch-helper f 4750 0 dbus - - - - -\n /usr/bin/fusermount f 4755 0 0 - - - - -\n /var/empty d 755 root root - - - - -\n /usr/bin/sudo f 4755 0 0 - - - - -\n\n' > /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/full_devices_table.txt +cat system/device_table.txt >> /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/full_devices_table.txt +>>> Generating filesystem image rootfs.ext2 +mkdir -p /mnt/source/Buildroot_MiSTer-vanilla/output/images +rm -rf /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/ext2 +mkdir -p /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/ext2 +rsync -auH --exclude=/THIS_IS_NOT_YOUR_ROOT_FILESYSTEM /mnt/source/Buildroot_MiSTer-vanilla/output/target/ /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/ext2/target +echo '#!/bin/sh' > /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/ext2/fakeroot +echo "set -e" >> /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/ext2/fakeroot +echo "chown -h -R 0:0 /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/ext2/target" >> /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/ext2/fakeroot +PATH="/mnt/source/Buildroot_MiSTer-vanilla/output/host/bin:/mnt/source/Buildroot_MiSTer-vanilla/output/host/sbin:/mnt/source/Buildroot_MiSTer-vanilla/work/.hostshim:/home/mcf/.local/bin:/home/mcf/.local/bin:/home/mcf/.nvm/versions/node/v24.15.0/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/usr/lib/wsl/lib:/snap/bin" /mnt/source/Buildroot_MiSTer-vanilla/work/buildroot/support/scripts/mkusers /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/full_users_table.txt /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/ext2/target >> /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/ext2/fakeroot +echo "/mnt/source/Buildroot_MiSTer-vanilla/output/host/bin/makedevs -d /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/full_devices_table.txt /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/ext2/target" >> /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/ext2/fakeroot +printf ' rm -rf /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/ext2/target/usr/lib/udev/hwdb.d/ /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/ext2/target/etc/udev/hwdb.d/\n' >> /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/ext2/fakeroot +echo "find /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/ext2/target/run/ -mindepth 1 -prune -print0 | xargs -0r rm -rf --" >> /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/ext2/fakeroot +echo "find /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/ext2/target/tmp/ -mindepth 1 -prune -print0 | xargs -0r rm -rf --" >> /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/ext2/fakeroot +printf ' find /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/ext2/target -print0 | xargs -0 -r touch -hd @1788535000\n' >> /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/ext2/fakeroot +printf ' \n' >> /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/ext2/fakeroot +printf ' rm -f /mnt/source/Buildroot_MiSTer-vanilla/output/images/rootfs.ext2\n /mnt/source/Buildroot_MiSTer-vanilla/output/host/sbin/mkfs.ext4 -d /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/ext2/target -N 0 -m 5 -L "rootfs" -I 256 -U 71916572-439f-448e-b8d8-12b0a032fa56 -E hash_seed=9afc615c-c310-4e03-ada9-613522e83ae6 -b 4096 -O has_journal,ext_attr,resize_inode,dir_index,filetype,extent,64bit,flex_bg,sparse_super,large_file,huge_file,dir_nlink,extra_isize,metadata_csum,^metadata_csum_seed,^orphan_file /mnt/source/Buildroot_MiSTer-vanilla/output/images/rootfs.ext2 "512M" || { ret=$?; echo "*** Maybe you need to increase the filesystem size (BR2_TARGET_ROOTFS_EXT2_SIZE)" 1>&2; exit $ret; }\n' >> /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/ext2/fakeroot +chmod a+x /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/ext2/fakeroot +PATH="/mnt/source/Buildroot_MiSTer-vanilla/output/host/bin:/mnt/source/Buildroot_MiSTer-vanilla/output/host/sbin:/mnt/source/Buildroot_MiSTer-vanilla/work/.hostshim:/home/mcf/.local/bin:/home/mcf/.local/bin:/home/mcf/.nvm/versions/node/v24.15.0/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/usr/lib/wsl/lib:/snap/bin" FAKEROOTDONTTRYCHOWN=1 /mnt/source/Buildroot_MiSTer-vanilla/output/host/bin/fakeroot -- /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/ext2/fakeroot +rootdir=/mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/ext2/target +table='/mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/full_devices_table.txt' +mke2fs 1.47.4 (6-Mar-2025) +Creating regular file /mnt/source/Buildroot_MiSTer-vanilla/output/images/rootfs.ext2 +Creating filesystem with 131072 4k blocks and 32768 inodes +Filesystem UUID: 71916572-439f-448e-b8d8-12b0a032fa56 +Superblock backups stored on blocks: + 32768, 98304 + +Allocating group tables: 0/4 done +Writing inode tables: 0/4 done +Creating journal (4096 blocks): done +Copying files into the device: done +Writing superblocks and filesystem accounting information: 0/4 done + +ln -sf rootfs.ext2 /mnt/source/Buildroot_MiSTer-vanilla/output/images/rootfs.ext4 +>>> Generating filesystem image rootfs.tar +mkdir -p /mnt/source/Buildroot_MiSTer-vanilla/output/images +rm -rf /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/tar +mkdir -p /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/tar +rsync -auH --exclude=/THIS_IS_NOT_YOUR_ROOT_FILESYSTEM /mnt/source/Buildroot_MiSTer-vanilla/output/target/ /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/tar/target +echo '#!/bin/sh' > /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/tar/fakeroot +echo "set -e" >> /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/tar/fakeroot +echo "chown -h -R 0:0 /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/tar/target" >> /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/tar/fakeroot +PATH="/mnt/source/Buildroot_MiSTer-vanilla/output/host/bin:/mnt/source/Buildroot_MiSTer-vanilla/output/host/sbin:/mnt/source/Buildroot_MiSTer-vanilla/work/.hostshim:/home/mcf/.local/bin:/home/mcf/.local/bin:/home/mcf/.nvm/versions/node/v24.15.0/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/usr/lib/wsl/lib:/snap/bin" /mnt/source/Buildroot_MiSTer-vanilla/work/buildroot/support/scripts/mkusers /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/full_users_table.txt /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/tar/target >> /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/tar/fakeroot +echo "/mnt/source/Buildroot_MiSTer-vanilla/output/host/bin/makedevs -d /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/full_devices_table.txt /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/tar/target" >> /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/tar/fakeroot +printf ' rm -rf /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/tar/target/usr/lib/udev/hwdb.d/ /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/tar/target/etc/udev/hwdb.d/\n' >> /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/tar/fakeroot +echo "find /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/tar/target/run/ -mindepth 1 -prune -print0 | xargs -0r rm -rf --" >> /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/tar/fakeroot +echo "find /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/tar/target/tmp/ -mindepth 1 -prune -print0 | xargs -0r rm -rf --" >> /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/tar/fakeroot +printf ' find /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/tar/target -print0 | xargs -0 -r touch -hd @1788535000\n' >> /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/tar/fakeroot +printf ' \n' >> /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/tar/fakeroot +printf ' (cd /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/tar/target; find -print0 | LC_ALL=C sort -z | tar --pax-option=exthdr.name=%%d/PaxHeaders/%%f,atime:=0,ctime:=0 -cf /mnt/source/Buildroot_MiSTer-vanilla/output/images/rootfs.tar --null --xattrs-include='\''*'\'' --no-recursion -T - --numeric-owner)\n' >> /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/tar/fakeroot +chmod a+x /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/tar/fakeroot +PATH="/mnt/source/Buildroot_MiSTer-vanilla/output/host/bin:/mnt/source/Buildroot_MiSTer-vanilla/output/host/sbin:/mnt/source/Buildroot_MiSTer-vanilla/work/.hostshim:/home/mcf/.local/bin:/home/mcf/.local/bin:/home/mcf/.nvm/versions/node/v24.15.0/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/usr/lib/wsl/lib:/snap/bin" FAKEROOTDONTTRYCHOWN=1 /mnt/source/Buildroot_MiSTer-vanilla/output/host/bin/fakeroot -- /mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/tar/fakeroot +rootdir=/mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/tar/target +table='/mnt/source/Buildroot_MiSTer-vanilla/output/build/buildroot-fs/full_devices_table.txt' +>>> Executing post-image script ../../board/mister/de10nano/post-image.sh +post-image.sh: zImage = /mnt/source/Buildroot_MiSTer-vanilla/output/images/zImage (9696920 bytes) +post-image.sh: dtb = /mnt/source/Buildroot_MiSTer-vanilla/output/images/socfpga_cyclone5_de10nano.dtb (20377 bytes) +post-image.sh: wrote /mnt/source/Buildroot_MiSTer-vanilla/output/images/zImage_dtb (9717297 bytes) +check-zimage-dtb.sh: /mnt/source/Buildroot_MiSTer-vanilla/output/images/zImage_dtb (9717297 bytes) +ok zImage magic 0x016f2818 present at +0x24 + zImage declared start (+0x28) = 0 + zImage declared end (+0x2C) = 9696920 <- U-Boot's fdt_addr offset + U-Boot computes fdt_addr = 0x01000000 + 0x0093f698 = 0x0193f698 +ok DTB magic 0xd00dfeed sits exactly at the declared end (9696920) + DTB totalsize = 20377 +ok DTB totalsize reaches exactly EOF (9696920 + 20377 = 9717297) +ok size 9717297 < 16 MiB budget (headroom 7059919 bytes, top addr 0x01944631) +check-zimage-dtb.sh: all assertions passed +post-image.sh: wrote /mnt/source/Buildroot_MiSTer-vanilla/output/images/linux.img (536870912 bytes, hardlink of /mnt/source/Buildroot_MiSTer-vanilla/output/images/rootfs.ext2) +check-linux-img.sh: /mnt/source/Buildroot_MiSTer-vanilla/output/images/linux.img (536870912 bytes) +ok size == 536870912 bytes (512 MiB) +ok volume label = 'rootfs' +ok filesystem UUID = 71916572-439f-448e-b8d8-12b0a032fa56 (pinned) +ok directory hash seed = 9afc615c-c310-4e03-ada9-613522e83ae6 (pinned) + features (as built): has_journal ext_attr resize_inode dir_index filetype extent 64bit flex_bg sparse_super large_file huge_file dir_nlink extra_isize metadata_csum +ok feature set matches the pinned 14-feature stock-derived list exactly +ok no ssh_host_* files anywhere in the image (ADR 0015) +ok dhcpcd hook set is exactly the pinned one (01-test 20-resolv.conf 30-hostname 50-ntp.conf 90-timezone 91-ntp-kick) +ok dhcpcd example-hook set is exactly the pinned one (10-wpa_supplicant 15-timezone 29-lookup-hostname 50-yp.conf) +ok /etc/ssh_keys is present and empty in the image (keys are runtime state, not build output) +check-linux-img.sh: all assertions passed +>>> Preparing the SDK +/mnt/source/Buildroot_MiSTer-vanilla/work/.hostshim/install -m 755 /mnt/source/Buildroot_MiSTer-vanilla/work/buildroot/support/misc/relocate-sdk.sh /mnt/source/Buildroot_MiSTer-vanilla/output/host/relocate-sdk.sh +mkdir -p /mnt/source/Buildroot_MiSTer-vanilla/output/host/share/buildroot +(\ + export LC_ALL=C; \ + grep -lr '/mnt/source/Buildroot_MiSTer-vanilla/output/host' '/mnt/source/Buildroot_MiSTer-vanilla/output/host' | while read -r FILE; do \ + if file -b --mime-type "$FILE" | grep -q '^text/' && \ + [ "$FILE" != '/mnt/source/Buildroot_MiSTer-vanilla/output/host/share/buildroot/sdk-location' ] && \ + [ "$FILE" != '/mnt/source/Buildroot_MiSTer-vanilla/output/host/share/buildroot/sdk-relocs' ]; then \ + echo "$FILE"; \ + fi; \ + done \ +) | sed -e 's|^/mnt/source/Buildroot_MiSTer-vanilla/output/host|.|g' > /mnt/source/Buildroot_MiSTer-vanilla/output/host/share/buildroot/sdk-relocs +echo /mnt/source/Buildroot_MiSTer-vanilla/output/host > /mnt/source/Buildroot_MiSTer-vanilla/output/host/share/buildroot/sdk-location +>>> Generating SDK tarball +tar czf "/mnt/source/Buildroot_MiSTer-vanilla/output/images/arm-buildroot-linux-gnueabihf_sdk-buildroot.tar.gz" \ + --owner=0 --group=0 --numeric-owner \ + --transform='s#^mnt/source/Buildroot_MiSTer-vanilla/output/host#arm-buildroot-linux-gnueabihf_sdk-buildroot#' \ + -C / mnt/source/Buildroot_MiSTer-vanilla/output/host +make[1]: Leaving directory '/mnt/source/Buildroot_MiSTer-vanilla/work/buildroot' +exit=0