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
115
README.md
115
README.md
|
|
@ -1,27 +1,22 @@
|
||||||
# raspberry-pi-nix
|
# raspberry-pi-nix
|
||||||
|
|
||||||
NixOS modules that make building images for raspberry-pi products
|
The primary goal of this software is to make it easy to create
|
||||||
easier. Most of the work in this repository is based on work in
|
working NixOS configurations for Raspberry Pi products. Specifically,
|
||||||
[nixos-hardware](https://github.com/NixOS/nixos-hardware) and
|
this repository aims to deliver the following benefits:
|
||||||
[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.
|
|
||||||
|
|
||||||
This flake provides nixos modules that correspond to different
|
1. Configure the kernel, device tree, and boot loader in a way that is
|
||||||
raspberry-pi products. These modules can be included in nixos
|
compatible with the hardware and proprietary firmware.
|
||||||
configurations and aim to deliver the following benefits:
|
2. Provide a nix interface to Raspberry Pi/device tree configuration
|
||||||
|
that will be familiar to those who have used Raspberry Pi's
|
||||||
1. Configure the kernel, device tree, and u-boot in a way that is
|
[config.txt based
|
||||||
compatible with the hardware.
|
configuration](https://www.raspberrypi.com/documentation/computers/config_txt.html).
|
||||||
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.
|
|
||||||
3. Make it easy to build an image suitable for flashing to an sd-card,
|
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.
|
without a need to first go through an installation media.
|
||||||
|
|
||||||
The important modules are `overlay/default.nix`, `rpi/default.nix`,
|
The important modules are `overlay/default.nix`, `rpi/default.nix`,
|
||||||
and `rpi/device-tree.nix`. The other modules for i2c, i2s, etc are
|
and `rpi/config.nix`. The other modules for i2c, i2s, etc are mostly
|
||||||
mostly wrappers that set common device tree settings for you.
|
wrappers that set `config.txt` settings and enable required kernel
|
||||||
|
modules.
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
|
||||||
|
|
@ -46,27 +41,12 @@ mostly wrappers that set common device tree settings for you.
|
||||||
useDHCP = false;
|
useDHCP = false;
|
||||||
interfaces = { wlan0.useDHCP = true; };
|
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 {
|
in {
|
||||||
nixosConfigurations = {
|
nixosConfigurations = {
|
||||||
rpi-zero-2-w-example = nixosSystem {
|
rpi-example = nixosSystem {
|
||||||
system = "aarch64-linux";
|
system = "aarch64-linux";
|
||||||
modules = [ raspberry-pi-nix.rpi-zero-2-w basic-config ];
|
modules = [ raspberry-pi-nix.rpi basic-config ];
|
||||||
};
|
|
||||||
rpi-4b-example = nixosSystem {
|
|
||||||
system = "aarch64-linux";
|
|
||||||
modules = [ raspberry-pi-nix.rpi-4b 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
|
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
|
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:
|
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
|
The image produced by this package is partitioned in the same way as
|
||||||
installation media from nixpkgs: There is a firmware partition that
|
the aarch64 installation media from nixpkgs: There is a firmware
|
||||||
contains necessary firmware, u-boot, and config.txt. Then there is
|
partition that contains necessary firmware, u-boot, and
|
||||||
another partition that contains everything else. After the sd-image is
|
config.txt. Then there is another partition (labeled `NIXOS_SD`) that
|
||||||
built, nixos system updates will not change anything in the firmware
|
contains everything else. The firmware and `config.txt` file are
|
||||||
partition ever again. New kernels and device tree configurations will
|
managed by NixOS modules defined in this package. Additionally, NixOS
|
||||||
remain on the nixos partition and be booted by u-boot in the firmware
|
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.
|
partition.
|
||||||
|
|
||||||
So, while you can control device tree params and overlays through your
|
## `config.txt` generation
|
||||||
nixos system configuration, if you want to modify other config.txt
|
|
||||||
variables this must be done manually by mounting the partition and
|
As noted, the `config.txt` file is generated by the NixOS
|
||||||
modifying the config.txt file.
|
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, ... }:
|
{ lib, config, pkgs, ... }:
|
||||||
let
|
let
|
||||||
cfg = config;
|
cfg = config.hardware.raspberry-pi;
|
||||||
render-raspberrypi-config = let
|
render-raspberrypi-config = let
|
||||||
render-options = opts:
|
render-options = opts:
|
||||||
lib.strings.concatStringsSep "\n" (render-dt-kvs opts);
|
lib.strings.concatStringsSep "\n" (render-dt-kvs opts);
|
||||||
|
|
@ -22,11 +22,11 @@ let
|
||||||
args = render-dt-kvs v;
|
args = render-dt-kvs v;
|
||||||
}) overlays);
|
}) overlays);
|
||||||
render-config-section = k:
|
render-config-section = k:
|
||||||
{ options, base-dtb-params, dt-overlays }:
|
{ options, base-dt-params, dt-overlays }:
|
||||||
let
|
let
|
||||||
all-config = lib.concatStringsSep "\n" (lib.filter (x: x != "") [
|
all-config = lib.concatStringsSep "\n" (lib.filter (x: x != "") [
|
||||||
(render-options options)
|
(render-options options)
|
||||||
(render-base-dt-params base-dtb-params)
|
(render-base-dt-params base-dt-params)
|
||||||
(render-dt-overlays dt-overlays)
|
(render-dt-overlays dt-overlays)
|
||||||
]);
|
]);
|
||||||
in ''
|
in ''
|
||||||
|
|
@ -38,48 +38,48 @@ let
|
||||||
(lib.attrsets.mapAttrsToList render-config-section conf);
|
(lib.attrsets.mapAttrsToList render-config-section conf);
|
||||||
in {
|
in {
|
||||||
options = {
|
options = {
|
||||||
raspberrypi-config = let
|
hardware.raspberry-pi = {
|
||||||
raspberrypi-config-options = {
|
config = let
|
||||||
options = {
|
raspberry-pi-config-options = {
|
||||||
options = lib.mkOption {
|
options = {
|
||||||
type = with lib.types; attrsOf anything;
|
options = lib.mkOption {
|
||||||
default = { };
|
type = with lib.types; attrsOf anything;
|
||||||
example = {
|
default = { };
|
||||||
enable_gic = true;
|
example = {
|
||||||
armstub = "armstub8-gic.bin";
|
enable_gic = true;
|
||||||
arm_boost = true;
|
arm_boost = true;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
base-dt-params = lib.mkOption {
|
||||||
base-dtb-params = lib.mkOption {
|
type = with lib.types; attrsOf anything;
|
||||||
type = with lib.types; attrsOf anything;
|
default = { };
|
||||||
default = { };
|
example = {
|
||||||
example = {
|
i2c = "on";
|
||||||
i2c = "on";
|
audio = "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 {
|
config-output = lib.mkOption {
|
||||||
type = with lib.types; attrsOf (submodule raspberrypi-config-options);
|
type = lib.types.package;
|
||||||
};
|
default = pkgs.writeTextFile {
|
||||||
raspberrypi-config-output = lib.mkOption {
|
name = "config.txt";
|
||||||
type = lib.types.package;
|
text = ''
|
||||||
default = pkgs.writeTextFile {
|
# This is a generated file. Do not edit!
|
||||||
name = "config.txt";
|
${render-raspberrypi-config cfg.config}
|
||||||
text = ''
|
'';
|
||||||
# Auto-generated by nix. Modifications will be overwritten.
|
};
|
||||||
${render-raspberrypi-config cfg.raspberrypi-config}
|
|
||||||
'';
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,10 @@
|
||||||
{ lib, pkgs, config, ... }:
|
{ 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 = {
|
system.activationScripts.raspberrypi = {
|
||||||
text = ''
|
text = ''
|
||||||
if ! grep -qs '/boot/firmware ' /proc/mounts; then
|
if ! grep -qs '/boot/firmware ' /proc/mounts; then
|
||||||
|
|
@ -11,29 +13,28 @@
|
||||||
fi
|
fi
|
||||||
cp ${pkgs.uboot_rpi_arm64}/u-boot.bin /boot/firmware/u-boot-rpi-arm64.bin
|
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 -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 = {
|
# Default config.txt on Raspberry Pi OS:
|
||||||
pi4 = {
|
# https://github.com/RPi-Distro/pi-gen/blob/master/stage1/00-boot-files/files/config.txt
|
||||||
options = {
|
hardware.raspberry-pi.config = {
|
||||||
enable_gic = true;
|
cm4 = { options = { otg_mode = true; }; };
|
||||||
armstub = "armstub8-gic.bin";
|
pi4 = { options = { arm_boost = true; }; };
|
||||||
arm_boost = true;
|
|
||||||
disable_overscan = true;
|
|
||||||
};
|
|
||||||
dt-overlays = { vc4-kms-v3d-pi4 = { cma-512 = null; }; };
|
|
||||||
};
|
|
||||||
pi02 = { dt-overlays = { vc4-kms-v3d = { cma-256 = null; }; }; };
|
|
||||||
all = {
|
all = {
|
||||||
options = {
|
options = {
|
||||||
|
# The firmware will start our u-boot binary rather than a
|
||||||
|
# linux kernel.
|
||||||
kernel = "u-boot-rpi-arm64.bin";
|
kernel = "u-boot-rpi-arm64.bin";
|
||||||
|
arm_64bit = true;
|
||||||
enable_uart = true;
|
enable_uart = true;
|
||||||
avoid_warnings = 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;
|
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 = ''
|
populateFirmwareCommands = ''
|
||||||
cp ${pkgs.uboot_rpi_arm64}/u-boot.bin firmware/u-boot-rpi-arm64.bin
|
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 -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 = ''
|
populateRootCommands = ''
|
||||||
mkdir -p ./files/boot
|
mkdir -p ./files/boot
|
||||||
|
|
|
||||||
|
|
@ -162,6 +162,7 @@ in {
|
||||||
"/boot/firmware" = {
|
"/boot/firmware" = {
|
||||||
device = "/dev/disk/by-label/${config.sdImage.firmwarePartitionName}";
|
device = "/dev/disk/by-label/${config.sdImage.firmwarePartitionName}";
|
||||||
fsType = "vfat";
|
fsType = "vfat";
|
||||||
|
options = [ "nofail" "noauto" ];
|
||||||
};
|
};
|
||||||
"/" = {
|
"/" = {
|
||||||
device = "/dev/disk/by-label/NIXOS_SD";
|
device = "/dev/disk/by-label/NIXOS_SD";
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue