nix: format treewide

This commit is contained in:
Jacob Birkett 2025-02-08 03:10:18 -08:00
parent 150128c843
commit 2abf8951ef
No known key found for this signature in database
GPG key ID: A65814ADB0C06288
8 changed files with 493 additions and 506 deletions

View file

@ -37,7 +37,8 @@
}; };
libcamera-src = { libcamera-src = {
flake = false; flake = false;
url = "github:raspberrypi/libcamera/69a894c4adad524d3063dd027f5c4774485cf9db"; # v0.3.1+rpt20240906 url =
"github:raspberrypi/libcamera/69a894c4adad524d3063dd027f5c4774485cf9db"; # v0.3.1+rpt20240906
}; };
libpisp-src = { libpisp-src = {
flake = false; flake = false;
@ -51,11 +52,11 @@
system = "aarch64-linux"; system = "aarch64-linux";
overlays = with self.overlays; [ core libcamera ]; overlays = with self.overlays; [ core libcamera ];
}; };
in in {
{
overlays = { overlays = {
core = import ./overlays (builtins.removeAttrs srcs [ "self" ]); core = import ./overlays (builtins.removeAttrs srcs [ "self" ]);
libcamera = import ./overlays/libcamera.nix (builtins.removeAttrs srcs [ "self" ]); libcamera = import ./overlays/libcamera.nix
(builtins.removeAttrs srcs [ "self" ]);
}; };
nixosModules = { nixosModules = {
raspberry-pi = import ./rpi { raspberry-pi = import ./rpi {
@ -68,32 +69,34 @@
nixosConfigurations = { nixosConfigurations = {
rpi-example = srcs.nixpkgs.lib.nixosSystem { rpi-example = srcs.nixpkgs.lib.nixosSystem {
system = "aarch64-linux"; system = "aarch64-linux";
modules = [ self.nixosModules.raspberry-pi self.nixosModules.sd-image ./example ]; modules = [
self.nixosModules.raspberry-pi
self.nixosModules.sd-image
./example
];
}; };
}; };
checks.aarch64-linux = self.packages.aarch64-linux; checks.aarch64-linux = self.packages.aarch64-linux;
packages.aarch64-linux = with pinned.lib; packages.aarch64-linux = with pinned.lib;
let let
kernels = kernels = foldlAttrs f { } pinned.rpi-kernels;
foldlAttrs f { } pinned.rpi-kernels;
f = acc: kernel-version: board-attr-set: f = acc: kernel-version: board-attr-set:
foldlAttrs foldlAttrs (acc: board-version: drv:
(acc: board-version: drv: acc // { acc // {
"linux-${kernel-version}-${board-version}" = drv; "linux-${kernel-version}-${board-version}" = drv;
}) }) acc board-attr-set;
acc in {
board-attr-set; example-sd-image =
in self.nixosConfigurations.rpi-example.config.system.build.sdImage;
{
example-sd-image = self.nixosConfigurations.rpi-example.config.system.build.sdImage;
firmware = pinned.raspberrypifw; firmware = pinned.raspberrypifw;
libcamera = pinned.libcamera; libcamera = pinned.libcamera;
wireless-firmware = pinned.raspberrypiWirelessFirmware; wireless-firmware = pinned.raspberrypiWirelessFirmware;
uboot-rpi-arm64 = pinned.uboot-rpi-arm64; uboot-rpi-arm64 = pinned.uboot-rpi-arm64;
} // kernels; } // kernels;
formatter = formatter = srcs.nixpkgs.lib.genAttrs [
srcs.nixpkgs.lib.genAttrs "aarch64-linux"
[ "aarch64-linux" "aarch64-darwin" "x86_64-linux"] "aarch64-darwin"
(system: srcs.nixpkgs.legacyPackages.${system}.nixfmt-classic); "x86_64-linux"
] (system: srcs.nixpkgs.legacyPackages.${system}.nixfmt-classic);
}; };
} }

View file

@ -1,12 +1,5 @@
{ u-boot-src { u-boot-src, rpi-linux-stable-src, rpi-linux-6_6_67-src, rpi-linux-6_12_11-src
, rpi-linux-stable-src , rpi-firmware-src, rpi-firmware-nonfree-src, rpi-bluez-firmware-src, ... }:
, rpi-linux-6_6_67-src
, rpi-linux-6_12_11-src
, rpi-firmware-src
, rpi-firmware-nonfree-src
, rpi-bluez-firmware-src
, ...
}:
final: prev: final: prev:
let let
versions = { versions = {
@ -14,15 +7,14 @@ let
v6_6_67.src = rpi-linux-6_6_67-src; v6_6_67.src = rpi-linux-6_6_67-src;
v6_12_11 = { v6_12_11 = {
src = rpi-linux-6_12_11-src; src = rpi-linux-6_12_11-src;
patches = [ patches = [{
{ name = "remove-readme-target.patch";
name = "remove-readme-target.patch"; patch = final.fetchpatch {
patch = final.fetchpatch { url =
url = "https://github.com/raspberrypi/linux/commit/3c0fd51d184f1748b83d28e1113265425c19bcb5.patch"; "https://github.com/raspberrypi/linux/commit/3c0fd51d184f1748b83d28e1113265425c19bcb5.patch";
hash = "sha256-v7uZOmPCUp2i7NGVgjqnQYe6dEBD+aATuP/oRs9jfuk="; hash = "sha256-v7uZOmPCUp2i7NGVgjqnQYe6dEBD+aATuP/oRs9jfuk=";
}; };
} }];
];
}; };
}; };
boards = [ "bcm2711" "bcm2712" ]; boards = [ "bcm2711" "bcm2712" ];
@ -32,8 +24,7 @@ let
let let
kernel = builtins.getAttr version versions; kernel = builtins.getAttr version versions;
version-slug = builtins.replaceStrings [ "v" "_" ] [ "" "." ] version; version-slug = builtins.replaceStrings [ "v" "_" ] [ "" "." ] version;
in in {
{
"${version}"."${board}" = (final.buildLinux { "${version}"."${board}" = (final.buildLinux {
modDirVersion = version-slug; modDirVersion = version-slug;
version = version-slug; version = version-slug;
@ -61,22 +52,18 @@ let
KUNIT = no; KUNIT = no;
}; };
features.efiBootStub = false; features.efiBootStub = false;
kernelPatches = kernelPatches = if kernel ? "patches" then kernel.patches else [ ];
if kernel ? "patches" then kernel.patches else [ ]; }).overrideAttrs (oldAttrs: {
}).overrideAttrs postConfigure = ''
(oldAttrs: { # The v7 defconfig has this set to '-v7' which screws up our modDirVersion.
postConfigure = '' sed -i $buildRoot/.config -e 's/^CONFIG_LOCALVERSION=.*/CONFIG_LOCALVERSION=""/'
# The v7 defconfig has this set to '-v7' which screws up our modDirVersion. sed -i $buildRoot/include/config/auto.conf -e 's/^CONFIG_LOCALVERSION=.*/CONFIG_LOCALVERSION=""/'
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' rpi-kernels =
(b: a: final.lib.recursiveUpdate b (rpi-kernel a)) builtins.foldl' (b: a: final.lib.recursiveUpdate b (rpi-kernel a)) { };
{ }; in {
in
{
# disable firmware compression so that brcm firmware can be found at # disable firmware compression so that brcm firmware can be found at
# the path expected by raspberry pi firmware/device tree # the path expected by raspberry pi firmware/device tree
compressFirmwareXz = x: x; compressFirmwareXz = x: x;
@ -105,22 +92,20 @@ in
# default to latest firmware # default to latest firmware
raspberrypiWirelessFirmware = final.callPackage raspberrypiWirelessFirmware = final.callPackage
( (import ./raspberrypi-wireless-firmware.nix {
import ./raspberrypi-wireless-firmware.nix { bluez-firmware = rpi-bluez-firmware-src;
bluez-firmware = rpi-bluez-firmware-src; firmware-nonfree = rpi-firmware-nonfree-src;
firmware-nonfree = rpi-firmware-nonfree-src; }) { };
} raspberrypifw =
) prev.raspberrypifw.overrideAttrs (oldfw: { src = rpi-firmware-src; });
{ };
raspberrypifw = prev.raspberrypifw.overrideAttrs (oldfw: { src = rpi-firmware-src; });
} // { } // {
# rpi kernels and firmware are available at # rpi kernels and firmware are available at
# `pkgs.rpi-kernels.<VERSION>.<BOARD>'. # `pkgs.rpi-kernels.<VERSION>.<BOARD>'.
# #
# For example: `pkgs.rpi-kernels.v6_6_67.bcm2712' # For example: `pkgs.rpi-kernels.v6_6_67.bcm2712'
rpi-kernels = rpi-kernels ( rpi-kernels = rpi-kernels (final.lib.cartesianProduct {
final.lib.cartesianProduct board = boards;
{ board = boards; version = (builtins.attrNames versions); } version = (builtins.attrNames versions);
); });
} }

View file

@ -1,8 +1,4 @@
{ rpicam-apps-src { rpicam-apps-src, libcamera-src, libpisp-src, ... }:
, libcamera-src
, libpisp-src
, ...
}:
final: prev: { final: prev: {
# A recent known working version of rpicam-apps # A recent known working version of rpicam-apps
libcamera-apps = libcamera-apps =
@ -27,12 +23,8 @@ final: prev: {
libpisp libpisp
openssl openssl
libtiff libtiff
(python3.withPackages (ps: with ps; [ (python3.withPackages
python3-gnutls (ps: with ps; [ python3-gnutls pybind11 pyyaml ply ]))
pybind11
pyyaml
ply
]))
libglibutil libglibutil
gst_all_1.gst-plugins-base gst_all_1.gst-plugins-base
]); ]);

View file

@ -1,4 +1,4 @@
{ rpicam-apps-src, lib, pkgs, stdenv }: { rpicam-apps-src, lib, pkgs, stdenv, }:
stdenv.mkDerivation { stdenv.mkDerivation {
pname = "libcamera-apps"; pname = "libcamera-apps";
@ -7,7 +7,18 @@ stdenv.mkDerivation {
src = rpicam-apps-src; src = rpicam-apps-src;
nativeBuildInputs = with pkgs; [ meson pkg-config ]; nativeBuildInputs = with pkgs; [ meson pkg-config ];
buildInputs = with pkgs; [ libjpeg libtiff libcamera libepoxy boost libexif libpng ffmpeg libdrm ninja ]; buildInputs = with pkgs; [
libjpeg
libtiff
libcamera
libepoxy
boost
libexif
libpng
ffmpeg
libdrm
ninja
];
mesonFlags = [ mesonFlags = [
"-Denable_qt=disabled" "-Denable_qt=disabled"
"-Denable_opencv=disabled" "-Denable_opencv=disabled"

View file

@ -1,128 +1,121 @@
{ lib, config, pkgs, ... }: { lib, config, pkgs, ... }:
let let
cfg = config.hardware.raspberry-pi; cfg = config.hardware.raspberry-pi;
render-raspberrypi-config = render-raspberrypi-config = let
let render-options = opts:
render-options = opts: lib.strings.concatStringsSep "\n" (render-dt-kvs opts);
lib.strings.concatStringsSep "\n" (render-dt-kvs opts); render-dt-param = x: "dtparam=" + x;
render-dt-param = x: "dtparam=" + x; render-dt-kv = k: v:
render-dt-kv = k: v: if isNull v.value then
if isNull v.value then k
k else
else let vstr = toString v.value; in "${k}=${vstr}";
let vstr = toString v.value; in "${k}=${vstr}"; render-dt-kvs = x:
render-dt-kvs = x: lib.attrsets.mapAttrsToList render-dt-kv
lib.attrsets.mapAttrsToList render-dt-kv (lib.filterAttrs (k: v: v.enable) x);
(lib.filterAttrs (k: v: v.enable) x); render-dt-overlay = { overlay, args }:
render-dt-overlay = { overlay, args }: "dtoverlay=" + overlay + "\n"
"dtoverlay=" + overlay + "\n" + lib.strings.concatMapStringsSep "\n" render-dt-param args + "\n"
+ lib.strings.concatMapStringsSep "\n" render-dt-param args + "\n" + "dtoverlay=";
+ "dtoverlay="; render-base-dt-params = params:
render-base-dt-params = params: lib.strings.concatMapStringsSep "\n" render-dt-param
lib.strings.concatMapStringsSep "\n" render-dt-param (render-dt-kvs params);
(render-dt-kvs params); render-dt-overlays = overlays:
render-dt-overlays = overlays: lib.strings.concatMapStringsSep "\n" render-dt-overlay
lib.strings.concatMapStringsSep "\n" render-dt-overlay (lib.attrsets.mapAttrsToList (k: v: {
(lib.attrsets.mapAttrsToList overlay = k;
(k: v: { args = render-dt-kvs v.params;
overlay = k; }) (lib.filterAttrs (k: v: v.enable) overlays));
args = render-dt-kvs v.params; render-config-section = k:
}) { options, base-dt-params, dt-overlays, }:
(lib.filterAttrs (k: v: v.enable) overlays)); let
render-config-section = k: all-config = lib.concatStringsSep "\n" (lib.filter (x: x != "") [
{ options, base-dt-params, dt-overlays }: (render-options options)
let (render-base-dt-params base-dt-params)
all-config = lib.concatStringsSep "\n" (lib.filter (x: x != "") [ (render-dt-overlays dt-overlays)
(render-options options) ]);
(render-base-dt-params base-dt-params) in ''
(render-dt-overlays dt-overlays) [${k}]
]); ${all-config}
in '';
'' in conf:
[${k}] lib.strings.concatStringsSep "\n"
${all-config} (lib.attrsets.mapAttrsToList render-config-section conf);
''; in {
in
conf:
lib.strings.concatStringsSep "\n"
(lib.attrsets.mapAttrsToList render-config-section conf);
in
{
options = { options = {
hardware.raspberry-pi = { hardware.raspberry-pi = {
config = config = let
let rpi-config-param = {
rpi-config-param = { options = {
options = { enable = lib.mkEnableOption "attr";
enable = lib.mkEnableOption "attr"; value =
value = lib.mkOption { type = with lib.types; oneOf [ int str bool ]; };
lib.mkOption { type = with lib.types; oneOf [ int str bool ]; };
};
}; };
dt-param = {
options = {
enable = lib.mkEnableOption "attr";
value = lib.mkOption {
type = with lib.types; nullOr (oneOf [ int str bool ]);
default = null;
};
};
};
dt-overlay = {
options = {
enable = lib.mkEnableOption "overlay";
params = lib.mkOption {
type = with lib.types; attrsOf (submodule dt-param);
};
};
};
raspberry-pi-config-options = {
options = {
options = lib.mkOption {
type = with lib.types; attrsOf (submodule rpi-config-param);
default = { };
example = {
enable_gic = {
enable = true;
value = true;
};
arm_boost = {
enable = true;
value = true;
};
};
};
base-dt-params = lib.mkOption {
type = with lib.types; attrsOf (submodule dt-param);
default = { };
example = {
i2c = {
enable = true;
value = "on";
};
audio = {
enable = true;
value = "on";
};
};
description = "parameters to pass to the base dtb";
};
dt-overlays = lib.mkOption {
type = with lib.types; attrsOf (submodule dt-overlay);
default = { };
example = { vc4-kms-v3d = { cma-256 = { enable = true; }; }; };
description = "dtb overlays to apply";
};
};
};
in
lib.mkOption {
type = with lib.types; attrsOf (submodule raspberry-pi-config-options);
}; };
dt-param = {
options = {
enable = lib.mkEnableOption "attr";
value = lib.mkOption {
type = with lib.types; nullOr (oneOf [ int str bool ]);
default = null;
};
};
};
dt-overlay = {
options = {
enable = lib.mkEnableOption "overlay";
params = lib.mkOption {
type = with lib.types; attrsOf (submodule dt-param);
};
};
};
raspberry-pi-config-options = {
options = {
options = lib.mkOption {
type = with lib.types; attrsOf (submodule rpi-config-param);
default = { };
example = {
enable_gic = {
enable = true;
value = true;
};
arm_boost = {
enable = true;
value = true;
};
};
};
base-dt-params = lib.mkOption {
type = with lib.types; attrsOf (submodule dt-param);
default = { };
example = {
i2c = {
enable = true;
value = "on";
};
audio = {
enable = true;
value = "on";
};
};
description = "parameters to pass to the base dtb";
};
dt-overlays = lib.mkOption {
type = with lib.types; attrsOf (submodule dt-overlay);
default = { };
example = { vc4-kms-v3d = { cma-256 = { enable = true; }; }; };
description = "dtb overlays to apply";
};
};
};
in lib.mkOption {
type = with lib.types; attrsOf (submodule raspberry-pi-config-options);
};
config-generated = lib.mkOption { config-generated = lib.mkOption {
type = lib.types.str; type = lib.types.str;
description = "the config text generated by raspberrypi.hardware.config"; description =
"the config text generated by raspberrypi.hardware.config";
readOnly = true; readOnly = true;
}; };
@ -139,6 +132,7 @@ in
}; };
}; };
config = { config = {
hardware.raspberry-pi.config-generated = render-raspberrypi-config cfg.config; hardware.raspberry-pi.config-generated =
render-raspberrypi-config cfg.config;
}; };
} }

View file

@ -1,4 +1,4 @@
{ pinned, core-overlay, libcamera-overlay }: { pinned, core-overlay, libcamera-overlay, }:
{ lib, pkgs, config, ... }: { lib, pkgs, config, ... }:
let let
@ -6,9 +6,9 @@ let
version = cfg.kernel-version; version = cfg.kernel-version;
board = cfg.board; board = cfg.board;
kernel = config.system.build.kernel; kernel = config.system.build.kernel;
initrd = "${config.system.build.initialRamdisk}/${config.system.boot.loader.initrdFile}"; initrd =
in "${config.system.build.initialRamdisk}/${config.system.boot.loader.initrdFile}";
{ in {
imports = [ ./config.nix ./i2c.nix ]; imports = [ ./config.nix ./i2c.nix ];
options = with lib; { options = with lib; {
@ -82,146 +82,148 @@ in
config = { config = {
systemd.services = { systemd.services = {
"raspberry-pi-firmware-migrate" = "raspberry-pi-firmware-migrate" = {
{ description = "update the firmware partition";
description = "update the firmware partition"; wantedBy = if cfg.firmware-migration-service.enable then
wantedBy = if cfg.firmware-migration-service.enable then [ "multi-user.target" ] else [ ]; [ "multi-user.target" ]
serviceConfig = else
let [ ];
firmware-path = "/boot/firmware"; serviceConfig = let
kernel-params = pkgs.writeTextFile { firmware-path = "/boot/firmware";
name = "cmdline.txt"; kernel-params = pkgs.writeTextFile {
text = '' name = "cmdline.txt";
${lib.strings.concatStringsSep " " config.boot.kernelParams} text = ''
''; ${lib.strings.concatStringsSep " " config.boot.kernelParams}
}; '';
in };
{ in {
Type = "oneshot"; Type = "oneshot";
MountImages = MountImages =
"/dev/disk/by-label/${cfg.firmware-partition-label}:${firmware-path}"; "/dev/disk/by-label/${cfg.firmware-partition-label}:${firmware-path}";
StateDirectory = "raspberrypi-firmware"; StateDirectory = "raspberrypi-firmware";
ExecStart = pkgs.writeShellScript "migrate-rpi-firmware" '' ExecStart = pkgs.writeShellScript "migrate-rpi-firmware" ''
shopt -s nullglob shopt -s nullglob
TARGET_FIRMWARE_DIR="${firmware-path}" TARGET_FIRMWARE_DIR="${firmware-path}"
TARGET_OVERLAYS_DIR="$TARGET_FIRMWARE_DIR/overlays" TARGET_OVERLAYS_DIR="$TARGET_FIRMWARE_DIR/overlays"
TMPFILE="$TARGET_FIRMWARE_DIR/tmp" TMPFILE="$TARGET_FIRMWARE_DIR/tmp"
KERNEL="${kernel}/${config.system.boot.loader.kernelFile}" KERNEL="${kernel}/${config.system.boot.loader.kernelFile}"
SHOULD_UBOOT=${if cfg.uboot.enable then "1" else "0"} SHOULD_UBOOT=${if cfg.uboot.enable then "1" else "0"}
SRC_FIRMWARE_DIR="${pkgs.raspberrypifw}/share/raspberrypi/boot" SRC_FIRMWARE_DIR="${pkgs.raspberrypifw}/share/raspberrypi/boot"
STARTFILES=("$SRC_FIRMWARE_DIR"/start*.elf) STARTFILES=("$SRC_FIRMWARE_DIR"/start*.elf)
DTBS=("$SRC_FIRMWARE_DIR"/*.dtb) DTBS=("$SRC_FIRMWARE_DIR"/*.dtb)
BOOTCODE="$SRC_FIRMWARE_DIR/bootcode.bin" BOOTCODE="$SRC_FIRMWARE_DIR/bootcode.bin"
FIXUPS=("$SRC_FIRMWARE_DIR"/fixup*.dat) FIXUPS=("$SRC_FIRMWARE_DIR"/fixup*.dat)
SRC_OVERLAYS_DIR="$SRC_FIRMWARE_DIR/overlays" SRC_OVERLAYS_DIR="$SRC_FIRMWARE_DIR/overlays"
SRC_OVERLAYS=("$SRC_OVERLAYS_DIR"/*) SRC_OVERLAYS=("$SRC_OVERLAYS_DIR"/*)
CONFIG="${config.hardware.raspberry-pi.config-output}" CONFIG="${config.hardware.raspberry-pi.config-output}"
${lib.strings.optionalString cfg.uboot.enable '' ${lib.strings.optionalString cfg.uboot.enable ''
UBOOT="${cfg.uboot.package}/u-boot.bin" UBOOT="${cfg.uboot.package}/u-boot.bin"
migrate_uboot() { migrate_uboot() {
echo "migrating uboot" echo "migrating uboot"
touch "$STATE_DIRECTORY/uboot-migration-in-progress" touch "$STATE_DIRECTORY/uboot-migration-in-progress"
cp "$UBOOT" "$TMPFILE" cp "$UBOOT" "$TMPFILE"
mv -T "$TMPFILE" "$TARGET_FIRMWARE_DIR/u-boot-rpi-arm64.bin" mv -T "$TMPFILE" "$TARGET_FIRMWARE_DIR/u-boot-rpi-arm64.bin"
echo "${builtins.toString cfg.uboot.package}" > "$STATE_DIRECTORY/uboot-version" echo "${
rm "$STATE_DIRECTORY/uboot-migration-in-progress" builtins.toString cfg.uboot.package
} }" > "$STATE_DIRECTORY/uboot-version"
''} rm "$STATE_DIRECTORY/uboot-migration-in-progress"
}
''}
migrate_kernel() { migrate_kernel() {
echo "migrating kernel" echo "migrating kernel"
touch "$STATE_DIRECTORY/kernel-migration-in-progress" touch "$STATE_DIRECTORY/kernel-migration-in-progress"
cp "$KERNEL" "$TMPFILE" cp "$KERNEL" "$TMPFILE"
mv -T "$TMPFILE" "$TARGET_FIRMWARE_DIR/kernel.img" mv -T "$TMPFILE" "$TARGET_FIRMWARE_DIR/kernel.img"
cp "${initrd}" "$TMPFILE" cp "${initrd}" "$TMPFILE"
mv -T "$TMPFILE" "$TARGET_FIRMWARE_DIR/initrd" mv -T "$TMPFILE" "$TARGET_FIRMWARE_DIR/initrd"
echo "${ echo "${
builtins.toString kernel builtins.toString kernel
}" > "$STATE_DIRECTORY/kernel-version" }" > "$STATE_DIRECTORY/kernel-version"
rm "$STATE_DIRECTORY/kernel-migration-in-progress" rm "$STATE_DIRECTORY/kernel-migration-in-progress"
} }
migrate_cmdline() { migrate_cmdline() {
echo "migrating cmdline" echo "migrating cmdline"
touch "$STATE_DIRECTORY/cmdline-migration-in-progress" touch "$STATE_DIRECTORY/cmdline-migration-in-progress"
cp "${kernel-params}" "$TMPFILE" cp "${kernel-params}" "$TMPFILE"
mv -T "$TMPFILE" "$TARGET_FIRMWARE_DIR/cmdline.txt" mv -T "$TMPFILE" "$TARGET_FIRMWARE_DIR/cmdline.txt"
echo "${ echo "${
builtins.toString kernel-params builtins.toString kernel-params
}" > "$STATE_DIRECTORY/cmdline-version" }" > "$STATE_DIRECTORY/cmdline-version"
rm "$STATE_DIRECTORY/cmdline-migration-in-progress" rm "$STATE_DIRECTORY/cmdline-migration-in-progress"
} }
migrate_config() { migrate_config() {
echo "migrating config.txt" echo "migrating config.txt"
touch "$STATE_DIRECTORY/config-migration-in-progress" touch "$STATE_DIRECTORY/config-migration-in-progress"
cp "$CONFIG" "$TMPFILE" cp "$CONFIG" "$TMPFILE"
mv -T "$TMPFILE" "$TARGET_FIRMWARE_DIR/config.txt" mv -T "$TMPFILE" "$TARGET_FIRMWARE_DIR/config.txt"
echo "${config.hardware.raspberry-pi.config-output}" > "$STATE_DIRECTORY/config-version" echo "${config.hardware.raspberry-pi.config-output}" > "$STATE_DIRECTORY/config-version"
rm "$STATE_DIRECTORY/config-migration-in-progress" rm "$STATE_DIRECTORY/config-migration-in-progress"
} }
migrate_firmware() { migrate_firmware() {
echo "migrating raspberrypi firmware" echo "migrating raspberrypi firmware"
touch "$STATE_DIRECTORY/firmware-migration-in-progress" touch "$STATE_DIRECTORY/firmware-migration-in-progress"
for SRC in "''${STARTFILES[@]}" "''${DTBS[@]}" "$BOOTCODE" "''${FIXUPS[@]}" for SRC in "''${STARTFILES[@]}" "''${DTBS[@]}" "$BOOTCODE" "''${FIXUPS[@]}"
do do
cp "$SRC" "$TMPFILE" cp "$SRC" "$TMPFILE"
mv -T "$TMPFILE" "$TARGET_FIRMWARE_DIR/$(basename "$SRC")" mv -T "$TMPFILE" "$TARGET_FIRMWARE_DIR/$(basename "$SRC")"
done done
if [[ ! -d "$TARGET_OVERLAYS_DIR" ]]; then if [[ ! -d "$TARGET_OVERLAYS_DIR" ]]; then
mkdir "$TARGET_OVERLAYS_DIR" mkdir "$TARGET_OVERLAYS_DIR"
fi fi
for SRC in "''${SRC_OVERLAYS[@]}" for SRC in "''${SRC_OVERLAYS[@]}"
do do
cp "$SRC" "$TMPFILE" cp "$SRC" "$TMPFILE"
mv -T "$TMPFILE" "$TARGET_OVERLAYS_DIR/$(basename "$SRC")" mv -T "$TMPFILE" "$TARGET_OVERLAYS_DIR/$(basename "$SRC")"
done done
echo "${ echo "${
builtins.toString pkgs.raspberrypifw builtins.toString pkgs.raspberrypifw
}" > "$STATE_DIRECTORY/firmware-version" }" > "$STATE_DIRECTORY/firmware-version"
rm "$STATE_DIRECTORY/firmware-migration-in-progress" rm "$STATE_DIRECTORY/firmware-migration-in-progress"
} }
${lib.strings.optionalString cfg.uboot.enable '' ${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") != ${ 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 builtins.toString cfg.uboot.package
} ]]; then } ]]; then
migrate_uboot migrate_uboot
fi fi
''} ''}
if [[ "$SHOULD_UBOOT" -ne 1 ]] && [[ ! -f "$STATE_DIRECTORY/kernel-version" || $(< "$STATE_DIRECTORY/kernel-version") != ${ if [[ "$SHOULD_UBOOT" -ne 1 ]] && [[ ! -f "$STATE_DIRECTORY/kernel-version" || $(< "$STATE_DIRECTORY/kernel-version") != ${
builtins.toString kernel builtins.toString kernel
} ]]; then } ]]; then
migrate_kernel migrate_kernel
fi fi
if [[ "$SHOULD_UBOOT" -ne 1 ]] && [[ ! -f "$STATE_DIRECTORY/cmdline-version" || $(< "$STATE_DIRECTORY/cmdline-version") != ${ if [[ "$SHOULD_UBOOT" -ne 1 ]] && [[ ! -f "$STATE_DIRECTORY/cmdline-version" || $(< "$STATE_DIRECTORY/cmdline-version") != ${
builtins.toString kernel-params builtins.toString kernel-params
} ]]; then } ]]; then
migrate_cmdline migrate_cmdline
fi fi
if [[ -f "$STATE_DIRECTORY/config-migration-in-progress" || ! -f "$STATE_DIRECTORY/config-version" || $(< "$STATE_DIRECTORY/config-version") != ${ 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 builtins.toString config.hardware.raspberry-pi.config-output
} ]]; then } ]]; then
migrate_config migrate_config
fi fi
if [[ -f "$STATE_DIRECTORY/firmware-migration-in-progress" || ! -f "$STATE_DIRECTORY/firmware-version" || $(< "$STATE_DIRECTORY/firmware-version") != ${ if [[ -f "$STATE_DIRECTORY/firmware-migration-in-progress" || ! -f "$STATE_DIRECTORY/firmware-version" || $(< "$STATE_DIRECTORY/firmware-version") != ${
builtins.toString pkgs.raspberrypifw builtins.toString pkgs.raspberrypifw
} ]]; then } ]]; then
migrate_firmware migrate_firmware
fi fi
''; '';
};
}; };
};
}; };
# Default config.txt on Raspberry Pi OS: # Default config.txt on Raspberry Pi OS:
@ -249,7 +251,8 @@ in
# linux kernel. # linux kernel.
kernel = { kernel = {
enable = true; enable = true;
value = if cfg.uboot.enable then "u-boot-rpi-arm64.bin" else "kernel.img"; value =
if cfg.uboot.enable then "u-boot-rpi-arm64.bin" else "kernel.img";
}; };
ramfsfile = { ramfsfile = {
enable = !cfg.uboot.enable; enable = !cfg.uboot.enable;
@ -294,37 +297,39 @@ in
}; };
nixpkgs = { nixpkgs = {
overlays = overlays = let
let rpi-overlays = [ core-overlay ]
rpi-overlays = [ core-overlay ] ++ (if config.raspberry-pi-nix.libcamera-overlay.enable then
++ (if config.raspberry-pi-nix.libcamera-overlay.enable [ libcamera-overlay ]
then [ libcamera-overlay ] else [ ]); else
rpi-overlay = lib.composeManyExtensions rpi-overlays; [ ]);
pin-prev-overlay = overlay: pinned-prev: final: prev: rpi-overlay = lib.composeManyExtensions rpi-overlays;
let pin-prev-overlay = overlay: pinned-prev: final: prev:
# apply the overlay to pinned-prev and fix that so no references to the actual final let
# and prev appear in applied-overlay # apply the overlay to pinned-prev and fix that so no references to the actual final
applied-overlay = # and prev appear in applied-overlay
lib.fix (final: pinned-prev // overlay final pinned-prev); applied-overlay =
# We only want to set keys that appear in the overlay, so restrict applied-overlay to lib.fix (final: pinned-prev // overlay final pinned-prev);
# these keys # We only want to set keys that appear in the overlay, so restrict applied-overlay to
restricted-overlay = lib.getAttrs (builtins.attrNames (overlay { } { })) applied-overlay; # these keys
in restricted-overlay =
prev // restricted-overlay; lib.getAttrs (builtins.attrNames (overlay { } { }))
in applied-overlay;
if cfg.pin-inputs.enable in prev // restricted-overlay;
then [ (pin-prev-overlay rpi-overlay pinned) ] in if cfg.pin-inputs.enable then
else [ rpi-overlay ]; [ (pin-prev-overlay rpi-overlay pinned) ]
else
[ rpi-overlay ];
}; };
boot = { boot = {
kernelParams = kernelParams = if cfg.uboot.enable then
if cfg.uboot.enable then [ ] [ ]
else [ else [
"console=tty1" "console=tty1"
# https://github.com/raspberrypi/firmware/issues/1539#issuecomment-784498108 # https://github.com/raspberrypi/firmware/issues/1539#issuecomment-784498108
"console=serial0,115200n8" "console=serial0,115200n8"
"init=/sbin/init" "init=/sbin/init"
]; ];
initrd = { initrd = {
availableKernelModules = [ availableKernelModules = [
"usbhid" "usbhid"
@ -334,7 +339,8 @@ in
"reset-raspberrypi" # required for vl805 firmware to load "reset-raspberrypi" # required for vl805 firmware to load
]; ];
}; };
kernelPackages = pkgs.linuxPackagesFor pkgs.rpi-kernels."${version}"."${board}"; kernelPackages =
pkgs.linuxPackagesFor pkgs.rpi-kernels."${version}"."${board}";
loader = { loader = {
grub.enable = lib.mkDefault false; grub.enable = lib.mkDefault false;
initScript.enable = !cfg.uboot.enable; initScript.enable = !cfg.uboot.enable;
@ -348,55 +354,56 @@ in
}; };
hardware.enableRedistributableFirmware = true; hardware.enableRedistributableFirmware = true;
users.groups = builtins.listToAttrs (map (k: { name = k; value = { }; }) users.groups = builtins.listToAttrs (map (k: {
[ "input" "sudo" "plugdev" "games" "netdev" "gpio" "i2c" "spi" ]); name = k;
value = { };
}) [ "input" "sudo" "plugdev" "games" "netdev" "gpio" "i2c" "spi" ]);
services = { services = {
udev.extraRules = udev.extraRules = let shell = "${pkgs.bash}/bin/bash";
let shell = "${pkgs.bash}/bin/bash"; in ''
in '' # https://raw.githubusercontent.com/RPi-Distro/raspberrypi-sys-mods/master/etc.armhf/udev/rules.d/99-com.rules
# 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=="input", GROUP="input", MODE="0660" SUBSYSTEM=="i2c-dev", GROUP="i2c", MODE="0660"
SUBSYSTEM=="i2c-dev", GROUP="i2c", MODE="0660" SUBSYSTEM=="spidev", GROUP="spi", MODE="0660"
SUBSYSTEM=="spidev", GROUP="spi", MODE="0660" SUBSYSTEM=="*gpiomem*", GROUP="gpio", MODE="0660"
SUBSYSTEM=="*gpiomem*", GROUP="gpio", MODE="0660" SUBSYSTEM=="rpivid-*", GROUP="video", MODE="0660"
SUBSYSTEM=="rpivid-*", GROUP="video", MODE="0660"
KERNEL=="vcsm-cma", GROUP="video", MODE="0660" KERNEL=="vcsm-cma", GROUP="video", MODE="0660"
SUBSYSTEM=="dma_heap", GROUP="video", MODE="0660" SUBSYSTEM=="dma_heap", GROUP="video", MODE="0660"
SUBSYSTEM=="gpio", 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", 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'" 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". # 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'" 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 '\ KERNEL=="ttyAMA[0-9]*|ttyS[0-9]*", PROGRAM="${shell} -c '\
ALIASES=/proc/device-tree/aliases; \ ALIASES=/proc/device-tree/aliases; \
TTYNODE=$$(readlink /sys/class/tty/%k/device/of_node | sed 's/base/:/' | cut -d: -f2); \ 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 \ if [ -e $$ALIASES/bluetooth ] && [ $$TTYNODE/bluetooth = $$(strings $$ALIASES/bluetooth) ]; then \
echo 1; \ echo 1; \
elif [ -e $$ALIASES/console ]; then \ elif [ -e $$ALIASES/console ]; then \
if [ $$TTYNODE = $$(strings $$ALIASES/console) ]; then \ if [ $$TTYNODE = $$(strings $$ALIASES/console) ]; then \
echo 0;\ echo 0;\
else \ else \
exit 1; \ exit 1; \
fi \ fi \
elif [ $$TTYNODE = $$(strings $$ALIASES/serial0) ]; then \ elif [ $$TTYNODE = $$(strings $$ALIASES/serial0) ]; then \
echo 0; \ echo 0; \
elif [ $$TTYNODE = $$(strings $$ALIASES/serial1) ]; then \ elif [ $$TTYNODE = $$(strings $$ALIASES/serial1) ]; then \
echo 1; \ echo 1; \
else \ else \
exit 1; \ exit 1; \
fi \ fi \
'", SYMLINK+="serial%c" '", SYMLINK+="serial%c"
ACTION=="add", SUBSYSTEM=="vtconsole", KERNEL=="vtcon1", RUN+="${shell} -c '\ ACTION=="add", SUBSYSTEM=="vtconsole", KERNEL=="vtcon1", RUN+="${shell} -c '\
if echo RPi-Sense FB | cmp -s /sys/class/graphics/fb0/name; then \ if echo RPi-Sense FB | cmp -s /sys/class/graphics/fb0/name; then \
echo 0 > /sys$devpath/bind; \ echo 0 > /sys$devpath/bind; \
fi; \ fi; \
'" '"
''; '';
}; };
}; };

View file

@ -13,57 +13,53 @@
# table, so the partition table id is a 1-indexed hex # table, so the partition table id is a 1-indexed hex
# number. So, we drop the hex prefix and stick on a "02" to # number. So, we drop the hex prefix and stick on a "02" to
# refer to the root partition. # refer to the root partition.
"root=PARTUUID=${lib.strings.removePrefix "0x" config.sdImage.firmwarePartitionID}-02" "root=PARTUUID=${
lib.strings.removePrefix "0x" config.sdImage.firmwarePartitionID
}-02"
"rootfstype=ext4" "rootfstype=ext4"
"fsck.repair=yes" "fsck.repair=yes"
"rootwait" "rootwait"
]; ];
sdImage = sdImage = let
let kernel-params = pkgs.writeTextFile {
kernel-params = pkgs.writeTextFile { name = "cmdline.txt";
name = "cmdline.txt"; text = ''
text = '' ${lib.strings.concatStringsSep " " config.boot.kernelParams}
${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 = ''
${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 =
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
'';
}; };
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 = ''
${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 = 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,8 +30,7 @@ let
} // optionalAttrs (config.sdImage.rootPartitionUUID != null) { } // optionalAttrs (config.sdImage.rootPartitionUUID != null) {
uuid = config.sdImage.rootPartitionUUID; uuid = config.sdImage.rootPartitionUUID;
}); });
in in {
{
imports = [ ]; imports = [ ];
options.sdImage = { options.sdImage = {
@ -153,7 +152,8 @@ in
config = { config = {
fileSystems = { fileSystems = {
"/boot/firmware" = { "/boot/firmware" = {
device = "/dev/disk/by-label/${config.raspberry-pi-nix.firmware-partition-label}"; device =
"/dev/disk/by-label/${config.raspberry-pi-nix.firmware-partition-label}";
fsType = "vfat"; fsType = "vfat";
}; };
"/" = { "/" = {
@ -164,81 +164,80 @@ in
sdImage.storePaths = [ config.system.build.toplevel ]; sdImage.storePaths = [ config.system.build.toplevel ];
system.build.sdImage = pkgs.callPackage system.build.sdImage = pkgs.callPackage ({ stdenv, dosfstools, e2fsprogs
({ stdenv, dosfstools, e2fsprogs, mtools, libfaketime, util-linux, zstd }: , mtools, libfaketime, util-linux, zstd, }:
stdenv.mkDerivation { stdenv.mkDerivation {
name = config.sdImage.imageName; name = config.sdImage.imageName;
nativeBuildInputs = nativeBuildInputs =
[ dosfstools e2fsprogs mtools libfaketime util-linux zstd ]; [ dosfstools e2fsprogs mtools libfaketime util-linux zstd ];
inherit (config.sdImage) compressImage; inherit (config.sdImage) compressImage;
buildCommand = '' buildCommand = ''
mkdir -p $out/nix-support $out/sd-image mkdir -p $out/nix-support $out/sd-image
export img=$out/sd-image/${config.sdImage.imageName} export img=$out/sd-image/${config.sdImage.imageName}
echo "${pkgs.stdenv.buildPlatform.system}" > $out/nix-support/system echo "${pkgs.stdenv.buildPlatform.system}" > $out/nix-support/system
if test -n "$compressImage"; then if test -n "$compressImage"; then
echo "file sd-image $img.zst" >> $out/nix-support/hydra-build-products echo "file sd-image $img.zst" >> $out/nix-support/hydra-build-products
else else
echo "file sd-image $img" >> $out/nix-support/hydra-build-products echo "file sd-image $img" >> $out/nix-support/hydra-build-products
fi fi
echo "Decompressing rootfs image" echo "Decompressing rootfs image"
zstd -d --no-progress "${rootfsImage}" -o ./root-fs.img zstd -d --no-progress "${rootfsImage}" -o ./root-fs.img
# Gap in front of the first partition, in MiB # Gap in front of the first partition, in MiB
gap=${toString config.sdImage.firmwarePartitionOffset} gap=${toString config.sdImage.firmwarePartitionOffset}
# Create the image file sized to fit /boot/firmware and /, plus slack for the gap. # Create the image file sized to fit /boot/firmware and /, plus slack for the gap.
rootSizeBlocks=$(du -B 512 --apparent-size ./root-fs.img | awk '{ print $1 }') rootSizeBlocks=$(du -B 512 --apparent-size ./root-fs.img | awk '{ print $1 }')
firmwareSizeBlocks=$((${ firmwareSizeBlocks=$((${
toString config.sdImage.firmwareSize toString config.sdImage.firmwareSize
} * 1024 * 1024 / 512)) } * 1024 * 1024 / 512))
imageSize=$((rootSizeBlocks * 512 + firmwareSizeBlocks * 512 + gap * 1024 * 1024)) imageSize=$((rootSizeBlocks * 512 + firmwareSizeBlocks * 512 + gap * 1024 * 1024))
truncate -s $imageSize $img truncate -s $imageSize $img
# type=b is 'W95 FAT32', type=83 is 'Linux'. # type=b is 'W95 FAT32', type=83 is 'Linux'.
# The "bootable" partition is where u-boot will look file for the bootloader # The "bootable" partition is where u-boot will look file for the bootloader
# information (dtbs, extlinux.conf file). # information (dtbs, extlinux.conf file).
sfdisk $img <<EOF sfdisk $img <<EOF
label: dos label: dos
label-id: ${config.sdImage.firmwarePartitionID} label-id: ${config.sdImage.firmwarePartitionID}
start=''${gap}M, size=$firmwareSizeBlocks, type=b start=''${gap}M, size=$firmwareSizeBlocks, type=b
start=$((gap + ${ start=$((gap + ${
toString config.sdImage.firmwareSize toString config.sdImage.firmwareSize
}))M, type=83, bootable }))M, type=83, bootable
EOF EOF
# Copy the rootfs into the SD image # Copy the rootfs into the SD image
eval $(partx $img -o START,SECTORS --nr 2 --pairs) eval $(partx $img -o START,SECTORS --nr 2 --pairs)
dd conv=notrunc if=./root-fs.img of=$img seek=$START count=$SECTORS dd conv=notrunc if=./root-fs.img of=$img seek=$START count=$SECTORS
# Create a FAT32 /boot/firmware partition of suitable size into firmware_part.img # Create a FAT32 /boot/firmware partition of suitable size into firmware_part.img
eval $(partx $img -o START,SECTORS --nr 1 --pairs) eval $(partx $img -o START,SECTORS --nr 1 --pairs)
truncate -s $((SECTORS * 512)) firmware_part.img truncate -s $((SECTORS * 512)) 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 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 # Populate the files intended for /boot/firmware
mkdir firmware mkdir firmware
${config.sdImage.populateFirmwareCommands} ${config.sdImage.populateFirmwareCommands}
# Copy the populated /boot/firmware into the SD image # Copy the populated /boot/firmware into the SD image
(cd firmware; mcopy -psvm -i ../firmware_part.img ./* ::) (cd firmware; mcopy -psvm -i ../firmware_part.img ./* ::)
# Verify the FAT partition before copying it. # Verify the FAT partition before copying it.
fsck.vfat -vn firmware_part.img fsck.vfat -vn firmware_part.img
dd conv=notrunc if=firmware_part.img of=$img seek=$START count=$SECTORS dd conv=notrunc if=firmware_part.img of=$img seek=$START count=$SECTORS
${config.sdImage.postBuildCommands} ${config.sdImage.postBuildCommands}
if test -n "$compressImage"; then if test -n "$compressImage"; then
zstd -T$NIX_BUILD_CORES --rm $img zstd -T$NIX_BUILD_CORES --rm $img
fi fi
''; '';
}) }) { };
{ };
boot.postBootCommands = lib.mkIf config.sdImage.expandOnBoot '' boot.postBootCommands = lib.mkIf config.sdImage.expandOnBoot ''
# On the first boot do some maintenance tasks # On the first boot do some maintenance tasks