Merge pull request #12 from tstat/pi-5

Add rpi-5 compatibility
This commit is contained in:
Travis Staton 2024-03-19 09:38:49 -04:00 committed by GitHub
commit b39b556e8a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 176 additions and 24 deletions

View file

@ -1,6 +1,8 @@
{ core-overlay, libcamera-overlay }: { core-overlay, libcamera-overlay }:
{ lib, pkgs, config, ... }: { lib, pkgs, config, ... }:
let cfg = config.raspberry-pi-nix;
in
{ {
imports = [ ../sd-image ./config.nix ./i2c.nix ]; imports = [ ../sd-image ./config.nix ./i2c.nix ];
@ -10,26 +12,70 @@
enable = mkOption { enable = mkOption {
default = true; default = true;
type = types.bool; type = types.bool;
description = ''
Whether to run the migration service automatically or not.
'';
}; };
}; };
libcamera-overlay = { libcamera-overlay = {
enable = mkOption { enable = mkOption {
default = true; default = true;
type = types.bool; type = types.bool;
description = ''
If enabled then the libcamera overlay is applied which
overrides libcamera with the rpi fork.
'';
};
};
uboot = {
enable = mkOption {
default = true;
type = types.bool;
description = ''
If enabled then uboot is used as the bootloader. If disabled
then the linux kernel is installed directly into the
firmware directory as expected by the raspberry pi boot
process.
This can be useful for newer hardware that doesn't yet have
uboot compatibility or less common setups, like booting a
cm4 with an nvme drive.
'';
}; };
}; };
}; };
}; };
config = { config = {
boot.kernelParams =
if cfg.uboot.enable then [ ]
else [
# This is ugly and fragile, but the sdImage image has an msdos
# table, so the partition table id is a 1-indexed hex
# number. So, we drop the hex prefix and stick on a "02" to
# refer to the root partition.
"root=PARTUUID=${lib.strings.removePrefix "0x" config.sdImage.firmwarePartitionID}-02"
"rootfstype=ext4"
"fsck.repair=yes"
"rootwait"
"init=/sbin/init"
];
systemd.services = { systemd.services = {
"raspberry-pi-firmware-migrate" = "raspberry-pi-firmware-migrate" =
lib.mkIf config.raspberry-pi-nix.firmware-migration-service.enable { {
description = "update the firmware partition"; description = "update the firmware partition";
wantedBy = [ "multi-user.target" ]; wantedBy = if cfg.firmware-migration-service.enable then [ "multi-user.target" ] else [ ];
serviceConfig = serviceConfig =
let firmware-path = "/boot/firmware"; let
in { firmware-path = "/boot/firmware";
kernel-params = pkgs.writeTextFile {
name = "cmdline.txt";
text = ''
${lib.strings.concatStringsSep " " config.boot.kernelParams}
'';
};
in
{
Type = "oneshot"; Type = "oneshot";
MountImages = MountImages =
"/dev/disk/by-label/${config.sdImage.firmwarePartitionName}:${firmware-path}"; "/dev/disk/by-label/${config.sdImage.firmwarePartitionName}:${firmware-path}";
@ -41,6 +87,8 @@
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"
KERNEL="${pkgs.rpi-kernels.latest.kernel}/Image"
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)
@ -61,6 +109,28 @@
rm "$STATE_DIRECTORY/uboot-migration-in-progress" rm "$STATE_DIRECTORY/uboot-migration-in-progress"
} }
migrate_kernel() {
echo "migrating kernel"
touch "$STATE_DIRECTORY/kernel-migration-in-progress"
cp "$KERNEL" "$TMPFILE"
mv -T "$TMPFILE" "$TARGET_FIRMWARE_DIR/kernel.img"
echo "${
builtins.toString pkgs.rpi-kernels.latest.kernel
}" > "$STATE_DIRECTORY/kernel-version"
rm "$STATE_DIRECTORY/kernel-migration-in-progress"
}
migrate_cmdline() {
echo "migrating cmdline"
touch "$STATE_DIRECTORY/cmdline-migration-in-progress"
cp "${kernel-params}" "$TMPFILE"
mv -T "$TMPFILE" "$TARGET_FIRMWARE_DIR/cmdline.txt"
echo "${
builtins.toString kernel-params
}" > "$STATE_DIRECTORY/cmdline-version"
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"
@ -94,12 +164,24 @@
rm "$STATE_DIRECTORY/firmware-migration-in-progress" rm "$STATE_DIRECTORY/firmware-migration-in-progress"
} }
if [[ -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 pkgs.uboot_rpi_arm64 builtins.toString pkgs.uboot_rpi_arm64
} ]]; then } ]]; then
migrate_uboot migrate_uboot
fi fi
if [[ "$SHOULD_UBOOT" -ne 1 ]] && [[ ! -f "$STATE_DIRECTORY/kernel-version" || $(< "$STATE_DIRECTORY/kernel-version") != ${
builtins.toString pkgs.rpi-kernels.latest.kernel
} ]]; then
migrate_kernel
fi
if [[ "$SHOULD_UBOOT" -ne 1 ]] && [[ ! -f "$STATE_DIRECTORY/cmdline-version" || $(< "$STATE_DIRECTORY/cmdline-version") != ${
builtins.toString kernel-params
} ]]; then
migrate_cmdline
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
@ -141,7 +223,7 @@
# linux kernel. # linux kernel.
kernel = { kernel = {
enable = true; enable = true;
value = "u-boot-rpi-arm64.bin"; value = if cfg.uboot.enable then "u-boot-rpi-arm64.bin" else "kernel.img";
}; };
arm_64bit = { arm_64bit = {
enable = true; enable = true;
@ -194,8 +276,9 @@
loader = { loader = {
grub.enable = lib.mkDefault false; grub.enable = lib.mkDefault false;
initScript.enable = !cfg.uboot.enable;
generic-extlinux-compatible = { generic-extlinux-compatible = {
enable = lib.mkDefault true; enable = lib.mkDefault cfg.uboot.enable;
# We want to use the device tree provided by firmware, so don't # We want to use the device tree provided by firmware, so don't
# add FDTDIR to the extlinux conf file. # add FDTDIR to the extlinux conf file.
useGenerationDeviceTree = false; useGenerationDeviceTree = false;
@ -205,10 +288,51 @@
hardware.enableRedistributableFirmware = true; hardware.enableRedistributableFirmware = true;
services = { services = {
udev.extraRules = '' udev.extraRules =
let shell = "${pkgs.bash}/bin/bash";
in ''
# 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=="i2c-dev", GROUP="i2c", MODE="0660"
SUBSYSTEM=="spidev", GROUP="spi", MODE="0660"
SUBSYSTEM=="*gpiomem*", GROUP="gpio", MODE="0660"
SUBSYSTEM=="rpivid-*", 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"
KERNEL=="gpiomem", GROUP="gpio", MODE="0660"
KERNEL=="gpiochip*", 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", 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".
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 '\
ALIASES=/proc/device-tree/aliases; \
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 \
echo 1; \
elif [ -e $$ALIASES/console ]; then \
if [ $$TTYNODE = $$(strings $$ALIASES/console) ]; then \
echo 0;\
else \
exit 1; \
fi \
elif [ $$TTYNODE = $$(strings $$ALIASES/serial0) ]; then \
echo 0; \
elif [ $$TTYNODE = $$(strings $$ALIASES/serial1) ]; then \
echo 1; \
else \
exit 1; \
fi \
'", SYMLINK+="serial%c"
ACTION=="add", SUBSYSTEM=="vtconsole", KERNEL=="vtcon1", RUN+="${shell} -c '\
if echo RPi-Sense FB | cmp -s /sys/class/graphics/fb0/name; then \
echo 0 > /sys$devpath/bind; \
fi; \
'"
''; '';
}; };
}; };

View file

@ -5,22 +5,50 @@
config = { config = {
boot.loader.grub.enable = false; boot.loader.grub.enable = false;
boot.loader.generic-extlinux-compatible.enable = true;
boot.consoleLogLevel = lib.mkDefault 7; boot.consoleLogLevel = lib.mkDefault 7;
# https://github.com/raspberrypi/firmware/issues/1539#issuecomment-784498108 # https://github.com/raspberrypi/firmware/issues/1539#issuecomment-784498108
boot.kernelParams = [ "console=serial0,115200n8" "console=tty1" ]; boot.kernelParams = [ "console=serial0,115200n8" "console=tty1" ];
sdImage = { sdImage =
populateFirmwareCommands = '' let
kernel-params = pkgs.writeTextFile {
name = "cmdline.txt";
text = ''
${lib.strings.concatStringsSep " " config.boot.kernelParams}
'';
};
populate-kernel =
if config.raspberry-pi-nix.uboot.enable
then ''
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
''
else ''
cp "${pkgs.rpi-kernels.latest.kernel}/Image" firmware/kernel.img
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 -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 cp ${config.hardware.raspberry-pi.config-output} firmware/config.txt
''; '';
populateRootCommands = '' populateRootCommands =
if config.raspberry-pi-nix.uboot.enable
then ''
mkdir -p ./files/boot mkdir -p ./files/boot
${config.boot.loader.generic-extlinux-compatible.populateCmd} -c ${config.system.build.toplevel} -d ./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
''; '';
}; };
}; };