diff --git a/nixos/modules/hardware/device-tree.nix b/nixos/modules/hardware/device-tree.nix new file mode 100644 index 00000000000..20066939572 --- /dev/null +++ b/nixos/modules/hardware/device-tree.nix @@ -0,0 +1,56 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.hardware.deviceTree; +in { + options = { + hardware.deviceTree = { + enable = mkOption { + default = pkgs.stdenv.hostPlatform.platform.kernelDTB or false; + type = types.bool; + description = '' + Build device tree files. These are used to describe the + non-discoverable hardware of a system. + ''; + }; + + base = mkOption { + default = "${config.boot.kernelPackages.kernel}/dtbs"; + defaultText = "\${config.boot.kernelPackages.kernel}/dtbs"; + example = literalExample "pkgs.deviceTree.raspberryPiDtbs"; + type = types.nullOr types.path; + description = '' + The package containing the base device-tree (.dtb) to boot. Contains + device trees bundled with the Linux kernel by default. + ''; + }; + + overlays = mkOption { + default = []; + example = literalExample + "[\"\${pkgs.deviceTree.raspberryPiOverlays}/w1-gpio.dtbo\"]"; + type = types.listOf types.path; + description = '' + A path containing device tree overlays (.dtbo) to be applied to all + base device-trees. + ''; + }; + + package = mkOption { + default = null; + type = types.nullOr types.path; + description = '' + A path containing device tree overlays (.dtbo) to be applied to all + base device-trees. Overrides `base` and `overlays`. + ''; + }; + }; + }; + + config = mkIf (cfg.enable) { + hardware.deviceTree.package = if (cfg.overlays != []) + then pkgs.deviceTree.applyOverlays cfg.base cfg.overlays else cfg.base; + }; +} diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 15990177d74..cf00fecc44f 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -46,6 +46,7 @@ ./hardware/cpu/amd-microcode.nix ./hardware/cpu/intel-microcode.nix ./hardware/digitalbitbox.nix + ./hardware/device-tree.nix ./hardware/sensor/iio.nix ./hardware/ksm.nix ./hardware/ledger.nix diff --git a/nixos/modules/system/activation/top-level.nix b/nixos/modules/system/activation/top-level.nix index 5c88d27b6c6..f67d2900561 100644 --- a/nixos/modules/system/activation/top-level.nix +++ b/nixos/modules/system/activation/top-level.nix @@ -46,8 +46,8 @@ let ln -s ${kernelPath} $out/kernel ln -s ${config.system.modulesTree} $out/kernel-modules - ${optionalString (pkgs.stdenv.hostPlatform.platform.kernelDTB or false) '' - ln -s ${config.boot.kernelPackages.kernel}/dtbs $out/dtbs + ${optionalString (config.hardware.deviceTree.package != null) '' + ln -s ${config.hardware.deviceTree.package} $out/dtbs ''} echo -n "$kernelParams" > $out/kernel-params diff --git a/nixos/modules/system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.sh b/nixos/modules/system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.sh index c780a89b102..0092ee92b62 100644 --- a/nixos/modules/system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.sh +++ b/nixos/modules/system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.sh @@ -75,9 +75,8 @@ addEntry() { copyToKernelsDir "$path/kernel"; kernel=$result copyToKernelsDir "$path/initrd"; initrd=$result - # XXX UGLY: maybe the system config should have a top-level "dtbs" entry? - dtbDir=$(readlink -m "$path/kernel/../dtbs") - if [ -d "$dtbDir" ]; then + dtbDir=$(readlink -m "$path/dtbs") + if [ -e "$dtbDir" ]; then copyToKernelsDir "$dtbDir"; dtbs=$result fi diff --git a/pkgs/os-specific/linux/device-tree.nix b/pkgs/os-specific/linux/device-tree.nix new file mode 100644 index 00000000000..81dccac8b8c --- /dev/null +++ b/pkgs/os-specific/linux/device-tree.nix @@ -0,0 +1,28 @@ +{ stdenvNoCC, dtc, findutils, raspberrypifw }: + +with stdenvNoCC.lib; { + applyOverlays = (base: overlays: stdenvNoCC.mkDerivation { + name = "device-tree-overlays"; + nativeBuildInputs = [ dtc findutils ]; + buildCommand = let + quotedDtbos = concatMapStringsSep " " (o: "\"${toString o}\"") (toList overlays); + in '' + for dtb in $(find ${base} -name "*.dtb" ); do + outDtb=$out/$(realpath --relative-to "${base}" "$dtb") + mkdir -p "$(dirname "$outDtb")" + fdtoverlay -o "$outDtb" -i "$dtb" ${quotedDtbos}; + done + ''; + }); + + raspberryPiDtbs = stdenvNoCC.mkDerivation { + name = "raspberrypi-dtbs-${raspberrypifw.version}"; + nativeBuildInputs = [ raspberrypifw ]; + buildCommand = '' + mkdir -p $out/broadcom/ + cp ${raspberrypifw}/share/raspberrypi/boot/bcm*.dtb $out/broadcom + ''; + }; + + raspberryPiOverlays = "${raspberrypifw}/share/raspberrypi/boot/overlays"; +} diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 25515fe593c..44cd12b4db6 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -169,6 +169,8 @@ in demoit = callPackage ../servers/demoit { }; + deviceTree = callPackage ../os-specific/linux/device-tree.nix {}; + diffPlugins = (callPackage ../build-support/plugins.nix {}).diffPlugins; dieHook = makeSetupHook {} ../build-support/setup-hooks/die.sh;