boot.nix
  1  # Raspberry Pi direct kernel boot module
  2  # Based on nixos-raspberrypi
  3  {
  4    lib,
  5    config,
  6    pkgs,
  7    ...
  8  }:
  9  let
 10    cfg = config.hardware.raspberry-pi.boot;
 11    configTxt = config.hardware.raspberry-pi.config-output;
 12  
 13    configTxtFile = pkgs.writeText "config.txt" configTxt;
 14  
 15    firmwareInstaller = pkgs.writeShellApplication {
 16      name = "rpi-firmware-installer";
 17      runtimeInputs = [ pkgs.coreutils ];
 18      text = ''
 19        FIRMWARE_PATH="${cfg.firmwarePath}"
 20        mkdir -p "$FIRMWARE_PATH"
 21        cp -f "${configTxtFile}" "$FIRMWARE_PATH/config.txt"
 22  
 23        ${lib.optionalString cfg.installDeviceTree ''
 24          DTB_SRC="${config.hardware.deviceTree.package}"
 25          for dtb in "$DTB_SRC"/*.dtb "$DTB_SRC"/broadcom/*.dtb; do
 26            [ -f "$dtb" ] && cp -f "$dtb" "$FIRMWARE_PATH/"
 27          done
 28          if [ -d "$DTB_SRC/overlays" ]; then
 29            mkdir -p "$FIRMWARE_PATH/overlays"
 30            for ovr in "$DTB_SRC/overlays"/*; do
 31              [ -f "$ovr" ] && cp -f "$ovr" "$FIRMWARE_PATH/overlays/"
 32            done
 33          fi
 34        ''}
 35  
 36        ${lib.optionalString cfg.installFirmware ''
 37          FIRMWARE_SRC="${cfg.firmwarePackage}/share/raspberrypi/boot"
 38          for f in "$FIRMWARE_SRC"/start*.elf "$FIRMWARE_SRC"/fixup*.dat; do
 39            [ -f "$f" ] && cp -f "$f" "$FIRMWARE_PATH/"
 40          done
 41          [ -f "$FIRMWARE_SRC/bootcode.bin" ] && cp -f "$FIRMWARE_SRC/bootcode.bin" "$FIRMWARE_PATH/"
 42        ''}
 43      '';
 44    };
 45  
 46    kernelInstaller = pkgs.writeShellApplication {
 47      name = "rpi-kernel-installer";
 48      runtimeInputs = [ pkgs.coreutils ];
 49      text = ''
 50        TOPLEVEL="$1"
 51        FIRMWARE_PATH="${cfg.firmwarePath}"
 52  
 53        KERNEL="$(readlink -f "$TOPLEVEL/kernel")"
 54        INITRD="$(readlink -f "$TOPLEVEL/initrd")"
 55  
 56        cp -f "$KERNEL" "$FIRMWARE_PATH/kernel.img"
 57        cp -f "$INITRD" "$FIRMWARE_PATH/initrd"
 58  
 59        INIT_PATH="$(readlink -f "$TOPLEVEL/init")"
 60        { cat "$TOPLEVEL/kernel-params"; echo -n " init=$INIT_PATH"; } > "$FIRMWARE_PATH/cmdline.txt"
 61      '';
 62    };
 63  
 64  in
 65  {
 66    options.hardware.raspberry-pi.boot = {
 67      enable = lib.mkEnableOption "Raspberry Pi boot management";
 68  
 69      firmwarePath = lib.mkOption {
 70        type = lib.types.str;
 71        default = "/boot/firmware";
 72        description = "Path to the firmware partition (FAT32).";
 73      };
 74  
 75      installDeviceTree = lib.mkOption {
 76        type = lib.types.bool;
 77        default = true;
 78        description = "Install device tree files to firmware partition.";
 79      };
 80  
 81      installFirmware = lib.mkOption {
 82        type = lib.types.bool;
 83        default = true;
 84        description = "Install Raspberry Pi firmware files (start*.elf, fixup*.dat).";
 85      };
 86  
 87      firmwarePackage = lib.mkOption {
 88        type = lib.types.package;
 89        default = pkgs.raspberrypifw;
 90        defaultText = lib.literalExpression "pkgs.raspberrypifw";
 91        description = "Raspberry Pi firmware package.";
 92      };
 93    };
 94  
 95    config = lib.mkIf cfg.enable {
 96      boot.loader.grub.enable = false;
 97      boot.loader.generic-extlinux-compatible.enable = lib.mkForce false;
 98  
 99      hardware.raspberry-pi.config.all.options.kernel = {
100        enable = true;
101        value = "kernel.img";
102      };
103  
104      hardware.raspberry-pi.config-extra = lib.mkAfter ''
105        initramfs initrd followkernel
106      '';
107  
108      system.build.installBootLoader = "${lib.getExe kernelInstaller}";
109      system.boot.loader.id = "raspberrypi-direct";
110      system.boot.loader.kernelFile = pkgs.stdenv.hostPlatform.linux-kernel.target;
111  
112      system.activationScripts.raspberryPiFirmware = {
113        text = "${lib.getExe firmwareInstaller}";
114        deps = [ "specialfs" ];
115      };
116  
117      system.build.raspberryPiConfigTxt = configTxtFile;
118      system.build.raspberryPiKernelInstaller = kernelInstaller;
119    };
120  }