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 }:
{ lib, pkgs, config, ... }:
let cfg = config.raspberry-pi-nix;
in
{
imports = [ ../sd-image ./config.nix ./i2c.nix ];
@ -10,26 +12,70 @@
enable = mkOption {
default = true;
type = types.bool;
description = ''
Whether to run the migration service automatically or not.
'';
};
};
libcamera-overlay = {
enable = mkOption {
default = true;
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 = {
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 = {
"raspberry-pi-firmware-migrate" =
lib.mkIf config.raspberry-pi-nix.firmware-migration-service.enable {
{
description = "update the firmware partition";
wantedBy = [ "multi-user.target" ];
wantedBy = if cfg.firmware-migration-service.enable then [ "multi-user.target" ] else [ ];
serviceConfig =
let firmware-path = "/boot/firmware";
in {
let
firmware-path = "/boot/firmware";
kernel-params = pkgs.writeTextFile {
name = "cmdline.txt";
text = ''
${lib.strings.concatStringsSep " " config.boot.kernelParams}
'';
};
in
{
Type = "oneshot";
MountImages =
"/dev/disk/by-label/${config.sdImage.firmwarePartitionName}:${firmware-path}";
@ -41,6 +87,8 @@
TARGET_OVERLAYS_DIR="$TARGET_FIRMWARE_DIR/overlays"
TMPFILE="$TARGET_FIRMWARE_DIR/tmp"
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"
STARTFILES=("$SRC_FIRMWARE_DIR"/start*.elf)
DTBS=("$SRC_FIRMWARE_DIR"/*.dtb)
@ -61,6 +109,28 @@
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() {
echo "migrating config.txt"
touch "$STATE_DIRECTORY/config-migration-in-progress"
@ -94,12 +164,24 @@
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
} ]]; then
migrate_uboot
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") != ${
builtins.toString config.hardware.raspberry-pi.config-output
} ]]; then
@ -141,7 +223,7 @@
# linux kernel.
kernel = {
enable = true;
value = "u-boot-rpi-arm64.bin";
value = if cfg.uboot.enable then "u-boot-rpi-arm64.bin" else "kernel.img";
};
arm_64bit = {
enable = true;
@ -194,8 +276,9 @@
loader = {
grub.enable = lib.mkDefault false;
initScript.enable = !cfg.uboot.enable;
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
# add FDTDIR to the extlinux conf file.
useGenerationDeviceTree = false;
@ -205,11 +288,52 @@
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"
'';
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=="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,23 +5,51 @@
config = {
boot.loader.grub.enable = false;
boot.loader.generic-extlinux-compatible.enable = true;
boot.consoleLogLevel = lib.mkDefault 7;
# https://github.com/raspberrypi/firmware/issues/1539#issuecomment-784498108
boot.kernelParams = [ "console=serial0,115200n8" "console=tty1" ];
sdImage = {
populateFirmwareCommands = ''
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 ${config.hardware.raspberry-pi.config-output} firmware/config.txt
'';
populateRootCommands = ''
mkdir -p ./files/boot
${config.boot.loader.generic-extlinux-compatible.populateCmd} -c ${config.system.build.toplevel} -d ./files/boot
'';
};
sdImage =
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
''
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 ${config.hardware.raspberry-pi.config-output} firmware/config.txt
'';
populateRootCommands =
if config.raspberry-pi-nix.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
'';
};
};
}