populate firmware partition via systemd service

Only copy files from modified packages.
This commit is contained in:
Travis Staton 2023-05-24 09:33:32 -04:00
parent 3ca8c6898a
commit a1b4cadb53
2 changed files with 93 additions and 39 deletions

View file

@ -87,8 +87,8 @@ the aarch64 installation media from nixpkgs: There is a firmware
partition that contains necessary firmware, u-boot, and partition that contains necessary firmware, u-boot, and
config.txt. Then there is another partition (labeled `NIXOS_SD`) that config.txt. Then there is another partition (labeled `NIXOS_SD`) that
contains everything else. The firmware and `config.txt` file are contains everything else. The firmware and `config.txt` file are
managed by NixOS modules defined in this package. Additionally, NixOS managed by NixOS modules defined in this package. Additionally, a
system activation will update the firmware and `config.txt` in the systemd service will update the firmware and `config.txt` in the
firmware partition __in place__. Linux kernels are stored 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 `NIXOS_SD` partition and will be booted by u-boot in the firmware
partition. partition.
@ -96,7 +96,8 @@ partition.
## `config.txt` generation ## `config.txt` generation
As noted, the `config.txt` file is generated by the NixOS 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 The relevant nixos option is
`hardware.raspberry-pi.config`. Configuration is partitioned into `hardware.raspberry-pi.config`. Configuration is partitioned into
@ -254,8 +255,8 @@ device tree configuration is controlled via the [config.txt
file](https://www.raspberrypi.com/documentation/computers/config_txt.html). file](https://www.raspberrypi.com/documentation/computers/config_txt.html).
Additionally, the firmware, device trees, and overlays from the Additionally, the firmware, device trees, and overlays from the
`raspberrypifw` package populate the firmware partition on system `raspberrypifw` package populate the firmware partition. This package
activation. This package is kept up to date by the overlay applied by is kept up to date by the overlay applied by this package, so you
this package, so you don't need configure this. However, if you want don't need configure this. However, if you want to use different
to use different firmware you can override that package to do so. firmware you can override that package to do so.

View file

@ -4,43 +4,96 @@
{ {
imports = [ ../sd-image ./config.nix ./i2c.nix ]; imports = [ ../sd-image ./config.nix ./i2c.nix ];
# On activation install u-boot, Raspberry Pi firmware, and our systemd.services = {
# generated config.txt "raspberry-pi-firmware-migrate" = {
system.activationScripts.raspberrypi = { description = "update the firmware partition";
text = '' wantedBy = [ "multi-user.target" ];
shopt -s nullglob serviceConfig = let firmware-path = "/boot/firmware";
in {
Type = "oneshot";
MountImages =
"/dev/disk/by-label/${config.sdImage.firmwarePartitionName}:${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" TARGET_OVERLAYS_DIR="$TARGET_FIRMWARE_DIR/overlays"
TMPFILE="$TARGET_FIRMWARE_DIR/tmp" TMPFILE="$TARGET_FIRMWARE_DIR/tmp"
UBOOT="${pkgs.uboot_rpi_arm64}/u-boot.bin" UBOOT="${pkgs.uboot_rpi_arm64}/u-boot.bin"
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}"
cp "$UBOOT" "$TMPFILE" migrate_uboot() {
mv -T "$TMPFILE" "$TARGET_FIRMWARE_DIR/u-boot-rpi-arm64.bin" 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 pkgs.uboot_rpi_arm64
}" > "$STATE_DIRECTORY/uboot-version"
rm "$STATE_DIRECTORY/uboot-migration-in-progress"
}
cp "$CONFIG" "$TMPFILE" migrate_config() {
mv -T "$TMPFILE" "$TARGET_FIRMWARE_DIR/config.txt" 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"
}
for SRC in "''${STARTFILES[@]}" "''${DTBS[@]}" "$BOOTCODE" "''${FIXUPS[@]}" migrate_firmware() {
do echo "migrating raspberrypi firmware"
cp "$SRC" "$TMPFILE" touch "$STATE_DIRECTORY/firmware-migration-in-progress"
mv -T "$TMPFILE" "$TARGET_FIRMWARE_DIR/$(basename "$SRC")" for SRC in "''${STARTFILES[@]}" "''${DTBS[@]}" "$BOOTCODE" "''${FIXUPS[@]}"
done do
cp "$SRC" "$TMPFILE"
mv -T "$TMPFILE" "$TARGET_FIRMWARE_DIR/$(basename "$SRC")"
done
for SRC in "''${SRC_OVERLAYS[@]}" if [[ ! -d "$TARGET_OVERLAYS_DIR" ]]; then
do mkdir "$TARGET_OVERLAYS_DIR"
cp "$SRC" "$TMPFILE" fi
mv -T "$TMPFILE" "$TARGET_OVERLAYS_DIR/$(basename "$SRC")"
done 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"
}
if [[ -f "$STATE_DIRECTORY/uboot-migration-in-progress" || ! -f "$STATE_DIRECTORY/uboot-version" || $(< "$STATE_DIRECTORY/uboot-version") != ${
builtins.toString pkgs.uboot_rpi_arm64
} ]]; then
migrate_uboot
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: # Default config.txt on Raspberry Pi OS: