Skip to content

Commit 570d6ea

Browse files
committed
✨ feat(rpi): extend Pi support to Raspberry Pi 5 (BCM2712)
Wires up the rpi5 build target on top of the board-aware Pi infrastructure. Pi-5-only logic in modules/rpi.nix (firmware- partition contents, [pi5] config.txt block, NixOS-built kernel as gzipped kernel_2712.img, NixOS-built initrd, explicit toplevel cmdline) is reachable via stereos.rpi.series = "rpi5", which the rpi5MixtapeSpecs set inline. Why a NixOS-built kernel as kernel_2712.img instead of raspberrypifw's prebuilt: • The firmware-shipped kernel_2712.img is a different version (e.g. 6.12.25-v8-16k+ in fw 1.20250430) than the kernel nixos-hardware configures (linux-rpi 6.12.75-1+rpt1). Booting the firmware kernel makes /lib/modules/<our-version>/ unusable — modprobe fails for everything kernel-module-dependent. • nixpkgs at our pinned rev has no ubootRaspberryPi5_64bit, so the standard sd-image-aarch64 U-Boot+extlinux flow is unavailable on Pi 5. We replace the prebuilt kernel directly and write our own cmdline.txt. • Pi 5 EEPROM detects the gzip magic on kernel_2712.img and decompresses on load; linuxPackages_rpi5 only installs the raw Image, so we gzip it during firmware-partition population. D0 vs C1 silicon: the EEPROM auto-selects bcm2712d0-rpi-5-b.dtb on D0 boards when both DTBs *and* overlays/bcm2712d0.dtbo are present. Ship only the C1 dtb and a 2 GB / rev-1.1 board panics during pinctrl-bcm2712 probe with an Asynchronous SError. We ship the full bcm2712 dtb glob and the entire overlays/ tree. GPIO 14/15 UART: enable_uart=1 by itself does not pinmux the RP1's UART0 to the GPIO header on Pi 5. The dtoverlay=uart0-pi5 overlay does that routing; the device enumerates as ttyAMA0, matching Pi 4's name (ttyAMA10 on Pi 5 is the dedicated debug-header UART, not GPIO 14/15). nixos-hardware pin: pinned to f1b7ff92cdd1 — the last commit before nixos-hardware#1841 replaced the rpi-kernel postConfigure sed with `LOCALVERSION = freeform ""`, which round-trips through nixpkgs' kernel-config emitter as the literal two characters `""` and breaks the modDirVersion sanity check. Tracked in nixos-hardware#1859, fix in #1860 unmerged as of 2026-05. Pi-5-only artifacts: • flake.nix nixos-hardware flake input • modules/rpi5-kernel-overlay.nix overlay defaulting makeModulesClosure to allowMissing=true; needed because all- hardware.nix lists modules that the rpi-vendor 6.12.x kernel builds as =y (dw_hdmi, …) so they're not present as .ko files in /lib/modules and modprobe errors during the modules-shrunk step. Pattern from nvmd/nixos-raspberrypi. • flake/images.nix rpi5MixtapeSpecs (sets series + imports nixos-hardware module + the kernel- overlay), rpi5Pkgs. • Makefile build-rpi5 / flash-rpi5 targets.
1 parent 1fc9933 commit 570d6ea

5 files changed

Lines changed: 110 additions & 3 deletions

File tree

Makefile

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ build-kernel: ## Build kernel artifacts for kernel boot
4040
# -- Raspberry Pi image builds -----------------------------------------------
4141
#
4242
# RPi images are aarch64-only and ship as a single SD card image.
43-
# The attr name adds "-rpi4-sd" to the mixtape (e.g. coder → coder-rpi4-sd).
43+
# The attr name adds "-rpi4-sd" / "-rpi5-sd" to the mixtape
44+
# (e.g. coder → coder-rpi4-sd, coder → coder-rpi5-sd).
4445

4546
.PHONY: build-rpi4
4647
build-rpi4: ## Build an SD card image for Raspberry Pi 4 (MIXTAPE=coder by default)
@@ -51,6 +52,15 @@ flash-rpi4: ## Flash RPi4 SD image to an SD card (SSH_KEY=~/.ssh/id_ed25519.pub
5152
@./scripts/flash-rpi.sh --board rpi4 \
5253
$(if $(SSH_KEY),--ssh-key $(SSH_KEY))
5354

55+
.PHONY: build-rpi5
56+
build-rpi5: ## Build an SD card image for Raspberry Pi 5 (MIXTAPE=coder by default)
57+
nix build .#packages.aarch64-linux.$(MIXTAPE)-rpi5-sd --impure -o result-rpi5
58+
59+
.PHONY: flash-rpi5
60+
flash-rpi5: ## Flash RPi5 SD image to an SD card (SSH_KEY=~/.ssh/id_ed25519.pub optional)
61+
@./scripts/flash-rpi.sh --board rpi5 \
62+
$(if $(SSH_KEY),--ssh-key $(SSH_KEY))
63+
5464
# -- VM development operations ------------------------------------------------
5565

5666
.PHONY: run

flake.lock

Lines changed: 17 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

flake.nix

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,19 @@
55
nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11";
66
nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
77
flake-parts.url = "github:hercules-ci/flake-parts";
8+
9+
# Raspberry Pi 4 / 5 configuration. The Pi 5 module sets
10+
# boot.kernelPackages to the rpi-vendor 6.12.x kernel (built with
11+
# bcm2712_defconfig and the RP1-southbridge initrd modules); without
12+
# this input there is no Pi 5 kernel in nixpkgs at our pinned rev.
13+
#
14+
# Pinned to f1b7ff92cdd1 — the last commit before nixos-hardware#1841
15+
# replaced the kernel's postConfigure sed with `LOCALVERSION = freeform ""`,
16+
# which expands through nixpkgs' kernel-config emitter as the literal
17+
# two characters `""`, breaking modDirVersion at build time. Tracked
18+
# in nixos-hardware#1859; fix in #1860 is open but unmerged. Revisit
19+
# the pin once #1860 (or any later fix) lands on master.
20+
nixos-hardware.url = "github:NixOS/nixos-hardware/f1b7ff92cdd1";
821
dagger.url = "github:dagger/nix";
922
dagger.inputs.nixpkgs.follows = "nixpkgs";
1023

flake/images.nix

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,15 @@
99
# packages.<system>.<mixtape-name>-kernel-artifacts (direct-kernel boot)
1010
# packages.<system>.<mixtape-name>-dist (all formats + mixtape.toml)
1111
#
12-
# RPi mixtapes only emit an SD card image:
12+
# RPi mixtapes only emit an SD card image, suffixed by board:
1313
# packages.aarch64-linux.<mixtape-name>-rpi4-sd (Pi 4 SD image)
14+
# packages.aarch64-linux.<mixtape-name>-rpi5-sd (Pi 5 SD image)
1415
#
1516
# Build with:
1617
# nix build .#packages.aarch64-linux.coder --impure
1718
# nix build .#packages.x86_64-linux.coder --impure
1819
# nix build .#packages.aarch64-linux.coder-rpi4-sd --impure
20+
# nix build .#packages.aarch64-linux.coder-rpi5-sd --impure
1921

2022
{ self, inputs, ... }:
2123

@@ -45,6 +47,28 @@ let
4547
{ name = "coder-rpi4-dev"; features = [ ../mixtapes/coder/package.nix ]; extraModules = [ ../profiles/rpi.nix ../profiles/dev.nix ]; }
4648
];
4749

50+
# RPi 5 mixtape definitions — aarch64-only, SD image output.
51+
# Each spec sets stereos.rpi.series = "rpi5" inline so modules/rpi.nix
52+
# writes the Pi 5 firmware partition + [pi5] config.txt block, and pulls
53+
# in nixos-hardware.raspberry-pi-5 for the rpi-vendor 6.12.x kernel
54+
# (nixpkgs has no Pi 5 kernel package at our pinned rev).
55+
rpi5MixtapeSpecs =
56+
let
57+
rpi5Modules = [
58+
../profiles/rpi.nix
59+
{ stereos.rpi.series = "rpi5"; }
60+
inputs.nixos-hardware.nixosModules.raspberry-pi-5
61+
# Skip modules that all-hardware.nix lists but the rpi-vendor
62+
# kernel builds as =y. See modules/rpi5-kernel-overlay.nix.
63+
../modules/rpi5-kernel-overlay.nix
64+
];
65+
in [
66+
{ name = "base-rpi5"; features = [ ../mixtapes/base/package.nix ]; extraModules = rpi5Modules; }
67+
{ name = "coder-rpi5"; features = [ ../mixtapes/coder/package.nix ]; extraModules = rpi5Modules; }
68+
{ name = "base-rpi5-dev"; features = [ ../mixtapes/base/package.nix ]; extraModules = rpi5Modules ++ [ ../profiles/dev.nix ]; }
69+
{ name = "coder-rpi5-dev"; features = [ ../mixtapes/coder/package.nix ]; extraModules = rpi5Modules ++ [ ../profiles/dev.nix ]; }
70+
];
71+
4872
# Helper to build packages for a given system
4973
buildSystemImages = system:
5074
let
@@ -115,8 +139,9 @@ let
115139
)
116140
else {};
117141
rpi4Pkgs = mkSdImagePkgs rpi4MixtapeSpecs;
142+
rpi5Pkgs = mkSdImagePkgs rpi5MixtapeSpecs;
118143
in
119-
rawPkgs // qcow2Named // kernelArtifactsNamed // distPkgs // rpi4Pkgs;
144+
rawPkgs // qcow2Named // kernelArtifactsNamed // distPkgs // rpi4Pkgs // rpi5Pkgs;
120145

121146
# Build packages for all target systems
122147
allPackages = builtins.listToAttrs (

modules/rpi5-kernel-overlay.nix

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# modules/rpi5-kernel-overlay.nix
2+
#
3+
# Pi-5-only overlay: tell makeModulesClosure to skip modules listed in
4+
# boot.initrd.availableKernelModules that are absent from the rpi-vendor
5+
# kernel's /lib/modules tree.
6+
#
7+
# Why this is needed: nixpkgs' installer/sd-card/sd-image-aarch64.nix
8+
# transitively imports profiles/all-hardware.nix, which sets a giant
9+
# boot.initrd.availableKernelModules list (dw_hdmi, drm_kms_helper,
10+
# pwm-bcm2835, …). The rpi-vendor 6.12.x kernel built with
11+
# bcm2712_defconfig compiles many of those as =y — they live in vmlinuz
12+
# rather than as separate .ko files, so modprobe errors out with
13+
#
14+
# modprobe: FATAL: Module dw-hdmi not found in directory ...
15+
#
16+
# during the `modules-shrunk` (makeModulesClosure) derivation, killing
17+
# the SD-image build before it assembles the initrd.
18+
#
19+
# Skipping them in the closure is safe because they're already linked
20+
# into the kernel image and auto-loaded by the kernel; there is no
21+
# corresponding action for the initrd to take.
22+
#
23+
# This is the canonical pattern: nvmd/nixos-raspberrypi applies the same
24+
# overlay unconditionally for every Pi variant. We scope it to Pi 5
25+
# builds (Pi 4 still uses the standard sd-image-aarch64 kernel and works
26+
# without the override).
27+
#
28+
# Refs:
29+
# https://github.com/NixOS/nixpkgs/issues/154163
30+
# https://discourse.nixos.org/t/cannot-build-raspberry-pi-sdimage-module-dw-hdmi-not-found/71804
31+
# https://github.com/nvmd/nixos-raspberrypi/blob/master/modules/raspberrypi.nix
32+
33+
{ ... }:
34+
35+
{
36+
nixpkgs.overlays = [
37+
(final: super: {
38+
makeModulesClosure = args:
39+
super.makeModulesClosure (args // { allowMissing = true; });
40+
})
41+
];
42+
}

0 commit comments

Comments
 (0)