diff --git a/.github/workflows/update-flake-lock.yml b/.github/workflows/update-flake-lock.yml deleted file mode 100644 index ec1a8cd..0000000 --- a/.github/workflows/update-flake-lock.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: update-flake-lock - -on: - workflow_dispatch: - schedule: - - cron: '0 0 * * 0' - -permissions: - contents: write - pull-requests: write - -jobs: - lockfile: - runs-on: ubuntu-latest - steps: - - name: Checkout repository - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 - - - name: Install nix - uses: DeterminateSystems/nix-installer-action@e50d5f73bfe71c2dd0aa4218de8f4afa59f8f81d # v16 - - - name: Update flake.lock - uses: DeterminateSystems/update-flake-lock@a2bbe0274e3a0c4194390a1e445f734c597ebc37 # v24 diff --git a/README.md b/README.md index 8c94ef9..91ca157 100644 --- a/README.md +++ b/README.md @@ -17,15 +17,66 @@ The important modules are `overlay/default.nix`, `rpi/default.nix`, and `rpi/config.nix`. The other modules are mostly wrappers that set `config.txt` settings and enable required kernel modules. -## Stability note - -`master` is the development branch -- if you want to avoid breaking changes, you -should pin your flake to a specific release and refer to the release notes when -upgrading. - ## Example -See the `rpi-example` config in this flake for an example config built by CI. +See the `rpi-example` config in this flake for a CI-checked example. + +```nix +{ + description = "raspberry-pi-nix example"; + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05"; + raspberry-pi-nix.url = "github:nix-community/raspberry-pi-nix"; + }; + + outputs = { self, nixpkgs, raspberry-pi-nix }: + let + inherit (nixpkgs.lib) nixosSystem; + basic-config = { pkgs, lib, ... }: { + # bcm2711 for rpi 3, 3+, 4, zero 2 w + # bcm2712 for rpi 5 + # See the docs at: + # https://www.raspberrypi.com/documentation/computers/linux_kernel.html#native-build-configuration + raspberry-pi-nix.board = "bcm2711"; + time.timeZone = "America/New_York"; + users.users.root.initialPassword = "root"; + networking = { + hostName = "basic-example"; + useDHCP = false; + interfaces = { + wlan0.useDHCP = true; + eth0.useDHCP = true; + }; + }; + hardware = { + bluetooth.enable = true; + raspberry-pi = { + config = { + all = { + base-dt-params = { + # enable autoprobing of bluetooth driver + # https://github.com/raspberrypi/linux/blob/c8c99191e1419062ac8b668956d19e788865912a/arch/arm/boot/dts/overlays/README#L222-L224 + krnbt = { + enable = true; + value = "on"; + }; + }; + }; + }; + }; + }; + }; + + in { + nixosConfigurations = { + rpi-example = nixosSystem { + system = "aarch64-linux"; + modules = [ raspberry-pi-nix.nixosModules.raspberry-pi basic-config ]; + }; + }; + }; +} +``` ## Using the provided cache to avoid compiling linux This repo uses the raspberry pi linux kernel fork, and compiling linux takes a @@ -36,10 +87,10 @@ to use this cache. ## Building an sd-card image -Include the provided `sd-image` nixos module this flake provides, then an image -suitable for flashing to an sd-card can be found at the attribute -`config.system.build.sdImage`. For example, if you wanted to build an image for -`rpi-example` in the above configuration example you could run: +An image suitable for flashing to an sd-card can be found at the +attribute `config.system.build.sdImage`. For example, if you wanted to +build an image for `rpi-example` in the above configuration +example you could run: ``` nix build '.#nixosConfigurations.rpi-example.config.system.build.sdImage' diff --git a/flake.lock b/flake.lock index 81f91aa..abb934b 100644 --- a/flake.lock +++ b/flake.lock @@ -36,16 +36,16 @@ }, "nixpkgs": { "locked": { - "lastModified": 1736061677, - "narHash": "sha256-DjkQPnkAfd7eB522PwnkGhOMuT9QVCZspDpJJYyOj60=", + "lastModified": 1728193676, + "narHash": "sha256-PbDWAIjKJdlVg+qQRhzdSor04bAPApDqIv2DofTyynk=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "cbd8ec4de4469333c82ff40d057350c30e9f7d36", + "rev": "ecbc1ca8ffd6aea8372ad16be9ebbb39889e55b6", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixos-24.11", + "ref": "nixos-24.05", "repo": "nixpkgs", "type": "github" } @@ -58,10 +58,10 @@ "rpi-bluez-firmware-src": "rpi-bluez-firmware-src", "rpi-firmware-nonfree-src": "rpi-firmware-nonfree-src", "rpi-firmware-src": "rpi-firmware-src", - "rpi-linux-6_12_17-src": "rpi-linux-6_12_17-src", - "rpi-linux-6_6_78-src": "rpi-linux-6_6_78-src", - "rpi-linux-stable-src": "rpi-linux-stable-src", - "rpicam-apps-src": "rpicam-apps-src" + "rpi-linux-6_10_12-src": "rpi-linux-6_10_12-src", + "rpi-linux-6_6_54-src": "rpi-linux-6_6_54-src", + "rpicam-apps-src": "rpicam-apps-src", + "u-boot-src": "u-boot-src" } }, "rpi-bluez-firmware-src": { @@ -101,45 +101,45 @@ "rpi-firmware-src": { "flake": false, "locked": { - "lastModified": 1728405098, - "narHash": "sha256-4gnK0KbqFnjBmWia9Jt2gveVWftmHrprpwBqYVqE/k0=", + "lastModified": 1727798811, + "narHash": "sha256-eavbshXGYmkYR33y9FLcQMJoAYdYTESVEy0g/RRXnb0=", "owner": "raspberrypi", "repo": "firmware", - "rev": "7bbb5f80d20a2335066a8781459c9f33e5eebc64", + "rev": "287e6a6c2d3b50eee3e2c5b2eacdd907e5cbe09a", "type": "github" }, "original": { "owner": "raspberrypi", - "ref": "1.20241008", + "ref": "1.20241001", "repo": "firmware", "type": "github" } }, - "rpi-linux-6_12_17-src": { + "rpi-linux-6_10_12-src": { "flake": false, "locked": { - "lastModified": 1740765145, - "narHash": "sha256-hoCsGc4+RC/2LmxDtswLBL5ZhWlw4vSiL4Vkl39r2MU=", + "lastModified": 1728305462, + "narHash": "sha256-LtvNmGD1D5YYv+C9xxxddAeHw69o3OX/H9M7F663L74=", "owner": "raspberrypi", "repo": "linux", - "rev": "5985ce32e511f4e8279a841a1b06a8c7d972b386", + "rev": "26ee50d56618c2d98100b1bc672fd201aed4d00f", "type": "github" }, "original": { "owner": "raspberrypi", - "ref": "rpi-6.12.y", + "ref": "rpi-6.10.y", "repo": "linux", "type": "github" } }, - "rpi-linux-6_6_78-src": { + "rpi-linux-6_6_54-src": { "flake": false, "locked": { - "lastModified": 1740503700, - "narHash": "sha256-Y8+ot4Yi3UKwlZK3ap15rZZ16VZDvmeFkD46+6Ku7bE=", + "lastModified": 1728155174, + "narHash": "sha256-/8RjW35XQMnshjAE4Ey8j3oWzE2GOntnBYY6PlvZGhs=", "owner": "raspberrypi", "repo": "linux", - "rev": "2e071057fded90e789c0101498e45a1778be93fe", + "rev": "12f0f28db3afe451a81a34c5a444f6841c10067c", "type": "github" }, "original": { @@ -149,23 +149,6 @@ "type": "github" } }, - "rpi-linux-stable-src": { - "flake": false, - "locked": { - "lastModified": 1728403745, - "narHash": "sha256-phCxkuO+jUGZkfzSrBq6yErQeO2Td+inIGHxctXbD5U=", - "owner": "raspberrypi", - "repo": "linux", - "rev": "5aeecea9f4a45248bcf564dec924965e066a7bfd", - "type": "github" - }, - "original": { - "owner": "raspberrypi", - "ref": "stable_20241008", - "repo": "linux", - "type": "github" - } - }, "rpicam-apps-src": { "flake": false, "locked": { @@ -182,6 +165,19 @@ "repo": "rpicam-apps", "type": "github" } + }, + "u-boot-src": { + "flake": false, + "locked": { + "lastModified": 1719857238, + "narHash": "sha256-mJ2TBy0Y5ZtcGFgtU5RKr0UDUp5FWzojbFb+o/ebRJU=", + "type": "tarball", + "url": "https://ftp.denx.de/pub/u-boot/u-boot-2024.07.tar.bz2" + }, + "original": { + "type": "tarball", + "url": "https://ftp.denx.de/pub/u-boot/u-boot-2024.07.tar.bz2" + } } }, "root": "root", diff --git a/flake.nix b/flake.nix index fe3fc24..ed8be8e 100644 --- a/flake.nix +++ b/flake.nix @@ -2,22 +2,22 @@ description = "raspberry-pi nixos configuration"; inputs = { - nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11"; - rpi-linux-stable-src = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05"; + u-boot-src = { flake = false; - url = "github:raspberrypi/linux/stable_20241008"; + url = "https://ftp.denx.de/pub/u-boot/u-boot-2024.07.tar.bz2"; }; - rpi-linux-6_6_78-src = { + rpi-linux-6_6_54-src = { flake = false; url = "github:raspberrypi/linux/rpi-6.6.y"; }; - rpi-linux-6_12_17-src = { + rpi-linux-6_10_12-src = { flake = false; - url = "github:raspberrypi/linux/rpi-6.12.y"; + url = "github:raspberrypi/linux/rpi-6.10.y"; }; rpi-firmware-src = { flake = false; - url = "github:raspberrypi/firmware/1.20241008"; + url = "github:raspberrypi/firmware/1.20241001"; }; rpi-firmware-nonfree-src = { flake = false; @@ -53,18 +53,15 @@ core = import ./overlays (builtins.removeAttrs srcs [ "self" ]); libcamera = import ./overlays/libcamera.nix (builtins.removeAttrs srcs [ "self" ]); }; - nixosModules = { - raspberry-pi = import ./rpi { - inherit pinned; - core-overlay = self.overlays.core; - libcamera-overlay = self.overlays.libcamera; - }; - sd-image = import ./sd-image; + nixosModules.raspberry-pi = import ./rpi { + inherit pinned; + core-overlay = self.overlays.core; + libcamera-overlay = self.overlays.libcamera; }; nixosConfigurations = { rpi-example = srcs.nixpkgs.lib.nixosSystem { system = "aarch64-linux"; - modules = [ self.nixosModules.raspberry-pi self.nixosModules.sd-image ./example ]; + modules = [ self.nixosModules.raspberry-pi ./example ]; }; }; checks.aarch64-linux = self.packages.aarch64-linux; diff --git a/overlays/default.nix b/overlays/default.nix index b859342..162330c 100644 --- a/overlays/default.nix +++ b/overlays/default.nix @@ -1,6 +1,6 @@ -{ rpi-linux-stable-src -, rpi-linux-6_6_78-src -, rpi-linux-6_12_17-src +{ u-boot-src +, rpi-linux-6_6_54-src +, rpi-linux-6_10_12-src , rpi-firmware-src , rpi-firmware-nonfree-src , rpi-bluez-firmware-src @@ -9,10 +9,9 @@ final: prev: let versions = { - v6_6_51.src = rpi-linux-stable-src; - v6_6_78.src = rpi-linux-6_6_78-src; - v6_12_17 = { - src = rpi-linux-6_12_17-src; + v6_6_54.src = rpi-linux-6_6_54-src; + v6_10_12 = { + src = rpi-linux-6_10_12-src; patches = [ { name = "remove-readme-target.patch"; @@ -62,7 +61,6 @@ let features.efiBootStub = false; kernelPatches = if kernel ? "patches" then kernel.patches else [ ]; - ignoreConfigErrors = true; }).overrideAttrs (oldAttrs: { postConfigure = '' @@ -83,10 +81,14 @@ in compressFirmwareZstd = x: x; # provide generic rpi arm64 u-boot - uboot-rpi-arm64 = final.buildUBoot { + uboot-rpi-arm64 = final.buildUBoot rec { defconfig = "rpi_arm64_defconfig"; extraMeta.platforms = [ "aarch64-linux" ]; filesToInstall = [ "u-boot.bin" ]; + version = "2024.04"; + patches = [ ]; + makeFlags = [ ]; + src = u-boot-src; # In raspberry pi sbcs the firmware manipulates the device tree in # a variety of ways before handing it off to the linux kernel. [1] # Since we have installed u-boot in place of a linux kernel we may @@ -114,7 +116,7 @@ in # rpi kernels and firmware are available at # `pkgs.rpi-kernels..'. # - # For example: `pkgs.rpi-kernels.v6_6_78.bcm2712' + # For example: `pkgs.rpi-kernels.v6_6_54.bcm2712' rpi-kernels = rpi-kernels ( final.lib.cartesianProduct { board = boards; version = (builtins.attrNames versions); } diff --git a/rpi/default.nix b/rpi/default.nix index ff0a62b..c5a9d49 100644 --- a/rpi/default.nix +++ b/rpi/default.nix @@ -6,15 +6,14 @@ let version = cfg.kernel-version; board = cfg.board; kernel = config.system.build.kernel; - initrd = "${config.system.build.initialRamdisk}/${config.system.boot.loader.initrdFile}"; in { - imports = [ ./config.nix ./i2c.nix ]; + imports = [ ../sd-image ./config.nix ./i2c.nix ]; options = with lib; { raspberry-pi-nix = { kernel-version = mkOption { - default = "v6_6_51"; + default = "v6_6_54"; type = types.str; description = "Kernel version to build."; }; @@ -26,11 +25,6 @@ in without the _defconfig part. ''; }; - firmware-partition-label = mkOption { - default = "FIRMWARE"; - type = types.str; - description = "label of rpi firmware partition"; - }; pin-inputs = { enable = mkOption { default = true; @@ -77,18 +71,6 @@ in package = mkPackageOption pkgs "uboot-rpi-arm64" { }; }; - serial-console = { - enable = mkOption { - default = true; - type = types.bool; - description = '' - Whether to enable a console on serial0. - - Corresponds with raspi-config's setting - "Would you like a login shell to be accessible over serial?" - ''; - }; - }; }; }; @@ -111,7 +93,7 @@ in { Type = "oneshot"; MountImages = - "/dev/disk/by-label/${cfg.firmware-partition-label}:${firmware-path}"; + "/dev/disk/by-label/${config.sdImage.firmwarePartitionName}:${firmware-path}"; StateDirectory = "raspberrypi-firmware"; ExecStart = pkgs.writeShellScript "migrate-rpi-firmware" '' shopt -s nullglob @@ -119,7 +101,7 @@ in TARGET_FIRMWARE_DIR="${firmware-path}" TARGET_OVERLAYS_DIR="$TARGET_FIRMWARE_DIR/overlays" TMPFILE="$TARGET_FIRMWARE_DIR/tmp" - KERNEL="${kernel}/${config.system.boot.loader.kernelFile}" + KERNEL="${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) @@ -148,8 +130,6 @@ in touch "$STATE_DIRECTORY/kernel-migration-in-progress" cp "$KERNEL" "$TMPFILE" mv -T "$TMPFILE" "$TARGET_FIRMWARE_DIR/kernel.img" - cp "${initrd}" "$TMPFILE" - mv -T "$TMPFILE" "$TARGET_FIRMWARE_DIR/initrd" echo "${ builtins.toString kernel }" > "$STATE_DIRECTORY/kernel-version" @@ -263,14 +243,6 @@ in enable = true; value = if cfg.uboot.enable then "u-boot-rpi-arm64.bin" else "kernel.img"; }; - ramfsfile = { - enable = !cfg.uboot.enable; - value = "initrd"; - }; - ramfsaddr = { - enable = !cfg.uboot.enable; - value = -1; - }; arm_64bit = { enable = true; value = true; @@ -331,14 +303,16 @@ in boot = { kernelParams = if cfg.uboot.enable then [ ] - else builtins.concatLists [ - [ "console=tty1" ] - (if cfg.serial-console.enable then [ - # https://github.com/raspberrypi/firmware/issues/1539#issuecomment-784498108 - "console=serial0,115200n8" - ] else [ ] - ) - [ "init=/sbin/init" ] + 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" ]; initrd = { availableKernelModules = [ diff --git a/sd-image/default.nix b/sd-image/default.nix index b845de3..212634d 100644 --- a/sd-image/default.nix +++ b/sd-image/default.nix @@ -8,16 +8,8 @@ boot.consoleLogLevel = lib.mkDefault 7; - boot.kernelParams = [ - # 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" - ]; + # https://github.com/raspberrypi/firmware/issues/1539#issuecomment-784498108 + boot.kernelParams = [ "console=serial0,115200n8" "console=tty1" ]; sdImage = let @@ -30,16 +22,14 @@ 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}"; + kernel = config.system.build.kernel; 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}/Image" firmware/kernel.img cp "${kernel-params}" firmware/cmdline.txt ''; in diff --git a/sd-image/sd-image.nix b/sd-image/sd-image.nix index b9fed6a..9ca69d8 100644 --- a/sd-image/sd-image.nix +++ b/sd-image/sd-image.nix @@ -30,8 +30,7 @@ let } // optionalAttrs (config.sdImage.rootPartitionUUID != null) { uuid = config.sdImage.rootPartitionUUID; }); -in -{ +in { imports = [ ]; options.sdImage = { @@ -83,6 +82,14 @@ in ''; }; + firmwarePartitionName = mkOption { + type = types.str; + default = "FIRMWARE"; + description = '' + Name of the filesystem which holds the boot firmware. + ''; + }; + rootPartitionUUID = mkOption { type = types.nullOr types.str; default = null; @@ -153,7 +160,7 @@ in config = { fileSystems = { "/boot/firmware" = { - device = "/dev/disk/by-label/${config.raspberry-pi-nix.firmware-partition-label}"; + device = "/dev/disk/by-label/${config.sdImage.firmwarePartitionName}"; fsType = "vfat"; }; "/" = { @@ -219,7 +226,7 @@ in # Create a FAT32 /boot/firmware partition of suitable size into firmware_part.img eval $(partx $img -o START,SECTORS --nr 1 --pairs) 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.sdImage.firmwarePartitionName} firmware_part.img # Populate the files intended for /boot/firmware mkdir firmware @@ -237,8 +244,7 @@ in zstd -T$NIX_BUILD_CORES --rm $img fi ''; - }) - { }; + }) { }; boot.postBootCommands = lib.mkIf config.sdImage.expandOnBoot '' # On the first boot do some maintenance tasks @@ -248,7 +254,7 @@ in # Figure out device names for the boot device and root filesystem. rootPart=$(${pkgs.util-linux}/bin/findmnt -n -o SOURCE /) bootDevice=$(lsblk -npo PKNAME $rootPart) - partNum=$(lsblk -npo PARTN $rootPart) + partNum=$(lsblk -npo MAJ:MIN $rootPart | ${pkgs.gawk}/bin/awk -F: '{print $2}') # Resize the root partition and the filesystem to fit the disk echo ",+," | sfdisk -N$partNum --no-reread $bootDevice