diff --git a/nixos/modules/system/boot/loader/raspberrypi/builder.sh b/nixos/modules/system/boot/loader/raspberrypi/builder.sh index f627d093eafb..8adc8a6a7e11 100644 --- a/nixos/modules/system/boot/loader/raspberrypi/builder.sh +++ b/nixos/modules/system/boot/loader/raspberrypi/builder.sh @@ -109,11 +109,15 @@ copyForced $fwdir/bootcode.bin /boot/bootcode.bin copyForced $fwdir/fixup.dat /boot/fixup.dat copyForced $fwdir/fixup_cd.dat /boot/fixup_cd.dat copyForced $fwdir/fixup_db.dat /boot/fixup_db.dat +copyForced $fwdir/fixup_x.dat /boot/fixup_x.dat copyForced $fwdir/start.elf /boot/start.elf copyForced $fwdir/start_cd.elf /boot/start_cd.elf copyForced $fwdir/start_db.elf /boot/start_db.elf copyForced $fwdir/start_x.elf /boot/start_x.elf +# Add the config.txt +copyForced @configTxt@ /boot/config.txt + # Remove obsolete files from /boot and /boot/old. for fn in /boot/old/*linux* /boot/old/*initrd-initrd* /boot/bcm*.dtb; do if ! test "${filesCopied[$fn]}" = 1; then diff --git a/nixos/modules/system/boot/loader/raspberrypi/builder_uboot.nix b/nixos/modules/system/boot/loader/raspberrypi/builder_uboot.nix new file mode 100644 index 000000000000..47f25a9c2b1b --- /dev/null +++ b/nixos/modules/system/boot/loader/raspberrypi/builder_uboot.nix @@ -0,0 +1,34 @@ +{ config, pkgs, configTxt }: + +let + cfg = config.boot.loader.raspberryPi; + isAarch64 = pkgs.stdenv.isAarch64; + + uboot = + if cfg.version == 1 then + pkgs.ubootRaspberryPi + else if cfg.version == 2 then + pkgs.ubootRaspberryPi2 + else + if isAarch64 then + pkgs.ubootRaspberryPi3_64bit + else + pkgs.ubootRaspberryPi3_32bit; + + extlinuxConfBuilder = + import ../generic-extlinux-compatible/extlinux-conf-builder.nix { + inherit pkgs; + }; +in +pkgs.substituteAll { + src = ./builder_uboot.sh; + isExecutable = true; + inherit (pkgs) bash; + path = [pkgs.coreutils pkgs.gnused pkgs.gnugrep]; + firmware = pkgs.raspberrypifw; + inherit uboot; + inherit configTxt; + inherit extlinuxConfBuilder; + version = cfg.version; +} + diff --git a/nixos/modules/system/boot/loader/raspberrypi/builder_uboot.sh b/nixos/modules/system/boot/loader/raspberrypi/builder_uboot.sh new file mode 100644 index 000000000000..36bf15066274 --- /dev/null +++ b/nixos/modules/system/boot/loader/raspberrypi/builder_uboot.sh @@ -0,0 +1,29 @@ +#! @bash@/bin/sh -e + +copyForced() { + local src="$1" + local dst="$2" + cp $src $dst.tmp + mv $dst.tmp $dst +} + +# Call the extlinux builder +"@extlinuxConfBuilder@" "$@" + +# Add the firmware files +fwdir=@firmware@/share/raspberrypi/boot/ +copyForced $fwdir/bootcode.bin /boot/bootcode.bin +copyForced $fwdir/fixup.dat /boot/fixup.dat +copyForced $fwdir/fixup_cd.dat /boot/fixup_cd.dat +copyForced $fwdir/fixup_db.dat /boot/fixup_db.dat +copyForced $fwdir/fixup_x.dat /boot/fixup_x.dat +copyForced $fwdir/start.elf /boot/start.elf +copyForced $fwdir/start_cd.elf /boot/start_cd.elf +copyForced $fwdir/start_db.elf /boot/start_db.elf +copyForced $fwdir/start_x.elf /boot/start_x.elf + +# Add the uboot file +copyForced @uboot@/u-boot.bin /boot/u-boot-rpi.bin + +# Add the config.txt +copyForced @configTxt@ /boot/config.txt diff --git a/nixos/modules/system/boot/loader/raspberrypi/raspberrypi.nix b/nixos/modules/system/boot/loader/raspberrypi/raspberrypi.nix index f246d04284ca..adf13ce6098c 100644 --- a/nixos/modules/system/boot/loader/raspberrypi/raspberrypi.nix +++ b/nixos/modules/system/boot/loader/raspberrypi/raspberrypi.nix @@ -5,42 +5,99 @@ with lib; let cfg = config.boot.loader.raspberryPi; - builder = pkgs.substituteAll { + builderGeneric = pkgs.substituteAll { src = ./builder.sh; isExecutable = true; inherit (pkgs) bash; path = [pkgs.coreutils pkgs.gnused pkgs.gnugrep]; firmware = pkgs.raspberrypifw; version = cfg.version; + inherit configTxt; }; platform = pkgs.stdenv.platform; + builderUboot = import ./builder_uboot.nix { inherit config; inherit pkgs; inherit configTxt; }; + + builder = + if cfg.uboot.enable then + "${builderUboot} -g ${toString cfg.uboot.configurationLimit} -t ${timeoutStr} -c" + else + builderGeneric; + + blCfg = config.boot.loader; + timeoutStr = if blCfg.timeout == null then "-1" else toString blCfg.timeout; + + isAarch64 = pkgs.stdenv.isAarch64; + optional = pkgs.stdenv.lib.optionalString; + + configTxt = + pkgs.writeText "config.txt" ('' + # U-Boot used to need this to work, regardless of whether UART is actually used or not. + # TODO: check when/if this can be removed. + enable_uart=1 + + # Prevent the firmware from smashing the framebuffer setup done by the mainline kernel + # when attempting to show low-voltage or overtemperature warnings. + avoid_warnings=1 + '' + optional isAarch64 '' + # Boot in 64-bit mode. + arm_control=0x200 + '' + optional cfg.uboot.enable '' + kernel=u-boot-rpi.bin + ''); + in { options = { - boot.loader.raspberryPi.enable = mkOption { - default = false; - type = types.bool; - description = '' - Whether to create files with the system generations in - /boot. - /boot/old will hold files from old generations. - ''; - }; + boot.loader.raspberryPi = { + enable = mkOption { + default = false; + type = types.bool; + description = '' + Whether to create files with the system generations in + /boot. + /boot/old will hold files from old generations. + ''; + }; - boot.loader.raspberryPi.version = mkOption { - default = 2; - type = types.enum [ 1 2 3 ]; - description = '' - ''; - }; + version = mkOption { + default = 2; + type = types.enum [ 1 2 3 ]; + description = '' + ''; + }; + uboot = { + enable = mkOption { + default = false; + type = types.bool; + description = '' + Enable using uboot as bootmanager for the raspberry pi. + ''; + }; + + configurationLimit = mkOption { + default = 20; + example = 10; + type = types.int; + description = '' + Maximum number of configurations in the boot menu. + ''; + }; + + }; + }; }; - config = mkIf config.boot.loader.raspberryPi.enable { + config = mkIf cfg.enable { + assertions = singleton { + assertion = !pkgs.stdenv.isAarch64 || cfg.version == 3; + message = "Only Raspberry Pi 3 supports aarch64."; + }; + system.build.installBootLoader = builder; system.boot.loader.id = "raspberrypi"; system.boot.loader.kernelFile = platform.kernelTarget;