From 4dbdc2c4040c439957d0ce49d4e51325712b25c2 Mon Sep 17 00:00:00 2001 From: "Michael C. Ferguson" Date: Fri, 2 Oct 2026 16:57:49 -0500 Subject: [PATCH] feat(zaparoo-scanout): package the zaparoo_scanout kernel module for DE10-Nano New kernel-module package built from ZaparooProject/Menu_MiSTer's kernel/scanout-slots/ at a master commit pin. It provides /dev/zaparoo-scanout: two exclusive write-combined 1080p framebuffer slots above the MiSTer_fb aperture. Not autoloaded. One local patch drops the module's hard-coded "6.18.38-MiSTer" release check, which made it refuse to load on any other kernel; vermagic and the remaining device-tree checks still pin it to the DE10-Nano. Enabled in the DE10-Nano defconfig only. Renovate tracks the pin monthly (driver-pin label), hash-sync refreshes the tarball hash, and ci-tests asserts the .ko.xz is in rootfs.tar. See docs/zaparoo-scanout.md. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/renovate-hash-sync.yml | 3 +- Config.in | 4 ++ configs/mister_de10nano_defconfig | 1 + docs/buildroot-config.md | 7 ++ docs/renovate.md | 2 +- docs/zaparoo-scanout.md | 70 +++++++++++++++++++ ...-the-hard-coded-kernel-release-check.patch | 35 ++++++++++ package/zaparoo-scanout/Config.in | 19 +++++ package/zaparoo-scanout/zaparoo-scanout.hash | 4 ++ package/zaparoo-scanout/zaparoo-scanout.mk | 16 +++++ renovate.json | 27 +++++++ scripts/ci-tests.sh | 10 +++ 12 files changed, 196 insertions(+), 2 deletions(-) create mode 100644 docs/zaparoo-scanout.md create mode 100644 package/zaparoo-scanout/0001-zaparoo_scanout-drop-the-hard-coded-kernel-release-check.patch create mode 100644 package/zaparoo-scanout/Config.in create mode 100644 package/zaparoo-scanout/zaparoo-scanout.hash create mode 100644 package/zaparoo-scanout/zaparoo-scanout.mk diff --git a/.github/workflows/renovate-hash-sync.yml b/.github/workflows/renovate-hash-sync.yml index 53c0475..ea4eefa 100644 --- a/.github/workflows/renovate-hash-sync.yml +++ b/.github/workflows/renovate-hash-sync.yml @@ -153,6 +153,7 @@ on: # both-lists-or-silent-failure note as rtl8852cu-morrownr above. - "package/aic8800/aic8800.mk" - "package/xone/xone.mk" + - "package/zaparoo-scanout/zaparoo-scanout.mk" - "package/midilink/midilink.mk" # ADR 0023: 7-Zip, which pins the SAME ip7z/7zip release asset # package/lzma-sdk does. Renovate raises ONE PR touching both .mk files @@ -297,7 +298,7 @@ jobs: # tarballs from the loop's .../archive/.tar.gz form and Buildroot's # .../archive//.tar.gz form -- see package/dualsensectl/ # dualsensectl.hash. - HASH_SYNC_PACKAGES: "rtl8852cu-morrownr aic8800 xone midilink munt bcm20702-firmware libchdr rcheevos dualsensectl ltunify" + HASH_SYNC_PACKAGES: "rtl8852cu-morrownr aic8800 xone zaparoo-scanout midilink munt bcm20702-firmware libchdr rcheevos dualsensectl ltunify" steps: # A manual run pushes commits to whatever branch it is pointed at, so diff --git a/Config.in b/Config.in index cfd0ee1..7812c10 100644 --- a/Config.in +++ b/Config.in @@ -69,6 +69,10 @@ menu "USB controller drivers (out-of-tree, P3.2)" source "$BR2_EXTERNAL_MISTER_PATH/package/xow-firmware/Config.in" endmenu +menu "Display drivers (out-of-tree)" + source "$BR2_EXTERNAL_MISTER_PATH/package/zaparoo-scanout/Config.in" +endmenu + menu "Input-device userspace tooling" # Deliberately NOT folded into the "USB controller drivers" menu above: # everything there is an out-of-tree KERNEL MODULE, and these are plain diff --git a/configs/mister_de10nano_defconfig b/configs/mister_de10nano_defconfig index 186ec5b..60284a3 100644 --- a/configs/mister_de10nano_defconfig +++ b/configs/mister_de10nano_defconfig @@ -68,5 +68,6 @@ BR2_PACKAGE_HOST_KMOD_XZ=y BR2_PACKAGE_MISTER_FIRMWARE=y BR2_PACKAGE_MISTER_DRIVERS=y BR2_PACKAGE_MISTER_USERSPACE=y +BR2_PACKAGE_ZAPAROO_SCANOUT=y BR2_PACKAGE_LINUX_RT=y BR2_PACKAGE_LINUX_RT_VERSION="7.2.8" diff --git a/docs/buildroot-config.md b/docs/buildroot-config.md index 2eca885..c0a11a1 100644 --- a/docs/buildroot-config.md +++ b/docs/buildroot-config.md @@ -2248,6 +2248,13 @@ first time the box gets an address, from a geo-IP lookup (ADR 0025). It needs the full zonelist to have a zone to copy, and the `posix/` subtree specifically — the same path the community `timezone.sh` copies from. +### 5.46 zaparoo-scanout (out-of-tree display module) + +`BR2_PACKAGE_ZAPAROO_SCANOUT=y`, in the DE10-Nano defconfig directly rather +than in the `mister-drivers` profile: the module validates the Cyclone V +machine compatible and the DE10's `MiSTer_fb` aperture, so it is DE10-only by +construction. See [`docs/zaparoo-scanout.md`](zaparoo-scanout.md). + --- ## 6. `de25nano.fragment` diff --git a/docs/renovate.md b/docs/renovate.md index a1e58db..4a94ae6 100644 --- a/docs/renovate.md +++ b/docs/renovate.md @@ -50,7 +50,7 @@ for the specific pieces most likely to need a fix on the first live run. | Buildroot release | `Makefile` (`BUILDROOT_VERSION`) | `customManagers` regex, `github-tags` datasource, `allowedVersions` locked to `2026.08.x` | `BUILDROOT_SHA256` — **auto-refreshed since 2026-08-24** by `renovate-hash-sync.yml` (`hash-sync-buildroot.sh`, case 6) from buildroot.org's GPG-signed `.sign` manifest; **manual** before that date (this row used to say so), and the `make buildroot-showsig` transcription remains the fallback — see below. **Since 2026-09-02 a second companion:** `scripts/check-defconfigs.sh` — the resolved-config hashes `scripts/check-defconfigs.sh` asserts per Buildroot version — is recorded for the new version by case 8 (`hash-sync-golden.sh`) in the same PR; if that case skips, `lint-config` only *warns* on the missing lines and the manual step is `scripts/check-defconfigs.sh --update-golden` + commit | | Kernel (6.18.y longterm) | `configs/mister_de10nano_defconfig` (`BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE`) — the one committed DE10 defconfig (ADR 0030) | one `customManagers` regex on that file + a `customDatasources` entry over `kernel.org/releases.json`, filtered to `moniker=longterm` and the `6.18.` prefix; `allowedVersions` locked to `6.18.y` as defense in depth. Same `depName` for both files, so Renovate emits **one PR touching both** | `board/mister/de10nano/patches/linux/linux.hash` — auto-refreshed by `renovate-hash-sync.yml` from kernel.org's signed `sha256sums.asc` | | Kernel (RT/beta, the **7.2 line**) | `configs/mister_de10nano_defconfig` (`BR2_PACKAGE_LINUX_RT_VERSION` — the `package/linux-rt` pin, a different symbol in the same file; its hash is `package/linux-rt/linux-rt.hash`) | a **separate** `customManagers` regex + its own `kernelStable72` datasource; `allowedVersions` locked to `/^7\.2(\.\d+)?$/`. Labeled `rt-kernel-pin` + `needs-manual-version-check`. **Rewritten 2026-08-17** when 7.2 released: the datasource was `kernelMainline` (`moniker=mainline`) and the depName `kernel-mainline-rt`. Both were right while 7.2 was in `-rc` and wrong the moment it shipped — mainline moves to 7.3-rc1 about two weeks later, so the old filter would have dragged the variant straight back off the line it had just reached. The filter is now **moniker-agnostic and version-scoped**, because the 7.2 line changes moniker underneath us: today 7.2 is the `mainline` entry and no 7.2.y stable release exists yet, and once 7.2.1 ships it becomes the `stable` entry instead. The matchString accepts two- *and* three-component values for the same reason | `board/mister/de10nano/patches/linux/linux.hash` — **auto-refreshed since 2026-08-17** by `renovate-hash-sync.yml` (`hash-sync-kernel.sh --pin=rt`) from kernel.org's signed `sha256sums.asc`, same as the 6.18 pin. This row says the opposite of what it said before that date, and the reason is that the pin changed sides, not that the rule loosened: an `-rc` is fetched as a cgit `.tar.gz` snapshot upstream signs in no way, so its hash could only be hand-written TOFU; a 7.2.y release is an ordinary `.tar.xz` covered by the signed manifest. The script still **refuses** any `-rc` for either pin, leaving the build to fail closed | -| 4 driver commit-SHA pins | `package/{rtl8852cu-morrownr,aic8800,xone,midilink}/*.mk` | `customManagers` regex per package, `git-refs` datasource tracking the upstream default branch's HEAD via `currentDigest` | matching `.hash` file — auto-refreshed by `renovate-hash-sync.yml` | +| 5 driver commit-SHA pins | `package/{rtl8852cu-morrownr,aic8800,xone,zaparoo-scanout,midilink}/*.mk` | `customManagers` regex per package, `git-refs` datasource tracking the upstream default branch's HEAD via `currentDigest` | matching `.hash` file — auto-refreshed by `renovate-hash-sync.yml` | | munt tag pin | `package/munt/munt.mk` | `github-tags` datasource, custom `regex:` versioning for the `munt_MAJOR_MINOR_PATCH` tag scheme | `package/munt/munt.hash` — auto-refreshed | | bcm20702-firmware **commit** pin | `package/bcm20702-firmware/bcm20702-firmware.mk` | `git-refs` datasource tracking `master` HEAD via `currentDigest`. **Was** a `github-tags`/`loose` tag pin until 2026-07-19 — see "Why this one is a commit pin" below | `package/bcm20702-firmware/bcm20702-firmware.hash` — auto-refreshed | | libchdr commit-SHA pin (Main_MiSTer shared-lib refactor; labeled `lib-pin`) | `package/libchdr/libchdr.mk` | `customManagers` regex, `git-refs` datasource tracking `rtissera/libchdr`'s `master` HEAD via `currentDigest` (a commit pin, not the stale `v0.3.0` tag — see the .mk's header) | `package/libchdr/libchdr.hash` — auto-refreshed by `renovate-hash-sync.yml`'s generic loop (standard `$(call github,...)` archive tarball) | diff --git a/docs/zaparoo-scanout.md b/docs/zaparoo-scanout.md new file mode 100644 index 0000000..62101dc --- /dev/null +++ b/docs/zaparoo-scanout.md @@ -0,0 +1,70 @@ +# zaparoo-scanout: the `zaparoo_scanout` kernel module + +`package/zaparoo-scanout` builds Zaparoo's `zaparoo_scanout` out-of-tree kernel +module and ships it in DE10-Nano images as +`/usr/lib/modules//updates/zaparoo_scanout.ko.xz`. + +## 1. What it does + +Loading the module registers the misc device `/dev/zaparoo-scanout` (mode +0600, opening it needs `CAP_SYS_RAWIO`). One open file at a time owns two +write-combined RGB565 framebuffer slots, each large enough for 1920x1080: + +| Slot | Physical address | `mmap` offset | +|---|---|---| +| 0 | `0x23000000` | `0` | +| 1 | `0x23400000` | `8294400` | + +Both slots sit above the `MiSTer_fb` device-tree aperture (`0x22000000`, +8 MiB) and above the `mem=511M` boundary, so Linux never manages that memory. +The ioctl `ZAPAROO_SCANOUT_GET_LAYOUT` (`_IOR('Z', 1, ...)`) returns a 64-byte +layout struct (ABI v1); the header is `kernel/scanout-slots/zaparoo_scanout_uapi.h` +in the source tree. The module sends no FPGA commands and owns no DMA or IRQ. + +It is **not autoloaded**: there is no modalias, so the client loads it with +`modprobe zaparoo_scanout`. + +## 2. Source and pin + +- Upstream: [ZaparooProject/Menu_MiSTer](https://github.com/ZaparooProject/Menu_MiSTer), + subdirectory `kernel/scanout-slots/`. It is derived from the MiSTer-MagiK + scanout-slots module. +- The pin is a commit on `master`. Buildroot downloads the whole repository + archive (~28 MB, mostly FPGA release binaries) and builds only that + subdirectory (`ZAPAROO_SCANOUT_MODULE_SUBDIRS`). +- Renovate tracks the pin through the `ZaparooProject/Menu_MiSTer` regex + manager, on a **monthly** schedule (the 1st, before 06:00), with the + `driver-pin` label. `renovate-hash-sync.yml` refreshes the hash as for any + other github-archive pin. + +## 3. Local patch + +`0001-zaparoo_scanout-drop-the-hard-coded-kernel-release-check.patch` removes +`validate_platform()`'s comparison of `utsname()->release` against the literal +`"6.18.38-MiSTer"`. Without it the module returns `-ENODEV` on every other +kernel, including the one it was built for. Vermagic already binds the `.ko` +to its kernel. The machine-compatible (`altr,socfpga-cyclone5`) and +`MiSTer_fb` `reg` checks stay, and they are what keep the module DE10-only. + +The `kernel_revision` modinfo field still names the upstream kernel commit +the source was written against; it does not describe this image's kernel. + +## 4. Licence + +The source is GPL-3.0-or-later (SPDX headers). The repository has no LICENSE +file, so the unpatched `zaparoo_scanout_uapi.h` stands in as the licence file. +Hash-sync refreshes only the tarball line, so a bump that edits that header +needs its hash line updated by hand (`make zaparoo-scanout-legal-info` fails +on the stale line). + +The module declares `MODULE_LICENSE("Proprietary")`, so loading it sets the +kernel's `P` taint flag and the module can link only non-GPL-only exports. + +## 5. Scope + +- **DE10-Nano only.** Enabled in `configs/mister_de10nano_defconfig`, not in + the `mister-drivers` profile ([buildroot-config.md §5.46](buildroot-config.md)). +- **Regular kernel only.** Like every out-of-tree module package here, it is + built against `BR2_LINUX_KERNEL`, not the `linux-rt` variant, so it is + absent when the board boots the RT kernel. +- CI asserts the `.ko.xz` is present in `rootfs.tar` (`scripts/ci-tests.sh`). diff --git a/package/zaparoo-scanout/0001-zaparoo_scanout-drop-the-hard-coded-kernel-release-check.patch b/package/zaparoo-scanout/0001-zaparoo_scanout-drop-the-hard-coded-kernel-release-check.patch new file mode 100644 index 0000000..05755d7 --- /dev/null +++ b/package/zaparoo-scanout/0001-zaparoo_scanout-drop-the-hard-coded-kernel-release-check.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "Michael C. Ferguson" +Date: Fri, 2 Oct 2026 16:35:16 -0500 +Subject: [PATCH] zaparoo_scanout: drop the hard-coded kernel release check + +validate_platform() refuses to load unless utsname()->release equals the +literal "6.18.38-MiSTer", so the module returns -ENODEV on any other +kernel even when it was built against that kernel. Module vermagic +already ties a .ko to the kernel it was compiled for, and the remaining +machine-compatible and MiSTer_fb device-tree checks still pin the +platform and the physical layout the slots depend on. + +Upstream: not submitted +Signed-off-by: Michael C. Ferguson +--- + kernel/scanout-slots/zaparoo_scanout.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/kernel/scanout-slots/zaparoo_scanout.c b/kernel/scanout-slots/zaparoo_scanout.c +index eac3033..47811b3 100644 +--- a/kernel/scanout-slots/zaparoo_scanout.c ++++ b/kernel/scanout-slots/zaparoo_scanout.c +@@ -54,8 +54,7 @@ static int validate_platform(void) + const __be32 *cells; + int len, ret = -ENODEV; + +- if (strcmp(utsname()->release, ZAPAROO_SCANOUT_KERNEL_RELEASE) || +- !of_machine_is_compatible(ZAPAROO_SCANOUT_MACHINE)) ++ if (!of_machine_is_compatible(ZAPAROO_SCANOUT_MACHINE)) + return -ENODEV; + cells = of_get_property(of_root, "#address-cells", &len); + if (!cells || len != 4 || be32_to_cpup(cells) != 1) +-- +2.53.0 + diff --git a/package/zaparoo-scanout/Config.in b/package/zaparoo-scanout/Config.in new file mode 100644 index 0000000..d3e835d --- /dev/null +++ b/package/zaparoo-scanout/Config.in @@ -0,0 +1,19 @@ +config BR2_PACKAGE_ZAPAROO_SCANOUT + bool "zaparoo-scanout" + depends on BR2_LINUX_KERNEL + depends on BR2_arm + help + Zaparoo's zaparoo_scanout kernel module: /dev/zaparoo-scanout + hands one owner two write-combined 1080p RGB565 framebuffer + slots above the MiSTer_fb aperture, for vblank-latched page + flips. Cyclone V (DE10-Nano) only; the module refuses to load + on any other machine. Not autoloaded. + + The module declares MODULE_LICENSE("Proprietary") because its + source is GPL-3.0-or-later, so loading it taints the kernel. + + https://github.com/ZaparooProject/Menu_MiSTer/tree/master/kernel/scanout-slots + +comment "zaparoo-scanout needs a Linux kernel to be built" + depends on BR2_arm + depends on !BR2_LINUX_KERNEL diff --git a/package/zaparoo-scanout/zaparoo-scanout.hash b/package/zaparoo-scanout/zaparoo-scanout.hash new file mode 100644 index 0000000..ed8f428 --- /dev/null +++ b/package/zaparoo-scanout/zaparoo-scanout.hash @@ -0,0 +1,4 @@ +# Locally computed (GitHub publishes no hashes for commit archives) +sha256 3646323af35645fcd90124d1fb65d92bba8f31b89a1aa2a80c52c0a4c33758e3 zaparoo-scanout-9fd408d2cd6fe8b27cee1df9d3aa8b946f0a8bc3.tar.gz +# No LICENSE file upstream; the unpatched UAPI header's SPDX line stands in for one +sha256 59cd03debe025d68d8f11f8cebe766d29c09038bcd93b8f839f7231676af5bd2 kernel/scanout-slots/zaparoo_scanout_uapi.h diff --git a/package/zaparoo-scanout/zaparoo-scanout.mk b/package/zaparoo-scanout/zaparoo-scanout.mk new file mode 100644 index 0000000..6127626 --- /dev/null +++ b/package/zaparoo-scanout/zaparoo-scanout.mk @@ -0,0 +1,16 @@ +################################################################################ +# +# zaparoo-scanout +# +################################################################################ + +# Commit pin on the Zaparoo Menu core fork; the module is one subdirectory of it. +# See docs/zaparoo-scanout.md. +ZAPAROO_SCANOUT_VERSION = 9fd408d2cd6fe8b27cee1df9d3aa8b946f0a8bc3 +ZAPAROO_SCANOUT_SITE = $(call github,ZaparooProject,Menu_MiSTer,$(ZAPAROO_SCANOUT_VERSION)) +ZAPAROO_SCANOUT_LICENSE = GPL-3.0+ +ZAPAROO_SCANOUT_LICENSE_FILES = kernel/scanout-slots/zaparoo_scanout_uapi.h +ZAPAROO_SCANOUT_MODULE_SUBDIRS = kernel/scanout-slots + +$(eval $(kernel-module)) +$(eval $(generic-package)) diff --git a/renovate.json b/renovate.json index d1249ee..30f6da9 100644 --- a/renovate.json +++ b/renovate.json @@ -230,6 +230,20 @@ "packageNameTemplate": "https://github.com/dlundqvist/xone", "datasourceTemplate": "git-refs" }, + { + "customType": "regex", + "description": "zaparoo_scanout kernel module commit pin (ZaparooProject/Menu_MiSTer, master branch; the module is kernel/scanout-slots/). Monthly cadence via the packageRule below. Hash: package/zaparoo-scanout/zaparoo-scanout.hash, refreshed by renovate-hash-sync.yml.", + "managerFilePatterns": [ + "/^package/zaparoo-scanout/zaparoo-scanout\\.mk$/" + ], + "matchStrings": [ + "ZAPAROO_SCANOUT_VERSION\\s*=\\s*(?[0-9a-f]{40})" + ], + "currentValueTemplate": "master", + "depNameTemplate": "ZaparooProject/Menu_MiSTer", + "packageNameTemplate": "https://github.com/ZaparooProject/Menu_MiSTer", + "datasourceTemplate": "git-refs" + }, { "customType": "regex", "description": "MidiLink_MiSTer commit pin (MiSTer-devel/MidiLink_MiSTer, master branch). Hash: package/midilink/midilink.hash, refreshed by renovate-hash-sync.yml.", @@ -423,6 +437,18 @@ } ], "packageRules": [ + { + "description": "zaparoo_scanout tracks a busy FPGA-core repository whose kernel/scanout-slots/ subdirectory rarely changes; take its commits monthly instead of weekly.", + "matchManagers": [ + "custom.regex" + ], + "matchDepNames": [ + "ZaparooProject/Menu_MiSTer" + ], + "schedule": [ + "* 0-5 1 * *" + ] + }, { "description": "Constrain the Buildroot pin to the 2026.08.x line -- do not let Renovate jump to a new Buildroot major/minor; P1.1's whole toolchain/config pin assumes the pinned line. (2026.08 is NOT an LTS; 2025.02 was the last LTS and 2027.02 is expected to be the next -- see docs. This is the interim non-LTS line until 2027.02 ships.) THIS REGEX IS WHY A LINE BUMP NEVER ARRIVES AS A RENOVATE PR, and that is deliberate, not a bug in the manager: `loose` versioning orders 2026.08 above 2026.05.2 correctly ([2026,8] vs [2026,5,2]), the github-tags datasource sees the tag, and allowedVersions then filters it out -- so a line bump stays a human decision. Moved 2026.05.x -> 2026.08.x by hand on 2026-09-05, the same way PR #54 moved 2026.02.x -> 2026.05.x. Bump this WITH the Makefile pin, never separately: leaving it behind silently freezes the pin, and moving it ahead invites a line jump nobody reviewed.", "matchManagers": [ @@ -474,6 +500,7 @@ "morrownr/rtl8852cu-20251113", "radxa-pkg/aic8800", "dlundqvist/xone", + "ZaparooProject/Menu_MiSTer", "MiSTer-devel/MidiLink_MiSTer", "munt/munt", "winterheart/broadcom-bt-firmware" diff --git a/scripts/ci-tests.sh b/scripts/ci-tests.sh index d4bf846..0a77b85 100755 --- a/scripts/ci-tests.sh +++ b/scripts/ci-tests.sh @@ -758,6 +758,16 @@ else fail "xone: all 9 .ko.xz modules present" "missing:$xone_missing" fi +# ============================================================================= +section "zaparoo-scanout (docs/zaparoo-scanout.md)" +# ============================================================================= + +if tar_has "usr/lib/modules/$KVER/updates/zaparoo_scanout.ko.xz"; then + pass "zaparoo-scanout: zaparoo_scanout.ko.xz present" +else + fail "zaparoo-scanout: zaparoo_scanout.ko.xz present" "missing usr/lib/modules/$KVER/updates/zaparoo_scanout.ko.xz" +fi + # In-kernel USB WiFi (ADR 0016 as updated in v10, docs/wifi-parity.md §6). # # This assertion USED to check the opposite thing: that the out-of-tree