Compare commits

...

131 commits

Author SHA1 Message Date
Travis Staton
3e8100d5e9
Merge pull request #92 from nevesenin/master
Fix "resizing" wrong partition when having two disks
2025-03-17 10:59:51 -04:00
Merten Falk
cb526994b3
Merge branch 'nix-community:master' into master 2025-03-14 10:25:17 +01:00
Travis Staton
3bfda6add7
Merge pull request #131 from JamieMagee/kernel-bump
bump 6.6.y and 6.12.y kernel versions
2025-03-02 10:15:20 -05:00
Jamie Magee
abd2352d04 bump 6.6.y and 6.12.y kernel versions
`rpi-6.6.y` went from `6.6.67` to `6.6.74`.
`rpi-6.12.y` went from `6.12.11` to `6.12.17`
2025-03-01 20:56:14 -08:00
Travis Staton
4f6706677c
Merge pull request #118 from JamieMagee/nix-flake-update
Automatically update `flake.lock` using GitHub Actions
2025-02-21 20:25:27 -05:00
Travis Staton
3e442842d3
Merge pull request #119 from jleeuwes/make-serial-console-optional
Add raspberry-pi-nix.serial-console.enable option
2025-02-21 20:23:39 -05:00
Travis Staton
b9f91f70ac
Merge pull request #124 from ElvishJerricco/upstream-uboot
use nixpkgs upstream uboot
2025-02-21 20:23:23 -05:00
Travis Staton
e4c33b4abb
Merge pull request #117 from JamieMagee/ignoreConfigErrors
Ignore kernel configuration errors
2025-02-21 20:22:56 -05:00
Merten Falk
d3c6ae3d78
Merge branch 'nix-community:master' into master 2025-02-21 10:08:31 +01:00
Will Fancher
b54486ef66 use nixpkgs upstream uboot
It's more up to date and it successfully cross compiles
2025-02-17 14:13:05 -05:00
Jeroen Leeuwestein
824ce25258 Make inclusion of console=serial0 in kernelParams (cmdline.txt) configurable 2025-02-08 20:02:07 +01:00
Travis Staton
f317116725
Merge pull request #102 from JamieMagee/linux-6_12
Drop kernel 6.10.12 in favour of 6.12.6
2025-02-07 12:30:24 -05:00
Jamie Magee
36d2ee3511 Automatically update flake.lock using GitHub Actions 2025-02-04 09:24:16 -08:00
Jamie Magee
2511824848 Ignore kernel configuration errors
Fixes #113

See https://github.com/NixOS/nixpkgs/pull/366004
2025-01-29 20:49:04 -08:00
Jamie Magee
e94b747760 Drop kernel 6.10.12 in favour of 6.12.11 2025-01-29 10:06:49 -08:00
Travis Staton
628e512d60
Merge pull request #107 from nix-community/stable-kernel
Add kernel tracking stable release
2025-01-08 12:53:00 -05:00
Travis Staton
85faa0f775
matching firmware 2025-01-08 11:59:48 -05:00
Travis Staton
340fc9e380
default to stable kernel 2025-01-08 11:55:38 -05:00
Travis Staton
25b46a0be0
add stable kernel 2025-01-08 11:54:30 -05:00
Travis Staton
6b63ee9828
Merge pull request #105 from nix-community/bump-nixpkgs
bump nixpkgs to 24.11
2025-01-06 11:34:31 -05:00
Travis Staton
f85fbd621f
bump nixpkgs to 24.11 2025-01-06 10:34:03 -05:00
Travis Staton
c776eb0a74
Merge pull request #101 from JamieMagee/linux-6_6
Update kernel from 6.6.54 to 6.6.67
2025-01-02 14:25:47 -05:00
Jamie Magee
97c51868c6 Update kernel from 6.6.54 to 6.6.67 2024-12-26 11:09:54 -08:00
empunkt
4a74a0208c Determine partition number for root partition by PARTN column 2024-11-26 13:35:07 +01:00
Travis Staton
aaec735faf
add stability note 2024-11-18 09:57:23 -05:00
Travis Staton
3a016ff26c
Merge pull request #79 from nix-community/flexible-partition-table-and-fs
Allow other partition tables and filesystems
2024-11-12 18:23:49 -05:00
Travis Staton
848c5add7f
readme tweaks 2024-11-12 12:36:49 -05:00
Travis Staton
b7c3578710
move comment 2024-11-12 12:31:36 -05:00
Travis Staton
beb01f006a
add firmware-partition-label option 2024-11-11 11:50:43 -05:00
Travis Staton
61d43e92fd
use config.system.boot.loader.kernelFile 2024-11-04 22:57:26 -05:00
Travis Staton
5c1f3831f9
Merge remote-tracking branch 'origin/master' into flexible-partition-table-and-fs 2024-11-04 22:55:15 -05:00
Travis Staton
57e8e8e842
Merge pull request #82 from nix-community/kernel-override
only mention rpi-kernels when overriding kernel
2024-11-04 22:50:17 -05:00
Travis Staton
ecc8ca530d
only mention rpi-kernels when overriding kernel
so that migrations / sd-image building work if there are additional kernel
overrides
2024-11-04 22:43:44 -05:00
Travis Staton
f872d7748f
shuffle kernel params 2024-11-03 21:58:22 -05:00
Travis Staton
ee53143215
add initrd 2024-11-03 21:58:22 -05:00
Travis Staton
d039a262ce
disable sd-image 2024-11-03 21:58:21 -05:00
Travis Staton
db08995cd6
Merge pull request #74 from pta2002/fix-dt-param 2024-10-20 17:47:36 -04:00
Pedro Alves
50a273f172 allow empty base dtparams 2024-10-19 16:07:01 +01:00
Travis Staton
9126fc5c04
Merge pull request #73 from nix-community/bump-deps
bump deps
2024-10-07 19:15:50 -04:00
Travis Staton
4501cff529 bump deps 2024-10-07 19:15:16 -04:00
Travis Staton
d342e97d25
Merge pull request #68 from SebTM/example_pipewire 2024-09-20 09:08:51 -04:00
Sebastian Sellmeier
81707d7230
example: add pipewire 2024-09-20 13:52:24 +02:00
Travis Staton
90ff6a72a9
remove somewhat off-topic details about setting up a substituter 2024-09-19 19:36:24 -04:00
Travis Staton
351301b1a1
Merge pull request #64 from nix-community/tag-fix
fixes #63: don't use tag with + in it
2024-09-12 16:41:08 -04:00
Travis Staton
5e9607fa18
fixes #63: don't use tag with + in it 2024-09-12 16:39:16 -04:00
Travis Staton
3236d867b3
Merge pull request #59 from adminy/master
packages version bump
2024-09-11 20:46:58 -04:00
adminy
0ffba0a5bf chore: packages version bump 2024-09-10 14:35:02 +01:00
Travis Staton
97c85054d1
Merge pull request #54 from dorkeline/fix-stray-quote 2024-08-24 13:57:59 -04:00
Travis Staton
d37f25bf2a
Merge pull request #55 from dorkeline/uboot-add-package-option-2 2024-08-24 13:56:43 -04:00
dorkeline
3fbf836224 uboot: remove mistakenly added line 2024-08-23 20:20:53 +02:00
dorkeline
80df3d197e uboot: fix a pkgs.uboot use in the migration script i didnt catch 2024-08-23 10:59:23 +02:00
dorkeline
8efedea712 migration: fix stray quote
Introduced in a993f0c but likely flew under the radar due to eval caching?
2024-08-23 09:28:26 +02:00
Travis Staton
ba595e6b0a
Merge pull request #51 from dorkeline/uboot-add-package-option
uboot: add package option
2024-08-22 09:23:08 -04:00
dorkeline
9b56cda093 uboot: add package option 2024-08-22 11:29:45 +02:00
Travis Staton
a993f0cd59
Merge pull request #46 from SebTM/uboot_optional
uboot: do not reference package if uboot disabled
2024-08-18 10:20:52 -04:00
Travis Staton
9c0181f876
Merge pull request #45 from SebTM/flake_libcamera-check
libcamera: add flake-check to binary-cache via buildbot
2024-08-18 10:19:34 -04:00
Sebastian Sellmeier
98b74ed7f2
uboot: do not reference package if uboot disabled 2024-08-17 19:54:49 +02:00
Sebastian Sellmeier
7f06ac402f
libcamera: add flake-check to binary-cache via buildbot 2024-08-17 19:34:36 +02:00
Travis Staton
6d61a9b18b
Merge pull request #42 from seaweed-generation/unstable-libcamera
Fix libcamera build
2024-08-15 16:55:30 -04:00
Eli Hastings
9d173a9416 Fix libcamera build
This backports the `postPatch` change from nixpkgs to the libcamera
overlay so the build doesn't break, and also changes the rpicam-apps
overlay so it builds properly now.

The version in the libcamera overlay has been fixed to match upstream.
2024-08-01 17:06:39 +01:00
Travis Staton
35bb455fde
Merge pull request #39 from Yash-Garg/patch-1
fix: deprecated `lib.cartesianProductofSets`
2024-08-01 08:23:29 -07:00
Yash Garg
4f3e27caae
fix: deprecated lib.cartesianProductofSets 2024-07-29 18:41:39 +05:30
Travis Staton
be1defc74e
Merge pull request #38 from nix-community/example-config-check
add example image to packages and CI
2024-07-27 10:37:01 -04:00
Travis Staton
4ecdee4572 update readme 2024-07-27 10:35:45 -04:00
Travis Staton
0dfdbce026 add example image to packages and CI 2024-07-27 10:14:13 -04:00
Travis Staton
953aca9361 add flake checks
flatten kernel attrset in order to adhere to flake spec
2024-07-26 20:51:21 -04:00
Travis Staton
336a0cf070 remove outdated comment 2024-07-26 09:07:18 -04:00
Travis Staton
3375c37c2c restrict board options 2024-07-26 08:50:52 -04:00
Travis Staton
cc48d16dd4 update board doc with better link 2024-07-26 08:45:21 -04:00
Travis Staton
02b119708c Remove default board, requiring the user to specify 2024-07-26 08:44:48 -04:00
Travis Staton
b4ad649630
Merge pull request #25 from 9gel/rpi-groups
Add groups so udev rules work in parity with official rpi
2024-07-08 17:10:44 -04:00
Travis Staton
c92bd86e0a
Merge pull request #23 from adminy/upgrade-with-fixes
chore: bump libs & fix libcamera, fix upstream nixpkgs
2024-07-08 17:09:00 -04:00
adminy
25b88136ac chore: undo backlight 2024-06-28 09:37:03 +01:00
adminy
196c7f8e4b chore: build latest kernel 2024-06-28 07:53:31 +01:00
adminy
caed11b1f6 chore: remove error silencing 2024-06-25 00:12:11 +01:00
Travis Staton
4001188615 remove package comment 2024-06-24 09:26:37 -04:00
Travis Staton
16d872085f Avoid tags with + in them due to parsing bug
https://github.com/NixOS/nix/issues/6688
2024-06-24 09:24:34 -04:00
Travis Staton
4f517c83bf use final when appropriate 2024-06-24 09:21:22 -04:00
Travis Staton
7f3a320cc0 fix clobbering of all but one board per version 2024-06-24 09:20:26 -04:00
Travis Staton
f0c963957b remove overrideDerivation
It wasn't fully applied and it isn't necessary for these overrides anyway
2024-06-24 09:18:51 -04:00
Nigel Choi
f1bf6b9d9b Add groups so udev rules work in parity with official rpi 2024-06-24 21:16:30 +08:00
Travis Staton
50e36bf86a fix version lookup 2024-06-24 09:13:52 -04:00
Travis Staton
9113306d60 run nixpkgs-fmt 2024-06-24 09:11:22 -04:00
adminy
b027897628 fix: fix targets for flake, add kernel 6.6.34 2024-06-23 16:43:11 +01:00
adminy
57a532319e chore: undo dtparams, improve kernel building code 2024-06-23 02:00:09 +01:00
adminy
aa99f3a2dd chore: downgrade u-boot to stable release 2024-06-23 00:02:04 +01:00
adminy
b9c9972ec6 chore: return to stable versions, undo compression, fix libcamera version 2024-06-22 23:49:48 +01:00
adminy
4240bff280 chore: no double caching, compression now supported 2024-06-22 16:32:44 +01:00
adminy
48bb6ed6fb chore: remove unused 2024-06-19 01:06:36 +01:00
adminy
5024cc20e2 add my kernel build cache url 2024-06-19 00:32:04 +01:00
adminy
c2388c307b chore: bump libs & fix libcamera, fix upstream nixpkgs 2024-06-18 23:58:46 +01:00
Travis Staton
6045de5f79 default uboot to false 2024-06-17 18:56:27 -04:00
Travis Staton
f3eb50ea39 expose more packages 2024-06-17 18:56:27 -04:00
Travis Staton
d77a2ae4ed optionally pin all inputs 2024-06-17 18:56:27 -04:00
Travis Staton
1570501aba
Merge pull request #22 from MinerSebas/zstd-compressionn
Also dont use zstd for firmware compression
2024-06-16 19:38:30 -04:00
MinerSebas
8a633100aa Also dont use zstd for firmware compression 2024-06-16 16:40:53 +02:00
Travis Staton
26d6ba2a91 remove references to unpinned kernel 2024-05-21 09:29:02 -04:00
Travis Staton
cf9500ba4c bump flake 2024-05-14 18:10:43 -04:00
Travis Staton
bacb0f119a add pin-kernel option 2024-05-13 22:03:05 -04:00
Travis Staton
e858a137fd bump rpi sources 2024-05-13 21:55:55 -04:00
Travis Staton
8fc9cbd3e4 pin kernel 2024-05-13 21:55:43 -04:00
Travis Staton
b39b556e8a
Merge pull request #12 from tstat/pi-5
Add rpi-5 compatibility
2024-03-19 09:38:49 -04:00
Travis Staton
9405f0c18a init script bash 2024-03-18 22:02:20 -04:00
Travis Staton
bc745f7dc1 document new options 2024-03-18 20:46:27 -04:00
Travis Staton
adf670acf2 don't hardcode root partition uuid 2024-03-18 20:28:46 -04:00
Travis Staton
462167cc93 add udev rules 2024-03-18 20:28:46 -04:00
Travis Staton
19a8570ec9 booting 2024-03-18 20:28:46 -04:00
Travis Staton
b1ac1e98cd readme tweak 2024-02-22 10:17:49 -05:00
Travis Staton
7f3e7cca31 docs 2024-02-22 10:13:12 -05:00
Travis Staton
75c155b9af
Merge pull request #10 from RCMast3r/master
adding cachix usage blurb to readme
2024-02-22 09:54:58 -05:00
Ben Hall
42b98aecd6 adding cachix usage blurb to readme 2024-02-20 15:08:02 -05:00
Travis Staton
9c35dd99cf move libcamera stuff into a separate overlay 2024-01-23 22:02:11 -05:00
Travis Staton
2e2c5b13fb Fix libcamera build 2024-01-23 22:02:11 -05:00
Travis Staton
fac66459b1 update u-boot 2024-01-23 22:02:11 -05:00
Travis Staton
efdc6f6816 update bluetooth firmware path 2024-01-23 22:02:11 -05:00
Travis Staton
9c8a4fc486 bump kernel, firmware, and libcamera/libcamera-apps 2024-01-23 22:02:11 -05:00
Travis Staton
409f6368c6
add license 2023-09-14 09:10:55 -04:00
Travis Staton
9f536c07d1 Revert "enable uart console for kernel"
This reverts commit 5f94c31db1.

fixes #6

ttyAMA0 controls uart0, which can be used for bluetooth. If it is used
for bluetooth then we don't want to write a bunch of garbage to it.
2023-07-03 21:45:03 -04:00
Travis Staton
24f5b92db8 add hardware.raspberrypi.config-generated option
outputs the generated config as text
2023-06-23 20:04:00 -04:00
Travis Staton
6e0da67830 add option to turn off migration service 2023-06-23 20:00:03 -04:00
Travis Staton
23faa56e6c Revert "bump u-boot"
This reverts commit 434b3367ac.
2023-06-19 14:11:11 -04:00
Travis Staton
434b3367ac bump u-boot 2023-06-19 12:10:20 -04:00
Travis Staton
5f94c31db1 enable uart console for kernel
serial0 is symlinked to ttyAMA0 on rpi's distro, but I don't know
exactly what is supposed to create that, and it isn't happening here.

Something to look into, but this works for now.
2023-06-16 09:38:50 -04:00
Travis Staton
4e4ed46f15 removed this too eagerly
compressing the firmware still breaks my zero-2-w
2023-06-16 09:35:17 -04:00
Travis Staton
da5b77e661
Merge pull request #5 from tstat/kernel-6.1
Kernel 6.1
2023-06-12 10:48:34 -04:00
Travis Staton
92e2a3b15f add docs for KUNIT setting 2023-06-12 10:44:29 -04:00
Travis Staton
7c6fa52715 set linux and firmware to latest release tag
disable KUNIT in kernel config
2023-06-12 09:53:24 -04:00
Travis Staton
43258812a1 update flake inputs 2023-06-10 07:22:03 -04:00
Travis Staton
561355cba6 add cache to example 2023-05-30 17:55:28 -04:00
Travis Staton
4d207117b7 add example link to readme 2023-05-24 21:28:20 -04:00
Travis Staton
a1b4cadb53 populate firmware partition via systemd service
Only copy files from modified packages.
2023-05-24 18:46:53 -04:00
16 changed files with 1102 additions and 499 deletions

23
.github/workflows/update-flake-lock.yml vendored Normal file
View file

@ -0,0 +1,23 @@
name: update-flake-lock
on:
workflow_dispatch:
schedule:
- cron: '0 0 * * 0'
permissions:
contents: write
pull-requests: write
jobs:
lockfile:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- name: Install nix
uses: DeterminateSystems/nix-installer-action@e50d5f73bfe71c2dd0aa4218de8f4afa59f8f81d # v16
- name: Update flake.lock
uses: DeterminateSystems/update-flake-lock@a2bbe0274e3a0c4194390a1e445f734c597ebc37 # v24

21
LICENSE Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2023 Travis Staton
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

146
README.md
View file

@ -17,64 +17,29 @@ The important modules are `overlay/default.nix`, `rpi/default.nix`,
and `rpi/config.nix`. The other modules are mostly wrappers that set
`config.txt` settings and enable required kernel modules.
## Stability note
`master` is the development branch -- if you want to avoid breaking changes, you
should pin your flake to a specific release and refer to the release notes when
upgrading.
## Example
```nix
{
description = "raspberry-pi-nix example";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-22.11";
raspberry-pi-nix.url = "github:tstat/raspberry-pi-nix";
};
See the `rpi-example` config in this flake for an example config built by CI.
outputs = { self, nixpkgs, raspberry-pi-nix }:
let
inherit (nixpkgs.lib) nixosSystem;
basic-config = { pkgs, lib, ... }: {
time.timeZone = "America/New_York";
users.users.root.initialPassword = "root";
networking = {
hostName = "basic-example";
useDHCP = false;
interfaces = { wlan0.useDHCP = true; };
};
environment.systemPackages = with pkgs; [ bluez bluez-tools ];
hardware = {
bluetooth.enable = true;
raspberry-pi = {
config = {
all = {
base-dt-params = {
# enable autoprobing of bluetooth driver
# https://github.com/raspberrypi/linux/blob/c8c99191e1419062ac8b668956d19e788865912a/arch/arm/boot/dts/overlays/README#L222-L224
krnbt = {
enable = true;
value = "on";
};
};
};
};
};
};
};
in {
nixosConfigurations = {
rpi-example = nixosSystem {
system = "aarch64-linux";
modules = [ raspberry-pi-nix.nixosModules.raspberry-pi basic-config ];
};
};
};
}
```
## Using the provided cache to avoid compiling linux
This repo uses the raspberry pi linux kernel fork, and compiling linux takes a
while. CI pushes kernel builds to the nix-community cachix cache that you may
use to avoid compiling linux yourself. The cache can be found at
https://nix-community.cachix.org, and you can follow the instructions there
to use this cache.
## Building an sd-card image
An image suitable for flashing to an sd-card can be found at the
attribute `config.system.build.sdImage`. For example, if you wanted to
build an image for `rpi-example` in the above configuration
example you could run:
Include the provided `sd-image` nixos module this flake provides, then an image
suitable for flashing to an sd-card can be found at the attribute
`config.system.build.sdImage`. For example, if you wanted to build an image for
`rpi-example` in the above configuration example you could run:
```
nix build '.#nixosConfigurations.rpi-example.config.system.build.sdImage'
@ -82,21 +47,21 @@ nix build '.#nixosConfigurations.rpi-example.config.system.build.sdImage'
## The firmware partition
The image produced by this package is partitioned in the same way as
the aarch64 installation media from nixpkgs: There is a firmware
partition that contains necessary firmware, u-boot, and
config.txt. Then there is another partition (labeled `NIXOS_SD`) that
contains everything else. The firmware and `config.txt` file are
managed by NixOS modules defined in this package. Additionally, NixOS
system activation will update the firmware and `config.txt` in the
firmware partition __in place__. Linux kernels are stored in the
`NIXOS_SD` partition and will be booted by u-boot in the firmware
partition.
The image produced by this package is partitioned in the same way as the aarch64
installation media from nixpkgs: There is a firmware partition that contains
necessary firmware, the kernel or u-boot, and config.txt. Then there is another
partition (labeled `NIXOS_SD`) that contains everything else. The firmware and
`config.txt` file are managed by NixOS modules defined in this
package. Additionally, a systemd service will update the firmware and
`config.txt` in the firmware partition __in place__. If uboot is enabled then
linux kernels are stored in the `NIXOS_SD` partition and will be booted by
u-boot in the firmware partition.
## `config.txt` generation
As noted, the `config.txt` file is generated by the NixOS
configuration and automatically updated on system activation.
configuration and automatically updated on when the nix configuration
is modified.
The relevant nixos option is
`hardware.raspberry-pi.config`. Configuration is partitioned into
@ -225,37 +190,36 @@ nix build '.#nixosConfigurations.rpi-example.config.hardware.raspberry-pi.config
## Firmware partition implementation notes
In Raspberry Pi devices the proprietary firmware manipulates the
device tree in a number of ways before handing it off to the kernel
(or in our case, to u-boot). The transformations that are performed
aren't documented so well (although I have found [this
list](https://forums.raspberrypi.com/viewtopic.php?t=329799#p1974233)
).
In Raspberry Pi devices the proprietary firmware manipulates the device tree in
a number of ways before handing it off to the kernel (or in our case, to
u-boot). The transformations that are performed aren't documented so well
(although I have found [this
list](https://forums.raspberrypi.com/viewtopic.php?t=329799#p1974233) ).
This manipulation makes it difficult to use the device tree configured
directly by NixOS as the proprietary firmware's manipulation must be
known and reproduced.
This manipulation makes it difficult to use the device tree configured directly
by NixOS as the proprietary firmware's manipulation must be known and
reproduced.
Even if the manipulation were successfully reproduced, some benefits
would be lost. For example, the firmware can detect connected hardware
during boot and automatically configure the device tree accordingly
before passing it onto the kernel. If this firmware device tree is
ignored then a NixOS system rebuild with a different device tree would
be required when swapping connected hardware. Examples of what I mean
by hardware include: the specific Raspberry Pi device booting the
image, connected cameras, and connected displays.
Even if the manipulation were successfully reproduced, some benefits would be
lost. For example, the firmware can detect connected hardware during boot and
automatically configure the device tree accordingly before passing it onto the
kernel. If this firmware device tree is ignored then a NixOS system rebuild with
a different device tree would be required when swapping connected
hardware. Examples of what I mean by hardware include: the specific Raspberry Pi
device booting the image, connected cameras, and connected displays.
So, in order to avoid the headaches associated with failing to
reproduce some firmware device tree manipulation, and to reap the
benefits afforded by the firmware device tree configuration, u-boot is
configured to use the device tree that it is given (i.e. the one that
the raspberry pi firmware loads and manipulates). As a consequence,
device tree configuration is controlled via the [config.txt
So, in order to avoid the headaches associated with failing to reproduce some
firmware device tree manipulation, and to reap the benefits afforded by the
firmware device tree configuration, the bootloader is configured to use the
device tree that it is given (i.e. the one that the raspberry pi firmware loads
and manipulates). As a consequence, device tree configuration is controlled via
the [config.txt
file](https://www.raspberrypi.com/documentation/computers/config_txt.html).
Additionally, the firmware, device trees, and overlays from the
`raspberrypifw` package populate the firmware partition on system
activation. This package is kept up to date by the overlay applied by
this package, so you don't need configure this. However, if you want
to use different firmware you can override that package to do so.
Additionally, the firmware, device trees, and overlays from the `raspberrypifw`
package populate the firmware partition. This package is kept up to date by the
overlay applied by this package, so you don't need configure this. However, if
you want to use different firmware you can override that package to do so.
## What's not working?
- [ ] Pi 5 u-boot devices other than sd-cards (i.e. usb, nvme).

44
example/default.nix Normal file
View file

@ -0,0 +1,44 @@
{ pkgs, lib, ... }: {
time.timeZone = "America/New_York";
users.users.root.initialPassword = "root";
networking = {
hostName = "example";
useDHCP = false;
interfaces = {
wlan0.useDHCP = true;
eth0.useDHCP = true;
};
};
raspberry-pi-nix.board = "bcm2711";
hardware = {
raspberry-pi = {
config = {
all = {
base-dt-params = {
BOOT_UART = {
value = 1;
enable = true;
};
uart_2ndstage = {
value = 1;
enable = true;
};
};
dt-overlays = {
disable-bt = {
enable = true;
params = { };
};
};
};
};
};
};
security.rtkit.enable = true;
services.pipewire = {
enable = true;
alsa.enable = true;
alsa.support32Bit = true;
pulse.enable = true;
};
}

138
flake.lock generated
View file

@ -1,45 +1,82 @@
{
"nodes": {
"libcamera-apps-src": {
"libcamera-src": {
"flake": false,
"locked": {
"lastModified": 1674645888,
"narHash": "sha256-UBTDHN0lMj02enB8im4Q+f/MCm/G2mFPP3pLImrZc5A=",
"lastModified": 1725630279,
"narHash": "sha256-KH30jmHfxXq4j2CL7kv18DYECJRp9ECuWNPnqPZajPA=",
"owner": "raspberrypi",
"repo": "libcamera-apps",
"rev": "9f08463997b82c4bf60e12c4ea43577959a8ae15",
"repo": "libcamera",
"rev": "69a894c4adad524d3063dd027f5c4774485cf9db",
"type": "github"
},
"original": {
"owner": "raspberrypi",
"ref": "v1.1.1",
"repo": "libcamera-apps",
"repo": "libcamera",
"rev": "69a894c4adad524d3063dd027f5c4774485cf9db",
"type": "github"
}
},
"libpisp-src": {
"flake": false,
"locked": {
"lastModified": 1724944683,
"narHash": "sha256-Fo2UJmQHS855YSSKKmGrsQnJzXog1cdpkIOO72yYAM4=",
"owner": "raspberrypi",
"repo": "libpisp",
"rev": "28196ed6edcfeda88d23cc5f213d51aa6fa17bb3",
"type": "github"
},
"original": {
"owner": "raspberrypi",
"ref": "v1.0.7",
"repo": "libpisp",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1736061677,
"narHash": "sha256-DjkQPnkAfd7eB522PwnkGhOMuT9QVCZspDpJJYyOj60=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "cbd8ec4de4469333c82ff40d057350c30e9f7d36",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-24.11",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"libcamera-apps-src": "libcamera-apps-src",
"libcamera-src": "libcamera-src",
"libpisp-src": "libpisp-src",
"nixpkgs": "nixpkgs",
"rpi-bluez-firmware-src": "rpi-bluez-firmware-src",
"rpi-firmware-nonfree-src": "rpi-firmware-nonfree-src",
"rpi-firmware-stable-src": "rpi-firmware-stable-src",
"rpi-linux-5_15-src": "rpi-linux-5_15-src",
"rpi-linux-5_15_87-src": "rpi-linux-5_15_87-src",
"u-boot-src": "u-boot-src"
"rpi-firmware-src": "rpi-firmware-src",
"rpi-linux-6_12_17-src": "rpi-linux-6_12_17-src",
"rpi-linux-6_6_78-src": "rpi-linux-6_6_78-src",
"rpi-linux-stable-src": "rpi-linux-stable-src",
"rpicam-apps-src": "rpicam-apps-src"
}
},
"rpi-bluez-firmware-src": {
"flake": false,
"locked": {
"lastModified": 1672928175,
"narHash": "sha256-gKGK0XzNrws5REkKg/JP6SZx3KsJduu53SfH3Dichkc=",
"lastModified": 1708969706,
"narHash": "sha256-KakKnOBeWxh0exu44beZ7cbr5ni4RA9vkWYb9sGMb8Q=",
"owner": "RPi-Distro",
"repo": "bluez-firmware",
"rev": "9556b08ace2a1735127894642cc8ea6529c04c90",
"rev": "78d6a07730e2d20c035899521ab67726dc028e1c",
"type": "github"
},
"original": {
"owner": "RPi-Distro",
"ref": "bookworm",
"repo": "bluez-firmware",
"type": "github"
}
@ -47,80 +84,103 @@
"rpi-firmware-nonfree-src": {
"flake": false,
"locked": {
"lastModified": 1674638139,
"narHash": "sha256-54JKmwypD7PRQdd7k6IcF7wL8ifMavEM0UwZwmA24O4=",
"lastModified": 1723266537,
"narHash": "sha256-T7eTKXqY9cxEMdab8Snda4CEOrEihy5uOhA6Fy+Mhnw=",
"owner": "RPi-Distro",
"repo": "firmware-nonfree",
"rev": "7f29411baead874b859eda53efdc2472345ea454",
"rev": "4b356e134e8333d073bd3802d767a825adec3807",
"type": "github"
},
"original": {
"owner": "RPi-Distro",
"ref": "bookworm",
"repo": "firmware-nonfree",
"type": "github"
}
},
"rpi-firmware-stable-src": {
"rpi-firmware-src": {
"flake": false,
"locked": {
"lastModified": 1673003776,
"narHash": "sha256-tdaH+zZwmILNFBge2gMqtzj/1Hydj9cxhPvhw+7jTrU=",
"lastModified": 1728405098,
"narHash": "sha256-4gnK0KbqFnjBmWia9Jt2gveVWftmHrprpwBqYVqE/k0=",
"owner": "raspberrypi",
"repo": "firmware",
"rev": "78852e166b4cf3ebb31d051e996d54792f0994b0",
"rev": "7bbb5f80d20a2335066a8781459c9f33e5eebc64",
"type": "github"
},
"original": {
"owner": "raspberrypi",
"ref": "stable",
"ref": "1.20241008",
"repo": "firmware",
"type": "github"
}
},
"rpi-linux-5_15-src": {
"rpi-linux-6_12_17-src": {
"flake": false,
"locked": {
"lastModified": 1675874870,
"narHash": "sha256-oy+VgoB4IdFZjGwkx88dDSpwWZj2D5t3PyXPIwDsY1Q=",
"lastModified": 1740765145,
"narHash": "sha256-hoCsGc4+RC/2LmxDtswLBL5ZhWlw4vSiL4Vkl39r2MU=",
"owner": "raspberrypi",
"repo": "linux",
"rev": "14b35093ca68bf2c81bbc90aace5007142b40b40",
"rev": "5985ce32e511f4e8279a841a1b06a8c7d972b386",
"type": "github"
},
"original": {
"owner": "raspberrypi",
"ref": "rpi-5.15.y",
"ref": "rpi-6.12.y",
"repo": "linux",
"type": "github"
}
},
"rpi-linux-5_15_87-src": {
"rpi-linux-6_6_78-src": {
"flake": false,
"locked": {
"lastModified": 1673628667,
"narHash": "sha256-hNLVfhalmRhhRfvu2mR/qDmmGl//Ic1eqR7N1HFj2CY=",
"lastModified": 1740503700,
"narHash": "sha256-Y8+ot4Yi3UKwlZK3ap15rZZ16VZDvmeFkD46+6Ku7bE=",
"owner": "raspberrypi",
"repo": "linux",
"rev": "da4c8e0ffe7a868b989211045657d600be3046a1",
"rev": "2e071057fded90e789c0101498e45a1778be93fe",
"type": "github"
},
"original": {
"owner": "raspberrypi",
"ref": "rpi-6.6.y",
"repo": "linux",
"rev": "da4c8e0ffe7a868b989211045657d600be3046a1",
"type": "github"
}
},
"u-boot-src": {
"rpi-linux-stable-src": {
"flake": false,
"locked": {
"narHash": "sha256-30fe8klLHRsEtEQ1VpYh4S+AflG5yCQYWlGmpWyFL8w=",
"type": "tarball",
"url": "https://ftp.denx.de/pub/u-boot/u-boot-2023.01.tar.bz2"
"lastModified": 1728403745,
"narHash": "sha256-phCxkuO+jUGZkfzSrBq6yErQeO2Td+inIGHxctXbD5U=",
"owner": "raspberrypi",
"repo": "linux",
"rev": "5aeecea9f4a45248bcf564dec924965e066a7bfd",
"type": "github"
},
"original": {
"type": "tarball",
"url": "https://ftp.denx.de/pub/u-boot/u-boot-2023.01.tar.bz2"
"owner": "raspberrypi",
"ref": "stable_20241008",
"repo": "linux",
"type": "github"
}
},
"rpicam-apps-src": {
"flake": false,
"locked": {
"lastModified": 1727515047,
"narHash": "sha256-qCYGrcibOeGztxf+sd44lD6VAOGoUNwRqZDdAmcTa/U=",
"owner": "raspberrypi",
"repo": "rpicam-apps",
"rev": "a8ccf9f3cd9df49875dfb834a2b490d41d226031",
"type": "github"
},
"original": {
"owner": "raspberrypi",
"ref": "v1.5.2",
"repo": "rpicam-apps",
"type": "github"
}
}
},

View file

@ -2,34 +2,90 @@
description = "raspberry-pi nixos configuration";
inputs = {
u-boot-src = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11";
rpi-linux-stable-src = {
flake = false;
url = "https://ftp.denx.de/pub/u-boot/u-boot-2023.01.tar.bz2";
url = "github:raspberrypi/linux/stable_20241008";
};
rpi-linux-5_15-src = {
rpi-linux-6_6_78-src = {
flake = false;
url = "github:raspberrypi/linux/rpi-5.15.y";
url = "github:raspberrypi/linux/rpi-6.6.y";
};
rpi-firmware-stable-src = {
rpi-linux-6_12_17-src = {
flake = false;
url = "github:raspberrypi/firmware/stable";
url = "github:raspberrypi/linux/rpi-6.12.y";
};
rpi-firmware-src = {
flake = false;
url = "github:raspberrypi/firmware/1.20241008";
};
rpi-firmware-nonfree-src = {
flake = false;
url = "github:RPi-Distro/firmware-nonfree";
url = "github:RPi-Distro/firmware-nonfree/bookworm";
};
rpi-bluez-firmware-src = {
flake = false;
url = "github:RPi-Distro/bluez-firmware";
url = "github:RPi-Distro/bluez-firmware/bookworm";
};
libcamera-apps-src = {
rpicam-apps-src = {
flake = false;
url = "github:raspberrypi/libcamera-apps/v1.1.1";
url = "github:raspberrypi/rpicam-apps/v1.5.2";
};
libcamera-src = {
flake = false;
url = "github:raspberrypi/libcamera/69a894c4adad524d3063dd027f5c4774485cf9db"; # v0.3.1+rpt20240906
};
libpisp-src = {
flake = false;
url = "github:raspberrypi/libpisp/v1.0.7";
};
};
outputs = srcs@{ self, ... }: {
overlay = import ./overlay (builtins.removeAttrs srcs [ "self" ]);
nixosModules.raspberry-pi = import ./rpi { overlay = self.overlay; };
outputs = srcs@{ self, ... }:
let
pinned = import srcs.nixpkgs {
system = "aarch64-linux";
overlays = with self.overlays; [ core libcamera ];
};
in
{
overlays = {
core = import ./overlays (builtins.removeAttrs srcs [ "self" ]);
libcamera = import ./overlays/libcamera.nix (builtins.removeAttrs srcs [ "self" ]);
};
nixosModules = {
raspberry-pi = import ./rpi {
inherit pinned;
core-overlay = self.overlays.core;
libcamera-overlay = self.overlays.libcamera;
};
sd-image = import ./sd-image;
};
nixosConfigurations = {
rpi-example = srcs.nixpkgs.lib.nixosSystem {
system = "aarch64-linux";
modules = [ self.nixosModules.raspberry-pi self.nixosModules.sd-image ./example ];
};
};
checks.aarch64-linux = self.packages.aarch64-linux;
packages.aarch64-linux = with pinned.lib;
let
kernels =
foldlAttrs f { } pinned.rpi-kernels;
f = acc: kernel-version: board-attr-set:
foldlAttrs
(acc: board-version: drv: acc // {
"linux-${kernel-version}-${board-version}" = drv;
})
acc
board-attr-set;
in
{
example-sd-image = self.nixosConfigurations.rpi-example.config.system.build.sdImage;
firmware = pinned.raspberrypifw;
libcamera = pinned.libcamera;
wireless-firmware = pinned.raspberrypiWirelessFirmware;
uboot-rpi-arm64 = pinned.uboot-rpi-arm64;
} // kernels;
};
}

View file

@ -1,82 +0,0 @@
{ u-boot-src, rpi-linux-5_15-src, rpi-firmware-stable-src
, rpi-firmware-nonfree-src, rpi-bluez-firmware-src, libcamera-apps-src }:
final: prev:
let
# The version to stick at `pkgs.rpi-kernels.latest'
latest = "v5_15_92";
# Helpers for building the `pkgs.rpi-kernels' map.
rpi-kernel = { kernel, version, fw, wireless-fw, argsOverride ? null }:
let
new-kernel = prev.linux_rpi4.override {
argsOverride = {
src = kernel;
inherit version;
modDirVersion = version;
} // (if builtins.isNull argsOverride then { } else argsOverride);
};
new-fw = prev.raspberrypifw.overrideAttrs (oldfw: { src = fw; });
new-wireless-fw = final.callPackage wireless-fw { };
version-slug = builtins.replaceStrings [ "." ] [ "_" ] version;
in {
"v${version-slug}" = {
kernel = new-kernel;
firmware = new-fw;
wireless-firmware = new-wireless-fw;
};
};
rpi-kernels = builtins.foldl' (b: a: b // rpi-kernel a) { };
in {
# disable firmware compression so that brcm firmware can be found at
# the path expected by raspberry pi firmware/device tree
compressFirmwareXz = x: x;
# A recent known working version of libcamera-apps
libcamera-apps =
final.callPackage ./libcamera-apps.nix { inherit libcamera-apps-src; };
# provide generic rpi arm64 u-boot
uboot_rpi_arm64 = prev.buildUBoot rec {
defconfig = "rpi_arm64_defconfig";
extraMeta.platforms = [ "aarch64-linux" ];
filesToInstall = [ "u-boot.bin" ];
version = "2023.01";
src = u-boot-src;
# In raspberry pi sbcs the firmware manipulates the device tree in
# a variety of ways before handing it off to the linux kernel. [1]
# Since we have installed u-boot in place of a linux kernel we may
# pass the device tree passed by the firmware onto the kernel, or
# we may provide the kernel with a device tree of our own. This
# configuration uses the device tree provided by firmware so that
# we don't have to be aware of all manipulation done by the
# firmware and attempt to mimic it.
#
# 1. https://forums.raspberrypi.com/viewtopic.php?t=329799#p1974233
extraConfig = ''
CONFIG_OF_HAS_PRIOR_STAGE=y
CONFIG_OF_BOARD=y
'';
};
# default to latest firmware
raspberrypiWirelessFirmware = final.rpi-kernels.latest.wireless-firmware;
raspberrypifw = final.rpi-kernels.latest.firmware;
} // {
# rpi kernels and firmware are available at
# `pkgs.rpi-kernels.<VERSION>.{kernel,firmware,wireless-firmware}'.
#
# For example: `pkgs.rpi-kernels.v5_15_87.kernel'
rpi-kernels = rpi-kernels [{
version = "5.15.92";
kernel = rpi-linux-5_15-src;
fw = rpi-firmware-stable-src;
wireless-fw = import ./raspberrypi-wireless-firmware.nix {
bluez-firmware = rpi-bluez-firmware-src;
firmware-nonfree = rpi-firmware-nonfree-src;
};
}] // {
latest = final.rpi-kernels."${latest}";
};
}

View file

@ -1,27 +0,0 @@
{ libcamera-apps-src, lib, stdenv, fetchFromGitHub, fetchpatch, cmake
, pkg-config, libjpeg, libtiff, libpng, libcamera, libepoxy, boost, libexif }:
stdenv.mkDerivation rec {
pname = "libcamera-apps";
version = "v1.1.0";
src = libcamera-apps-src;
nativeBuildInputs = [ cmake pkg-config ];
buildInputs = [ libjpeg libtiff libcamera libepoxy boost libexif libpng ];
cmakeFlags = [
"-DENABLE_QT=0"
"-DENABLE_OPENCV=0"
"-DENABLE_TFLITE=0"
"-DENABLE_X11=1"
"-DENABLE_DRM=1"
(if (stdenv.hostPlatform.isAarch64) then "-DARM64=ON" else "-DARM64=OFF")
];
meta = with lib; {
description = "Userland tools interfacing with Raspberry Pi cameras";
homepage = "https://github.com/raspberrypi/libcamera-apps";
license = licenses.bsd2;
platforms = [ "aarch64-linux" ];
};
}

122
overlays/default.nix Normal file
View file

@ -0,0 +1,122 @@
{ rpi-linux-stable-src
, rpi-linux-6_6_78-src
, rpi-linux-6_12_17-src
, rpi-firmware-src
, rpi-firmware-nonfree-src
, rpi-bluez-firmware-src
, ...
}:
final: prev:
let
versions = {
v6_6_51.src = rpi-linux-stable-src;
v6_6_78.src = rpi-linux-6_6_78-src;
v6_12_17 = {
src = rpi-linux-6_12_17-src;
patches = [
{
name = "remove-readme-target.patch";
patch = final.fetchpatch {
url = "https://github.com/raspberrypi/linux/commit/3c0fd51d184f1748b83d28e1113265425c19bcb5.patch";
hash = "sha256-v7uZOmPCUp2i7NGVgjqnQYe6dEBD+aATuP/oRs9jfuk=";
};
}
];
};
};
boards = [ "bcm2711" "bcm2712" ];
# Helpers for building the `pkgs.rpi-kernels' map.
rpi-kernel = { version, board }:
let
kernel = builtins.getAttr version versions;
version-slug = builtins.replaceStrings [ "v" "_" ] [ "" "." ] version;
in
{
"${version}"."${board}" = (final.buildLinux {
modDirVersion = version-slug;
version = version-slug;
pname = "linux-rpi";
src = kernel.src;
defconfig = "${board}_defconfig";
structuredExtraConfig = with final.lib.kernel; {
# The perl script to generate kernel options sets unspecified
# parameters to `m` if possible [1]. This results in the
# unspecified config option KUNIT [2] getting set to `m` which
# causes DRM_VC4_KUNIT_TEST [3] to get set to `y`.
#
# This vc4 unit test fails on boot due to a null pointer
# exception with the existing config. I'm not sure why, but in
# any case, the DRM_VC4_KUNIT_TEST config option itself states
# that it is only useful for kernel developers working on the
# vc4 driver. So, I feel no need to deviate from the standard
# rpi kernel and attempt to successfully enable this test and
# other unit tests because the nixos perl script has this
# sloppy "default to m" behavior. So, I set KUNIT to `n`.
#
# [1] https://github.com/NixOS/nixpkgs/blob/85bcb95aa83be667e562e781e9d186c57a07d757/pkgs/os-specific/linux/kernel/generate-config.pl#L1-L10
# [2] https://github.com/raspberrypi/linux/blob/1.20230405/lib/kunit/Kconfig#L5-L14
# [3] https://github.com/raspberrypi/linux/blob/bb63dc31e48948bc2649357758c7a152210109c4/drivers/gpu/drm/vc4/Kconfig#L38-L52
KUNIT = no;
};
features.efiBootStub = false;
kernelPatches =
if kernel ? "patches" then kernel.patches else [ ];
ignoreConfigErrors = true;
}).overrideAttrs
(oldAttrs: {
postConfigure = ''
# The v7 defconfig has this set to '-v7' which screws up our modDirVersion.
sed -i $buildRoot/.config -e 's/^CONFIG_LOCALVERSION=.*/CONFIG_LOCALVERSION=""/'
sed -i $buildRoot/include/config/auto.conf -e 's/^CONFIG_LOCALVERSION=.*/CONFIG_LOCALVERSION=""/'
'';
});
};
rpi-kernels = builtins.foldl'
(b: a: final.lib.recursiveUpdate b (rpi-kernel a))
{ };
in
{
# disable firmware compression so that brcm firmware can be found at
# the path expected by raspberry pi firmware/device tree
compressFirmwareXz = x: x;
compressFirmwareZstd = x: x;
# provide generic rpi arm64 u-boot
uboot-rpi-arm64 = final.buildUBoot {
defconfig = "rpi_arm64_defconfig";
extraMeta.platforms = [ "aarch64-linux" ];
filesToInstall = [ "u-boot.bin" ];
# In raspberry pi sbcs the firmware manipulates the device tree in
# a variety of ways before handing it off to the linux kernel. [1]
# Since we have installed u-boot in place of a linux kernel we may
# pass the device tree passed by the firmware onto the kernel, or
# we may provide the kernel with a device tree of our own. This
# configuration uses the device tree provided by firmware so that
# we don't have to be aware of all manipulation done by the
# firmware and attempt to mimic it.
#
# 1. https://forums.raspberrypi.com/viewtopic.php?t=329799#p1974233
};
# default to latest firmware
raspberrypiWirelessFirmware = final.callPackage
(
import ./raspberrypi-wireless-firmware.nix {
bluez-firmware = rpi-bluez-firmware-src;
firmware-nonfree = rpi-firmware-nonfree-src;
}
)
{ };
raspberrypifw = prev.raspberrypifw.overrideAttrs (oldfw: { src = rpi-firmware-src; });
} // {
# rpi kernels and firmware are available at
# `pkgs.rpi-kernels.<VERSION>.<BOARD>'.
#
# For example: `pkgs.rpi-kernels.v6_6_78.bcm2712'
rpi-kernels = rpi-kernels (
final.lib.cartesianProduct
{ board = boards; version = (builtins.attrNames versions); }
);
}

57
overlays/libcamera.nix Normal file
View file

@ -0,0 +1,57 @@
{ rpicam-apps-src
, libcamera-src
, libpisp-src
, ...
}:
final: prev: {
# A recent known working version of rpicam-apps
libcamera-apps =
final.callPackage ./rpicam-apps.nix { inherit rpicam-apps-src; };
libpisp = final.stdenv.mkDerivation {
name = "libpisp";
version = "1.0.7";
src = libpisp-src;
nativeBuildInputs = with final; [ pkg-config meson ninja ];
buildInputs = with final; [ nlohmann_json boost ];
# Meson is no longer able to pick up Boost automatically.
# https://github.com/NixOS/nixpkgs/issues/86131
BOOST_INCLUDEDIR = "${prev.lib.getDev final.boost}/include";
BOOST_LIBRARYDIR = "${prev.lib.getLib final.boost}/lib";
};
libcamera = prev.libcamera.overrideAttrs (old: {
version = "0.3.1";
src = libcamera-src;
buildInputs = old.buildInputs ++ (with final; [
libpisp
openssl
libtiff
(python3.withPackages (ps: with ps; [
python3-gnutls
pybind11
pyyaml
ply
]))
libglibutil
gst_all_1.gst-plugins-base
]);
patches = [ ];
postPatch = ''
patchShebangs src/py/ utils/
'';
mesonFlags = [
"--buildtype=release"
"-Dpipelines=rpi/vc4,rpi/pisp"
"-Dipas=rpi/vc4,rpi/pisp"
"-Dv4l2=true"
"-Dgstreamer=enabled"
"-Dtest=false"
"-Dlc-compliance=disabled"
"-Dcam=disabled"
"-Dqcam=disabled"
"-Ddocumentation=enabled"
"-Dpycamera=enabled"
];
});
}

View file

@ -1,9 +1,9 @@
{ bluez-firmware, firmware-nonfree }:
{ lib, stdenvNoCC, fetchFromGitHub }:
{ lib, stdenvNoCC }:
stdenvNoCC.mkDerivation {
pname = "raspberrypi-wireless-firmware";
version = "2023-01-19";
version = "2024-02-26";
srcs = [ ];
@ -23,7 +23,7 @@ stdenvNoCC.mkDerivation {
cp -rv "${firmware-nonfree}/debian/config/brcm80211/." "$out/lib/firmware/"
# Bluetooth firmware
cp -rv "${bluez-firmware}/broadcom/." "$out/lib/firmware/brcm"
cp -rv "${bluez-firmware}/debian/firmware/broadcom/." "$out/lib/firmware/brcm"
# brcmfmac43455-stdio.bin is a symlink to ../cypress/cyfmac43455-stdio.bin that doesn't exist
# See https://github.com/RPi-Distro/firmware-nonfree/issues/26

30
overlays/rpicam-apps.nix Normal file
View file

@ -0,0 +1,30 @@
{ rpicam-apps-src, lib, pkgs, stdenv }:
stdenv.mkDerivation {
pname = "libcamera-apps";
version = "v1.5.0";
src = rpicam-apps-src;
nativeBuildInputs = with pkgs; [ meson pkg-config ];
buildInputs = with pkgs; [ libjpeg libtiff libcamera libepoxy boost libexif libpng ffmpeg libdrm ninja ];
mesonFlags = [
"-Denable_qt=disabled"
"-Denable_opencv=disabled"
"-Denable_tflite=disabled"
"-Denable_egl=disabled"
"-Denable_hailo=disabled"
"-Denable_drm=enabled"
];
# Meson is no longer able to pick up Boost automatically.
# https://github.com/NixOS/nixpkgs/issues/86131
BOOST_INCLUDEDIR = "${lib.getDev pkgs.boost}/include";
BOOST_LIBRARYDIR = "${lib.getLib pkgs.boost}/lib";
meta = with lib; {
description = "Userland tools interfacing with Raspberry Pi cameras";
homepage = "https://github.com/raspberrypi/libcamera-apps";
license = licenses.bsd2;
platforms = [ "aarch64-linux" ];
};
}

View file

@ -1,7 +1,8 @@
{ lib, config, pkgs, ... }:
let
cfg = config.hardware.raspberry-pi;
render-raspberrypi-config = let
render-raspberrypi-config =
let
render-options = opts:
lib.strings.concatStringsSep "\n" (render-dt-kvs opts);
render-dt-param = x: "dtparam=" + x;
@ -22,10 +23,12 @@ let
(render-dt-kvs params);
render-dt-overlays = overlays:
lib.strings.concatMapStringsSep "\n" render-dt-overlay
(lib.attrsets.mapAttrsToList (k: v: {
(lib.attrsets.mapAttrsToList
(k: v: {
overlay = k;
args = render-dt-kvs v.params;
}) (lib.filterAttrs (k: v: v.enable) overlays));
})
(lib.filterAttrs (k: v: v.enable) overlays));
render-config-section = k:
{ options, base-dt-params, dt-overlays }:
let
@ -34,17 +37,21 @@ let
(render-base-dt-params base-dt-params)
(render-dt-overlays dt-overlays)
]);
in ''
in
''
[${k}]
${all-config}
'';
in conf:
in
conf:
lib.strings.concatStringsSep "\n"
(lib.attrsets.mapAttrsToList render-config-section conf);
in {
in
{
options = {
hardware.raspberry-pi = {
config = let
config =
let
rpi-config-param = {
options = {
enable = lib.mkEnableOption "attr";
@ -86,7 +93,7 @@ in {
};
};
base-dt-params = lib.mkOption {
type = with lib.types; attrsOf (submodule rpi-config-param);
type = with lib.types; attrsOf (submodule dt-param);
default = { };
example = {
i2c = {
@ -108,19 +115,30 @@ in {
};
};
};
in lib.mkOption {
in
lib.mkOption {
type = with lib.types; attrsOf (submodule raspberry-pi-config-options);
};
config-generated = lib.mkOption {
type = lib.types.str;
description = "the config text generated by raspberrypi.hardware.config";
readOnly = true;
};
config-output = lib.mkOption {
type = lib.types.package;
default = pkgs.writeTextFile {
name = "config.txt";
text = ''
# This is a generated file. Do not edit!
${render-raspberrypi-config cfg.config}
${cfg.config-generated}
'';
};
};
};
};
config = {
hardware.raspberry-pi.config-generated = render-raspberrypi-config cfg.config;
};
}

View file

@ -1,19 +1,126 @@
{ overlay }:
{ pinned, core-overlay, libcamera-overlay }:
{ lib, pkgs, config, ... }:
let
cfg = config.raspberry-pi-nix;
version = cfg.kernel-version;
board = cfg.board;
kernel = config.system.build.kernel;
initrd = "${config.system.build.initialRamdisk}/${config.system.boot.loader.initrdFile}";
in
{
imports = [ ../sd-image ./config.nix ./i2c.nix ];
imports = [ ./config.nix ./i2c.nix ];
# On activation install u-boot, Raspberry Pi firmware, and our
# generated config.txt
system.activationScripts.raspberrypi = {
options = with lib; {
raspberry-pi-nix = {
kernel-version = mkOption {
default = "v6_6_51";
type = types.str;
description = "Kernel version to build.";
};
board = mkOption {
type = types.enum [ "bcm2711" "bcm2712" ];
description = ''
The kernel board version to build.
Examples at: https://www.raspberrypi.com/documentation/computers/linux_kernel.html#native-build-configuration
without the _defconfig part.
'';
};
firmware-partition-label = mkOption {
default = "FIRMWARE";
type = types.str;
description = "label of rpi firmware partition";
};
pin-inputs = {
enable = mkOption {
default = true;
type = types.bool;
description = ''
Whether to pin the kernel to the latest cachix build.
'';
};
};
firmware-migration-service = {
enable = mkOption {
default = true;
type = types.bool;
description = ''
Whether to run the migration service automatically or not.
'';
};
};
libcamera-overlay = {
enable = mkOption {
default = true;
type = types.bool;
description = ''
If enabled then the libcamera overlay is applied which
overrides libcamera with the rpi fork.
'';
};
};
uboot = {
enable = mkOption {
default = false;
type = types.bool;
description = ''
If enabled then uboot is used as the bootloader. If disabled
then the linux kernel is installed directly into the
firmware directory as expected by the raspberry pi boot
process.
This can be useful for newer hardware that doesn't yet have
uboot compatibility or less common setups, like booting a
cm4 with an nvme drive.
'';
};
package = mkPackageOption pkgs "uboot-rpi-arm64" { };
};
serial-console = {
enable = mkOption {
default = true;
type = types.bool;
description = ''
Whether to enable a console on serial0.
Corresponds with raspi-config's setting
"Would you like a login shell to be accessible over serial?"
'';
};
};
};
};
config = {
systemd.services = {
"raspberry-pi-firmware-migrate" =
{
description = "update the firmware partition";
wantedBy = if cfg.firmware-migration-service.enable then [ "multi-user.target" ] else [ ];
serviceConfig =
let
firmware-path = "/boot/firmware";
kernel-params = pkgs.writeTextFile {
name = "cmdline.txt";
text = ''
${lib.strings.concatStringsSep " " config.boot.kernelParams}
'';
};
in
{
Type = "oneshot";
MountImages =
"/dev/disk/by-label/${cfg.firmware-partition-label}:${firmware-path}";
StateDirectory = "raspberrypi-firmware";
ExecStart = pkgs.writeShellScript "migrate-rpi-firmware" ''
shopt -s nullglob
TARGET_FIRMWARE_DIR="/boot/firmware"
TARGET_FIRMWARE_DIR="${firmware-path}"
TARGET_OVERLAYS_DIR="$TARGET_FIRMWARE_DIR/overlays"
TMPFILE="$TARGET_FIRMWARE_DIR/tmp"
UBOOT="${pkgs.uboot_rpi_arm64}/u-boot.bin"
KERNEL="${kernel}/${config.system.boot.loader.kernelFile}"
SHOULD_UBOOT=${if cfg.uboot.enable then "1" else "0"}
SRC_FIRMWARE_DIR="${pkgs.raspberrypifw}/share/raspberrypi/boot"
STARTFILES=("$SRC_FIRMWARE_DIR"/start*.elf)
DTBS=("$SRC_FIRMWARE_DIR"/*.dtb)
@ -23,25 +130,111 @@
SRC_OVERLAYS=("$SRC_OVERLAYS_DIR"/*)
CONFIG="${config.hardware.raspberry-pi.config-output}"
${lib.strings.optionalString cfg.uboot.enable ''
UBOOT="${cfg.uboot.package}/u-boot.bin"
migrate_uboot() {
echo "migrating uboot"
touch "$STATE_DIRECTORY/uboot-migration-in-progress"
cp "$UBOOT" "$TMPFILE"
mv -T "$TMPFILE" "$TARGET_FIRMWARE_DIR/u-boot-rpi-arm64.bin"
echo "${builtins.toString cfg.uboot.package}" > "$STATE_DIRECTORY/uboot-version"
rm "$STATE_DIRECTORY/uboot-migration-in-progress"
}
''}
migrate_kernel() {
echo "migrating kernel"
touch "$STATE_DIRECTORY/kernel-migration-in-progress"
cp "$KERNEL" "$TMPFILE"
mv -T "$TMPFILE" "$TARGET_FIRMWARE_DIR/kernel.img"
cp "${initrd}" "$TMPFILE"
mv -T "$TMPFILE" "$TARGET_FIRMWARE_DIR/initrd"
echo "${
builtins.toString kernel
}" > "$STATE_DIRECTORY/kernel-version"
rm "$STATE_DIRECTORY/kernel-migration-in-progress"
}
migrate_cmdline() {
echo "migrating cmdline"
touch "$STATE_DIRECTORY/cmdline-migration-in-progress"
cp "${kernel-params}" "$TMPFILE"
mv -T "$TMPFILE" "$TARGET_FIRMWARE_DIR/cmdline.txt"
echo "${
builtins.toString kernel-params
}" > "$STATE_DIRECTORY/cmdline-version"
rm "$STATE_DIRECTORY/cmdline-migration-in-progress"
}
migrate_config() {
echo "migrating config.txt"
touch "$STATE_DIRECTORY/config-migration-in-progress"
cp "$CONFIG" "$TMPFILE"
mv -T "$TMPFILE" "$TARGET_FIRMWARE_DIR/config.txt"
echo "${config.hardware.raspberry-pi.config-output}" > "$STATE_DIRECTORY/config-version"
rm "$STATE_DIRECTORY/config-migration-in-progress"
}
migrate_firmware() {
echo "migrating raspberrypi firmware"
touch "$STATE_DIRECTORY/firmware-migration-in-progress"
for SRC in "''${STARTFILES[@]}" "''${DTBS[@]}" "$BOOTCODE" "''${FIXUPS[@]}"
do
cp "$SRC" "$TMPFILE"
mv -T "$TMPFILE" "$TARGET_FIRMWARE_DIR/$(basename "$SRC")"
done
if [[ ! -d "$TARGET_OVERLAYS_DIR" ]]; then
mkdir "$TARGET_OVERLAYS_DIR"
fi
for SRC in "''${SRC_OVERLAYS[@]}"
do
cp "$SRC" "$TMPFILE"
mv -T "$TMPFILE" "$TARGET_OVERLAYS_DIR/$(basename "$SRC")"
done
echo "${
builtins.toString pkgs.raspberrypifw
}" > "$STATE_DIRECTORY/firmware-version"
rm "$STATE_DIRECTORY/firmware-migration-in-progress"
}
${lib.strings.optionalString cfg.uboot.enable ''
if [[ "$SHOULD_UBOOT" -eq 1 ]] && [[ -f "$STATE_DIRECTORY/uboot-migration-in-progress" || ! -f "$STATE_DIRECTORY/uboot-version" || $(< "$STATE_DIRECTORY/uboot-version") != ${
builtins.toString cfg.uboot.package
} ]]; then
migrate_uboot
fi
''}
if [[ "$SHOULD_UBOOT" -ne 1 ]] && [[ ! -f "$STATE_DIRECTORY/kernel-version" || $(< "$STATE_DIRECTORY/kernel-version") != ${
builtins.toString kernel
} ]]; then
migrate_kernel
fi
if [[ "$SHOULD_UBOOT" -ne 1 ]] && [[ ! -f "$STATE_DIRECTORY/cmdline-version" || $(< "$STATE_DIRECTORY/cmdline-version") != ${
builtins.toString kernel-params
} ]]; then
migrate_cmdline
fi
if [[ -f "$STATE_DIRECTORY/config-migration-in-progress" || ! -f "$STATE_DIRECTORY/config-version" || $(< "$STATE_DIRECTORY/config-version") != ${
builtins.toString config.hardware.raspberry-pi.config-output
} ]]; then
migrate_config
fi
if [[ -f "$STATE_DIRECTORY/firmware-migration-in-progress" || ! -f "$STATE_DIRECTORY/firmware-version" || $(< "$STATE_DIRECTORY/firmware-version") != ${
builtins.toString pkgs.raspberrypifw
} ]]; then
migrate_firmware
fi
'';
};
};
};
# Default config.txt on Raspberry Pi OS:
# https://github.com/RPi-Distro/pi-gen/blob/master/stage1/00-boot-files/files/config.txt
@ -68,7 +261,15 @@
# linux kernel.
kernel = {
enable = true;
value = "u-boot-rpi-arm64.bin";
value = if cfg.uboot.enable then "u-boot-rpi-arm64.bin" else "kernel.img";
};
ramfsfile = {
enable = !cfg.uboot.enable;
value = "initrd";
};
ramfsaddr = {
enable = !cfg.uboot.enable;
value = -1;
};
arm_64bit = {
enable = true;
@ -104,21 +305,56 @@
};
};
nixpkgs = { overlays = [ overlay ]; };
nixpkgs = {
overlays =
let
rpi-overlays = [ core-overlay ]
++ (if config.raspberry-pi-nix.libcamera-overlay.enable
then [ libcamera-overlay ] else [ ]);
rpi-overlay = lib.composeManyExtensions rpi-overlays;
pin-prev-overlay = overlay: pinned-prev: final: prev:
let
# apply the overlay to pinned-prev and fix that so no references to the actual final
# and prev appear in applied-overlay
applied-overlay =
lib.fix (final: pinned-prev // overlay final pinned-prev);
# We only want to set keys that appear in the overlay, so restrict applied-overlay to
# these keys
restricted-overlay = lib.getAttrs (builtins.attrNames (overlay { } { })) applied-overlay;
in
prev // restricted-overlay;
in
if cfg.pin-inputs.enable
then [ (pin-prev-overlay rpi-overlay pinned) ]
else [ rpi-overlay ];
};
boot = {
initrd.availableKernelModules = [
kernelParams =
if cfg.uboot.enable then [ ]
else builtins.concatLists [
[ "console=tty1" ]
(if cfg.serial-console.enable then [
# https://github.com/raspberrypi/firmware/issues/1539#issuecomment-784498108
"console=serial0,115200n8"
] else [ ]
)
[ "init=/sbin/init" ]
];
initrd = {
availableKernelModules = [
"usbhid"
"usb_storage"
"vc4"
"pcie_brcmstb" # required for the pcie bus to work
"reset-raspberrypi" # required for vl805 firmware to load
];
kernelPackages = pkgs.linuxPackagesFor (pkgs.rpi-kernels.latest.kernel);
};
kernelPackages = pkgs.linuxPackagesFor pkgs.rpi-kernels."${version}"."${board}";
loader = {
grub.enable = lib.mkDefault false;
initScript.enable = !cfg.uboot.enable;
generic-extlinux-compatible = {
enable = lib.mkDefault true;
enable = lib.mkDefault cfg.uboot.enable;
# We want to use the device tree provided by firmware, so don't
# add FDTDIR to the extlinux conf file.
useGenerationDeviceTree = false;
@ -127,11 +363,56 @@
};
hardware.enableRedistributableFirmware = true;
users.groups = builtins.listToAttrs (map (k: { name = k; value = { }; })
[ "input" "sudo" "plugdev" "games" "netdev" "gpio" "i2c" "spi" ]);
services = {
udev.extraRules = ''
udev.extraRules =
let shell = "${pkgs.bash}/bin/bash";
in ''
# https://raw.githubusercontent.com/RPi-Distro/raspberrypi-sys-mods/master/etc.armhf/udev/rules.d/99-com.rules
SUBSYSTEM=="input", GROUP="input", MODE="0660"
SUBSYSTEM=="i2c-dev", GROUP="i2c", MODE="0660"
SUBSYSTEM=="spidev", GROUP="spi", MODE="0660"
SUBSYSTEM=="*gpiomem*", GROUP="gpio", MODE="0660"
SUBSYSTEM=="rpivid-*", GROUP="video", MODE="0660"
KERNEL=="vcsm-cma", GROUP="video", MODE="0660"
SUBSYSTEM=="dma_heap", GROUP="video", MODE="0660"
KERNEL=="gpiomem", GROUP="gpio", MODE="0660"
KERNEL=="gpiochip*", GROUP="gpio", MODE="0660"
SUBSYSTEM=="gpio", GROUP="gpio", MODE="0660"
SUBSYSTEM=="gpio", KERNEL=="gpiochip*", ACTION=="add", PROGRAM="${shell} -c 'chgrp -R gpio /sys/class/gpio && chmod -R g=u /sys/class/gpio'"
SUBSYSTEM=="gpio", ACTION=="add", PROGRAM="${shell} -c 'chgrp -R gpio /sys%p && chmod -R g=u /sys%p'"
# PWM export results in a "change" action on the pwmchip device (not "add" of a new device), so match actions other than "remove".
SUBSYSTEM=="pwm", ACTION!="remove", PROGRAM="${shell} -c 'chgrp -R gpio /sys%p && chmod -R g=u /sys%p'"
KERNEL=="ttyAMA[0-9]*|ttyS[0-9]*", PROGRAM="${shell} -c '\
ALIASES=/proc/device-tree/aliases; \
TTYNODE=$$(readlink /sys/class/tty/%k/device/of_node | sed 's/base/:/' | cut -d: -f2); \
if [ -e $$ALIASES/bluetooth ] && [ $$TTYNODE/bluetooth = $$(strings $$ALIASES/bluetooth) ]; then \
echo 1; \
elif [ -e $$ALIASES/console ]; then \
if [ $$TTYNODE = $$(strings $$ALIASES/console) ]; then \
echo 0;\
else \
exit 1; \
fi \
elif [ $$TTYNODE = $$(strings $$ALIASES/serial0) ]; then \
echo 0; \
elif [ $$TTYNODE = $$(strings $$ALIASES/serial1) ]; then \
echo 1; \
else \
exit 1; \
fi \
'", SYMLINK+="serial%c"
ACTION=="add", SUBSYSTEM=="vtconsole", KERNEL=="vtcon1", RUN+="${shell} -c '\
if echo RPi-Sense FB | cmp -s /sys/class/graphics/fb0/name; then \
echo 0 > /sys$devpath/bind; \
fi; \
'"
'';
};
};
}

View file

@ -5,22 +5,64 @@
config = {
boot.loader.grub.enable = false;
boot.loader.generic-extlinux-compatible.enable = true;
boot.consoleLogLevel = lib.mkDefault 7;
# https://github.com/raspberrypi/firmware/issues/1539#issuecomment-784498108
boot.kernelParams = [ "console=serial0,115200n8" "console=tty1" ];
boot.kernelParams = [
# This is ugly and fragile, but the sdImage image has an msdos
# table, so the partition table id is a 1-indexed hex
# number. So, we drop the hex prefix and stick on a "02" to
# refer to the root partition.
"root=PARTUUID=${lib.strings.removePrefix "0x" config.sdImage.firmwarePartitionID}-02"
"rootfstype=ext4"
"fsck.repair=yes"
"rootwait"
];
sdImage = {
sdImage =
let
kernel-params = pkgs.writeTextFile {
name = "cmdline.txt";
text = ''
${lib.strings.concatStringsSep " " config.boot.kernelParams}
'';
};
cfg = config.raspberry-pi-nix;
version = cfg.kernel-version;
board = cfg.board;
kernel = "${config.system.build.kernel}/${config.system.boot.loader.kernelFile}";
initrd = "${config.system.build.initialRamdisk}/${config.system.boot.loader.initrdFile}";
populate-kernel =
if cfg.uboot.enable
then ''
cp ${cfg.uboot.package}/u-boot.bin firmware/u-boot-rpi-arm64.bin
''
else ''
cp "${kernel}" firmware/kernel.img
cp "${initrd}" firmware/initrd
cp "${kernel-params}" firmware/cmdline.txt
'';
in
{
populateFirmwareCommands = ''
cp ${pkgs.uboot_rpi_arm64}/u-boot.bin firmware/u-boot-rpi-arm64.bin
${populate-kernel}
cp -r ${pkgs.raspberrypifw}/share/raspberrypi/boot/{start*.elf,*.dtb,bootcode.bin,fixup*.dat,overlays} firmware
cp ${config.hardware.raspberry-pi.config-output} firmware/config.txt
'';
populateRootCommands = ''
populateRootCommands =
if cfg.uboot.enable
then ''
mkdir -p ./files/boot
${config.boot.loader.generic-extlinux-compatible.populateCmd} -c ${config.system.build.toplevel} -d ./files/boot
''
else ''
mkdir -p ./files/sbin
content="$(
echo "#!${pkgs.bash}/bin/bash"
echo "exec ${config.system.build.toplevel}/init"
)"
echo "$content" > ./files/sbin/init
chmod 744 ./files/sbin/init
'';
};
};

View file

@ -30,7 +30,8 @@ let
} // optionalAttrs (config.sdImage.rootPartitionUUID != null) {
uuid = config.sdImage.rootPartitionUUID;
});
in {
in
{
imports = [ ];
options.sdImage = {
@ -82,14 +83,6 @@ in {
'';
};
firmwarePartitionName = mkOption {
type = types.str;
default = "FIRMWARE";
description = ''
Name of the filesystem which holds the boot firmware.
'';
};
rootPartitionUUID = mkOption {
type = types.nullOr types.str;
default = null;
@ -160,7 +153,7 @@ in {
config = {
fileSystems = {
"/boot/firmware" = {
device = "/dev/disk/by-label/${config.sdImage.firmwarePartitionName}";
device = "/dev/disk/by-label/${config.raspberry-pi-nix.firmware-partition-label}";
fsType = "vfat";
};
"/" = {
@ -226,7 +219,7 @@ in {
# Create a FAT32 /boot/firmware partition of suitable size into firmware_part.img
eval $(partx $img -o START,SECTORS --nr 1 --pairs)
truncate -s $((SECTORS * 512)) firmware_part.img
faketime "1970-01-01 00:00:00" mkfs.vfat -i ${config.sdImage.firmwarePartitionID} -n ${config.sdImage.firmwarePartitionName} firmware_part.img
faketime "1970-01-01 00:00:00" mkfs.vfat -i ${config.sdImage.firmwarePartitionID} -n ${config.raspberry-pi-nix.firmware-partition-label} firmware_part.img
# Populate the files intended for /boot/firmware
mkdir firmware
@ -244,7 +237,8 @@ in {
zstd -T$NIX_BUILD_CORES --rm $img
fi
'';
}) { };
})
{ };
boot.postBootCommands = lib.mkIf config.sdImage.expandOnBoot ''
# On the first boot do some maintenance tasks
@ -254,7 +248,7 @@ in {
# Figure out device names for the boot device and root filesystem.
rootPart=$(${pkgs.util-linux}/bin/findmnt -n -o SOURCE /)
bootDevice=$(lsblk -npo PKNAME $rootPart)
partNum=$(lsblk -npo MAJ:MIN $rootPart | ${pkgs.gawk}/bin/awk -F: '{print $2}')
partNum=$(lsblk -npo PARTN $rootPart)
# Resize the root partition and the filesystem to fit the disk
echo ",+," | sfdisk -N$partNum --no-reread $bootDevice