mirror of
https://github.com/nix-community/raspberry-pi-nix.git
synced 2025-11-08 19:46:03 +01:00
update default rpi config
This commit is contained in:
parent
67f257e524
commit
739c404f11
6 changed files with 147 additions and 104 deletions
117
README.md
117
README.md
|
|
@ -1,27 +1,22 @@
|
|||
# raspberry-pi-nix
|
||||
|
||||
NixOS modules that make building images for raspberry-pi products
|
||||
easier. Most of the work in this repository is based on work in
|
||||
[nixos-hardware](https://github.com/NixOS/nixos-hardware) and
|
||||
[nixpkgs](https://github.com/NixOS/nixpkgs). Additionally, be aware
|
||||
that I am no expert and this repo is the product of me fooling around
|
||||
with some pis.
|
||||
The primary goal of this software is to make it easy to create
|
||||
working NixOS configurations for Raspberry Pi products. Specifically,
|
||||
this repository aims to deliver the following benefits:
|
||||
|
||||
This flake provides nixos modules that correspond to different
|
||||
raspberry-pi products. These modules can be included in nixos
|
||||
configurations and aim to deliver the following benefits:
|
||||
|
||||
1. Configure the kernel, device tree, and u-boot in a way that is
|
||||
compatible with the hardware.
|
||||
2. Provide a nix interface to device tree configuration that will be
|
||||
familiar to those who have used raspberry-pi's config.txt based
|
||||
configuration.
|
||||
1. Configure the kernel, device tree, and boot loader in a way that is
|
||||
compatible with the hardware and proprietary firmware.
|
||||
2. Provide a nix interface to Raspberry Pi/device tree configuration
|
||||
that will be familiar to those who have used Raspberry Pi's
|
||||
[config.txt based
|
||||
configuration](https://www.raspberrypi.com/documentation/computers/config_txt.html).
|
||||
3. Make it easy to build an image suitable for flashing to an sd-card,
|
||||
without a need to first go through an installation media.
|
||||
|
||||
|
||||
The important modules are `overlay/default.nix`, `rpi/default.nix`,
|
||||
and `rpi/device-tree.nix`. The other modules for i2c, i2s, etc are
|
||||
mostly wrappers that set common device tree settings for you.
|
||||
and `rpi/config.nix`. The other modules for i2c, i2s, etc are mostly
|
||||
wrappers that set `config.txt` settings and enable required kernel
|
||||
modules.
|
||||
|
||||
## Example
|
||||
|
||||
|
|
@ -46,27 +41,12 @@ mostly wrappers that set common device tree settings for you.
|
|||
useDHCP = false;
|
||||
interfaces = { wlan0.useDHCP = true; };
|
||||
};
|
||||
hardware.raspberry-pi = {
|
||||
i2c.enable = true;
|
||||
audio.enable = true;
|
||||
fkms-3d.enable = true;
|
||||
deviceTree = {
|
||||
dt-overlays = [{
|
||||
overlay = "imx477"; # add the overlay for the HQ camera
|
||||
args = [ ];
|
||||
}];
|
||||
};
|
||||
};
|
||||
};
|
||||
in {
|
||||
nixosConfigurations = {
|
||||
rpi-zero-2-w-example = nixosSystem {
|
||||
rpi-example = nixosSystem {
|
||||
system = "aarch64-linux";
|
||||
modules = [ raspberry-pi-nix.rpi-zero-2-w basic-config ];
|
||||
};
|
||||
rpi-4b-example = nixosSystem {
|
||||
system = "aarch64-linux";
|
||||
modules = [ raspberry-pi-nix.rpi-4b basic-config ];
|
||||
modules = [ raspberry-pi-nix.rpi basic-config ];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -77,25 +57,64 @@ mostly wrappers that set common device tree settings for you.
|
|||
|
||||
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-zero-2-w-example` in the above configuration
|
||||
build an image for `rpi-example` in the above configuration
|
||||
example you could run:
|
||||
|
||||
```
|
||||
nix build '.#nixosConfigurations.rpi-zero-2-w-example.config.system.build.sdImage'
|
||||
nix build '.#nixosConfigurations.rpi-example.config.system.build.sdImage'
|
||||
```
|
||||
|
||||
## Other notes
|
||||
## The firmware partition
|
||||
|
||||
The sd-image built 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 that contains everything else. After the sd-image is
|
||||
built, nixos system updates will not change anything in the firmware
|
||||
partition ever again. New kernels and device tree configurations will
|
||||
remain on the nixos partition and be booted by u-boot in the firmware
|
||||
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.
|
||||
|
||||
So, while you can control device tree params and overlays through your
|
||||
nixos system configuration, if you want to modify other config.txt
|
||||
variables this must be done manually by mounting the partition and
|
||||
modifying the config.txt file.
|
||||
## `config.txt` generation
|
||||
|
||||
As noted, the `config.txt` file is generated by the NixOS
|
||||
configuration and automatically updated on system activation.
|
||||
|
||||
|
||||
## 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)
|
||||
).
|
||||
|
||||
This manipulation makes it difficult to use the device tree configured
|
||||
directly by NixOS as you must know and reproduce the manipulation
|
||||
performed by the proprietary firmware.
|
||||
|
||||
Even if the manipulation was reproduced, some convenience would be
|
||||
missed out. For example, the firmware can detect hardware during boot
|
||||
and automatically configure the device tree accordingly, rather than
|
||||
requiring a NixOS system rebuild with a different device tree for
|
||||
different 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
|
||||
file](https://www.raspberrypi.com/documentation/computers/config_txt.html).
|
||||
|
||||
Additionally, the firmware, device trees, and overlays from the
|
||||
`raspberrypifw` package populates 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.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{ lib, config, pkgs, ... }:
|
||||
let
|
||||
cfg = config;
|
||||
cfg = config.hardware.raspberry-pi;
|
||||
render-raspberrypi-config = let
|
||||
render-options = opts:
|
||||
lib.strings.concatStringsSep "\n" (render-dt-kvs opts);
|
||||
|
|
@ -22,11 +22,11 @@ let
|
|||
args = render-dt-kvs v;
|
||||
}) overlays);
|
||||
render-config-section = k:
|
||||
{ options, base-dtb-params, dt-overlays }:
|
||||
{ options, base-dt-params, dt-overlays }:
|
||||
let
|
||||
all-config = lib.concatStringsSep "\n" (lib.filter (x: x != "") [
|
||||
(render-options options)
|
||||
(render-base-dt-params base-dtb-params)
|
||||
(render-base-dt-params base-dt-params)
|
||||
(render-dt-overlays dt-overlays)
|
||||
]);
|
||||
in ''
|
||||
|
|
@ -38,48 +38,48 @@ let
|
|||
(lib.attrsets.mapAttrsToList render-config-section conf);
|
||||
in {
|
||||
options = {
|
||||
raspberrypi-config = let
|
||||
raspberrypi-config-options = {
|
||||
options = {
|
||||
options = lib.mkOption {
|
||||
type = with lib.types; attrsOf anything;
|
||||
default = { };
|
||||
example = {
|
||||
enable_gic = true;
|
||||
armstub = "armstub8-gic.bin";
|
||||
arm_boost = true;
|
||||
hardware.raspberry-pi = {
|
||||
config = let
|
||||
raspberry-pi-config-options = {
|
||||
options = {
|
||||
options = lib.mkOption {
|
||||
type = with lib.types; attrsOf anything;
|
||||
default = { };
|
||||
example = {
|
||||
enable_gic = true;
|
||||
arm_boost = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
base-dtb-params = lib.mkOption {
|
||||
type = with lib.types; attrsOf anything;
|
||||
default = { };
|
||||
example = {
|
||||
i2c = "on";
|
||||
audio = "on";
|
||||
base-dt-params = lib.mkOption {
|
||||
type = with lib.types; attrsOf anything;
|
||||
default = { };
|
||||
example = {
|
||||
i2c = "on";
|
||||
audio = "on";
|
||||
};
|
||||
description = "parameters to pass to the base dtb";
|
||||
};
|
||||
dt-overlays = lib.mkOption {
|
||||
type = with lib.types; attrsOf (attrsOf (nullOr str));
|
||||
default = { };
|
||||
example = { vc4-kms-v3d = { cma-256 = null; }; };
|
||||
description = "dtb overlays to apply";
|
||||
};
|
||||
description = "parameters to pass to the base dtb";
|
||||
};
|
||||
dt-overlays = lib.mkOption {
|
||||
type = with lib.types; attrsOf (attrsOf (nullOr str));
|
||||
default = { };
|
||||
example = { vc4-kms-v3d = { cma-256 = null; }; };
|
||||
description = "dtb overlays to apply";
|
||||
};
|
||||
};
|
||||
in lib.mkOption {
|
||||
type = with lib.types; attrsOf (submodule raspberry-pi-config-options);
|
||||
};
|
||||
in lib.mkOption {
|
||||
type = with lib.types; attrsOf (submodule raspberrypi-config-options);
|
||||
};
|
||||
raspberrypi-config-output = lib.mkOption {
|
||||
type = lib.types.package;
|
||||
default = pkgs.writeTextFile {
|
||||
name = "config.txt";
|
||||
text = ''
|
||||
# Auto-generated by nix. Modifications will be overwritten.
|
||||
${render-raspberrypi-config cfg.raspberrypi-config}
|
||||
'';
|
||||
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}
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,8 +2,10 @@
|
|||
{ lib, pkgs, config, ... }:
|
||||
|
||||
{
|
||||
imports = [ ../sd-image ./config.nix ];
|
||||
imports = [ ../sd-image ./config.nix ./i2c.nix ];
|
||||
|
||||
# On activation install u-boot, Raspberry Pi firmware, and our
|
||||
# generated config.txt
|
||||
system.activationScripts.raspberrypi = {
|
||||
text = ''
|
||||
if ! grep -qs '/boot/firmware ' /proc/mounts; then
|
||||
|
|
@ -11,29 +13,28 @@
|
|||
fi
|
||||
cp ${pkgs.uboot_rpi_arm64}/u-boot.bin /boot/firmware/u-boot-rpi-arm64.bin
|
||||
cp -r ${pkgs.raspberrypifw}/share/raspberrypi/boot/{start*.elf,*.dtb,bootcode.bin,fixup*.dat,overlays} /boot/firmware
|
||||
cp ${config.raspberrypi-config-output} /boot/firmware/config.txt
|
||||
cp ${config.hardware.raspberry-pi.config-output} /boot/firmware/config.txt
|
||||
'';
|
||||
};
|
||||
|
||||
raspberrypi-config = {
|
||||
pi4 = {
|
||||
options = {
|
||||
enable_gic = true;
|
||||
armstub = "armstub8-gic.bin";
|
||||
arm_boost = true;
|
||||
disable_overscan = true;
|
||||
};
|
||||
dt-overlays = { vc4-kms-v3d-pi4 = { cma-512 = null; }; };
|
||||
};
|
||||
pi02 = { dt-overlays = { vc4-kms-v3d = { cma-256 = null; }; }; };
|
||||
# Default config.txt on Raspberry Pi OS:
|
||||
# https://github.com/RPi-Distro/pi-gen/blob/master/stage1/00-boot-files/files/config.txt
|
||||
hardware.raspberry-pi.config = {
|
||||
cm4 = { options = { otg_mode = true; }; };
|
||||
pi4 = { options = { arm_boost = true; }; };
|
||||
all = {
|
||||
options = {
|
||||
# The firmware will start our u-boot binary rather than a
|
||||
# linux kernel.
|
||||
kernel = "u-boot-rpi-arm64.bin";
|
||||
arm_64bit = true;
|
||||
enable_uart = true;
|
||||
avoid_warnings = true;
|
||||
arm_64bit = true;
|
||||
camera_auto_detect = true;
|
||||
display_auto_detect = true;
|
||||
disable_overscan = true;
|
||||
};
|
||||
base-dtb-params = { krnbt = "on"; };
|
||||
dt-overlays = { vc4-kms-v3d = { }; };
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -59,4 +60,12 @@
|
|||
};
|
||||
};
|
||||
hardware.enableRedistributableFirmware = true;
|
||||
|
||||
services = {
|
||||
udev.extraRules = ''
|
||||
SUBSYSTEM=="dma_heap", GROUP="video", MODE="0660"
|
||||
KERNEL=="gpiomem", GROUP="gpio", MODE="0660"
|
||||
KERNEL=="gpiochip*", GROUP="gpio", MODE="0660"
|
||||
'';
|
||||
};
|
||||
}
|
||||
|
|
|
|||
14
rpi/i2c.nix
Normal file
14
rpi/i2c.nix
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let cfg = config.hardware.raspberry-pi.i2c;
|
||||
in {
|
||||
options.hardware.raspberry-pi.i2c = {
|
||||
enable = lib.mkEnableOption "configuration for i2c";
|
||||
};
|
||||
config = lib.mkIf cfg.enable {
|
||||
hardware = {
|
||||
raspberry-pi.config.all.base-dt-params = { i2c = "on"; };
|
||||
i2c.enable = true;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
@ -16,7 +16,7 @@
|
|||
populateFirmwareCommands = ''
|
||||
cp ${pkgs.uboot_rpi_arm64}/u-boot.bin firmware/u-boot-rpi-arm64.bin
|
||||
cp -r ${pkgs.raspberrypifw}/share/raspberrypi/boot/{start*.elf,*.dtb,bootcode.bin,fixup*.dat,overlays} firmware
|
||||
cp ${config.raspberrypi-config-output} firmware/config.txt
|
||||
cp ${config.hardware.raspberry-pi.config-output} firmware/config.txt
|
||||
'';
|
||||
populateRootCommands = ''
|
||||
mkdir -p ./files/boot
|
||||
|
|
|
|||
|
|
@ -162,6 +162,7 @@ in {
|
|||
"/boot/firmware" = {
|
||||
device = "/dev/disk/by-label/${config.sdImage.firmwarePartitionName}";
|
||||
fsType = "vfat";
|
||||
options = [ "nofail" "noauto" ];
|
||||
};
|
||||
"/" = {
|
||||
device = "/dev/disk/by-label/NIXOS_SD";
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue