Skip to content

Commit

Permalink
populate firmware partition via systemd service
Browse files Browse the repository at this point in the history
Only copy files from modified packages.
  • Loading branch information
tstat committed May 24, 2023
1 parent 3ca8c68 commit a1b4cad
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 39 deletions.
15 changes: 8 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,16 +87,17 @@ 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
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__. 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
Expand Down Expand Up @@ -254,8 +255,8 @@ 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.
`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.

117 changes: 85 additions & 32 deletions rpi/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -4,43 +4,96 @@
{
imports = [ ../sd-image ./config.nix ./i2c.nix ];

# On activation install u-boot, Raspberry Pi firmware, and our
# generated config.txt
system.activationScripts.raspberrypi = {
text = ''
shopt -s nullglob
systemd.services = {
"raspberry-pi-firmware-migrate" = {
description = "update the firmware partition";
wantedBy = [ "multi-user.target" ];
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_OVERLAYS_DIR="$TARGET_FIRMWARE_DIR/overlays"
TMPFILE="$TARGET_FIRMWARE_DIR/tmp"
UBOOT="${pkgs.uboot_rpi_arm64}/u-boot.bin"
SRC_FIRMWARE_DIR="${pkgs.raspberrypifw}/share/raspberrypi/boot"
STARTFILES=("$SRC_FIRMWARE_DIR"/start*.elf)
DTBS=("$SRC_FIRMWARE_DIR"/*.dtb)
BOOTCODE="$SRC_FIRMWARE_DIR/bootcode.bin"
FIXUPS=("$SRC_FIRMWARE_DIR"/fixup*.dat)
SRC_OVERLAYS_DIR="$SRC_FIRMWARE_DIR/overlays"
SRC_OVERLAYS=("$SRC_OVERLAYS_DIR"/*)
CONFIG="${config.hardware.raspberry-pi.config-output}"
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"
SRC_FIRMWARE_DIR="${pkgs.raspberrypifw}/share/raspberrypi/boot"
STARTFILES=("$SRC_FIRMWARE_DIR"/start*.elf)
DTBS=("$SRC_FIRMWARE_DIR"/*.dtb)
BOOTCODE="$SRC_FIRMWARE_DIR/bootcode.bin"
FIXUPS=("$SRC_FIRMWARE_DIR"/fixup*.dat)
SRC_OVERLAYS_DIR="$SRC_FIRMWARE_DIR/overlays"
SRC_OVERLAYS=("$SRC_OVERLAYS_DIR"/*)
CONFIG="${config.hardware.raspberry-pi.config-output}"
cp "$UBOOT" "$TMPFILE"
mv -T "$TMPFILE" "$TARGET_FIRMWARE_DIR/u-boot-rpi-arm64.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 pkgs.uboot_rpi_arm64
}" > "$STATE_DIRECTORY/uboot-version"
rm "$STATE_DIRECTORY/uboot-migration-in-progress"
}
cp "$CONFIG" "$TMPFILE"
mv -T "$TMPFILE" "$TARGET_FIRMWARE_DIR/config.txt"
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"
}
for SRC in "''${STARTFILES[@]}" "''${DTBS[@]}" "$BOOTCODE" "''${FIXUPS[@]}"
do
cp "$SRC" "$TMPFILE"
mv -T "$TMPFILE" "$TARGET_FIRMWARE_DIR/$(basename "$SRC")"
done
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
for SRC in "''${SRC_OVERLAYS[@]}"
do
cp "$SRC" "$TMPFILE"
mv -T "$TMPFILE" "$TARGET_OVERLAYS_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"
}
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:
Expand Down

0 comments on commit a1b4cad

Please sign in to comment.