raspberrypi-bootloader: Adds support for using uboot

Uboot is copied into `/boot` in the installation process.
The boot entries are created by calling the `generic-extlinux-compatible` builder.

Changed files
+141 -17
nixos
modules
+4
nixos/modules/system/boot/loader/raspberrypi/builder.sh
···
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
+34
nixos/modules/system/boot/loader/raspberrypi/builder_uboot.nix
···
+
{ 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;
+
}
+
+29
nixos/modules/system/boot/loader/raspberrypi/builder_uboot.sh
···
+
#! @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
+74 -17
nixos/modules/system/boot/loader/raspberrypi/raspberrypi.nix
···
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
-
<literal>/boot</literal>.
-
<literal>/boot/old</literal> 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
+
<literal>/boot</literal>.
+
<literal>/boot/old</literal> will hold files from old generations.
+
'';
+
};
+
+
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.
+
'';
+
};
+
+
};
};
+
};
-
boot.loader.raspberryPi.version = mkOption {
-
default = 2;
-
type = types.enum [ 1 2 3 ];
-
description = ''
-
'';
+
config = mkIf cfg.enable {
+
assertions = singleton {
+
assertion = !pkgs.stdenv.isAarch64 || cfg.version == 3;
+
message = "Only Raspberry Pi 3 supports aarch64.";
};
-
};
-
-
config = mkIf config.boot.loader.raspberryPi.enable {
system.build.installBootLoader = builder;
system.boot.loader.id = "raspberrypi";
system.boot.loader.kernelFile = platform.kernelTarget;