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 }