diff --git a/README.md b/README.md index 91ca157..4c7882e 100644 --- a/README.md +++ b/README.md @@ -19,64 +19,7 @@ and `rpi/config.nix`. The other modules are mostly wrappers that set ## Example -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 ]; - }; - }; - }; -} -``` +See the `rpi-example` config in this flake for an example config built by CI. ## Using the provided cache to avoid compiling linux This repo uses the raspberry pi linux kernel fork, and compiling linux takes a @@ -87,10 +30,10 @@ to use this cache. ## Building an sd-card image -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: +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: ``` nix build '.#nixosConfigurations.rpi-example.config.system.build.sdImage' diff --git a/flake.nix b/flake.nix index ed8be8e..c0acdc3 100644 --- a/flake.nix +++ b/flake.nix @@ -53,15 +53,18 @@ 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; + nixosModules = { + raspberry-pi = import ./rpi { + inherit pinned; + core-overlay = self.overlays.core; + libcamera-overlay = self.overlays.libcamera; + }; + sd-image = import ./sd-image; }; nixosConfigurations = { rpi-example = srcs.nixpkgs.lib.nixosSystem { system = "aarch64-linux"; - modules = [ self.nixosModules.raspberry-pi ./example ]; + modules = [ self.nixosModules.raspberry-pi self.nixosModules.sd-image ./example ]; }; }; checks.aarch64-linux = self.packages.aarch64-linux; diff --git a/rpi/default.nix b/rpi/default.nix index c5a9d49..5900692 100644 --- a/rpi/default.nix +++ b/rpi/default.nix @@ -6,9 +6,10 @@ 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 = [ ../sd-image ./config.nix ./i2c.nix ]; + imports = [ ./config.nix ./i2c.nix ]; options = with lib; { raspberry-pi-nix = { @@ -25,6 +26,11 @@ 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; @@ -93,7 +99,7 @@ in { Type = "oneshot"; MountImages = - "/dev/disk/by-label/${config.sdImage.firmwarePartitionName}:${firmware-path}"; + "/dev/disk/by-label/${cfg.firmware-partition-label}:${firmware-path}"; StateDirectory = "raspberrypi-firmware"; ExecStart = pkgs.writeShellScript "migrate-rpi-firmware" '' shopt -s nullglob @@ -101,7 +107,7 @@ in TARGET_FIRMWARE_DIR="${firmware-path}" TARGET_OVERLAYS_DIR="$TARGET_FIRMWARE_DIR/overlays" TMPFILE="$TARGET_FIRMWARE_DIR/tmp" - KERNEL="${kernel}/Image" + KERNEL="${kernel}/${config.system.boot.loader.kernelFile}" SHOULD_UBOOT=${if cfg.uboot.enable then "1" else "0"} SRC_FIRMWARE_DIR="${pkgs.raspberrypifw}/share/raspberrypi/boot" STARTFILES=("$SRC_FIRMWARE_DIR"/start*.elf) @@ -130,6 +136,8 @@ 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" @@ -243,6 +251,14 @@ 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; @@ -304,14 +320,9 @@ in 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" + "console=tty1" + # https://github.com/raspberrypi/firmware/issues/1539#issuecomment-784498108 + "console=serial0,115200n8" "init=/sbin/init" ]; initrd = { diff --git a/sd-image/default.nix b/sd-image/default.nix index 212634d..b845de3 100644 --- a/sd-image/default.nix +++ b/sd-image/default.nix @@ -8,8 +8,16 @@ boot.consoleLogLevel = lib.mkDefault 7; - # https://github.com/raspberrypi/firmware/issues/1539#issuecomment-784498108 - boot.kernelParams = [ "console=serial0,115200n8" "console=tty1" ]; + 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" + ]; sdImage = let @@ -22,14 +30,16 @@ cfg = config.raspberry-pi-nix; version = cfg.kernel-version; board = cfg.board; - kernel = config.system.build.kernel; + kernel = "${config.system.build.kernel}/${config.system.boot.loader.kernelFile}"; + initrd = "${config.system.build.initialRamdisk}/${config.system.boot.loader.initrdFile}"; populate-kernel = if cfg.uboot.enable then '' cp ${cfg.uboot.package}/u-boot.bin firmware/u-boot-rpi-arm64.bin '' else '' - cp "${kernel}/Image" firmware/kernel.img + cp "${kernel}" firmware/kernel.img + cp "${initrd}" firmware/initrd cp "${kernel-params}" firmware/cmdline.txt ''; in diff --git a/sd-image/sd-image.nix b/sd-image/sd-image.nix index 9ca69d8..60eedfc 100644 --- a/sd-image/sd-image.nix +++ b/sd-image/sd-image.nix @@ -30,7 +30,8 @@ let } // optionalAttrs (config.sdImage.rootPartitionUUID != null) { uuid = config.sdImage.rootPartitionUUID; }); -in { +in +{ imports = [ ]; options.sdImage = { @@ -82,14 +83,6 @@ 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; @@ -160,7 +153,7 @@ in { config = { fileSystems = { "/boot/firmware" = { - device = "/dev/disk/by-label/${config.sdImage.firmwarePartitionName}"; + device = "/dev/disk/by-label/${config.raspberry-pi-nix.firmware-partition-label}"; fsType = "vfat"; }; "/" = { @@ -226,7 +219,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.sdImage.firmwarePartitionName} 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 # Populate the files intended for /boot/firmware mkdir firmware @@ -244,7 +237,8 @@ in { zstd -T$NIX_BUILD_CORES --rm $img fi ''; - }) { }; + }) + { }; boot.postBootCommands = lib.mkIf config.sdImage.expandOnBoot '' # On the first boot do some maintenance tasks