summary refs log tree commit diff
path: root/nixos/modules/system/boot
diff options
context:
space:
mode:
authorBastian Köcher <git@kchr.de>2018-04-02 00:28:50 +0200
committerTuomas Tynkkynen <tuomas.tynkkynen@iki.fi>2018-04-22 18:27:17 +0300
commit8bc970bbc7c4ee9423844fbe7a6561ed90d414db (patch)
tree2baffa2217d7ba0681d548c03fc074dff5171d0f /nixos/modules/system/boot
parentc3e78d3988b8b4a3b5d51fabd3efed5b196ae07e (diff)
downloadnixlib-8bc970bbc7c4ee9423844fbe7a6561ed90d414db.tar
nixlib-8bc970bbc7c4ee9423844fbe7a6561ed90d414db.tar.gz
nixlib-8bc970bbc7c4ee9423844fbe7a6561ed90d414db.tar.bz2
nixlib-8bc970bbc7c4ee9423844fbe7a6561ed90d414db.tar.lz
nixlib-8bc970bbc7c4ee9423844fbe7a6561ed90d414db.tar.xz
nixlib-8bc970bbc7c4ee9423844fbe7a6561ed90d414db.tar.zst
nixlib-8bc970bbc7c4ee9423844fbe7a6561ed90d414db.zip
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.
Diffstat (limited to 'nixos/modules/system/boot')
-rw-r--r--nixos/modules/system/boot/loader/raspberrypi/builder.sh4
-rw-r--r--nixos/modules/system/boot/loader/raspberrypi/builder_uboot.nix34
-rw-r--r--nixos/modules/system/boot/loader/raspberrypi/builder_uboot.sh29
-rw-r--r--nixos/modules/system/boot/loader/raspberrypi/raspberrypi.nix91
4 files changed, 141 insertions, 17 deletions
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
-        <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.
+        '';
+      };
 
-    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;