at 22.05-pre 6.4 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 cfg = config.hardware.deviceTree; 7 8 overlayType = types.submodule { 9 options = { 10 name = mkOption { 11 type = types.str; 12 description = '' 13 Name of this overlay 14 ''; 15 }; 16 17 dtsFile = mkOption { 18 type = types.nullOr types.path; 19 description = '' 20 Path to .dts overlay file, overlay is applied to 21 each .dtb file matching "compatible" of the overlay. 22 ''; 23 default = null; 24 example = literalExpression "./dts/overlays.dts"; 25 }; 26 27 dtsText = mkOption { 28 type = types.nullOr types.str; 29 default = null; 30 description = '' 31 Literal DTS contents, overlay is applied to 32 each .dtb file matching "compatible" of the overlay. 33 ''; 34 example = '' 35 /dts-v1/; 36 /plugin/; 37 / { 38 compatible = "raspberrypi"; 39 fragment@0 { 40 target-path = "/soc"; 41 __overlay__ { 42 pps { 43 compatible = "pps-gpio"; 44 status = "okay"; 45 }; 46 }; 47 }; 48 }; 49 ''; 50 }; 51 52 dtboFile = mkOption { 53 type = types.nullOr types.path; 54 default = null; 55 description = '' 56 Path to .dtbo compiled overlay file. 57 ''; 58 }; 59 }; 60 }; 61 62 # this requires kernel package 63 dtbsWithSymbols = pkgs.stdenv.mkDerivation { 64 name = "dtbs-with-symbols"; 65 inherit (cfg.kernelPackage) src nativeBuildInputs depsBuildBuild; 66 patches = map (patch: patch.patch) cfg.kernelPackage.kernelPatches; 67 buildPhase = '' 68 patchShebangs scripts/* 69 substituteInPlace scripts/Makefile.lib \ 70 --replace 'DTC_FLAGS += $(DTC_FLAGS_$(basetarget))' 'DTC_FLAGS += $(DTC_FLAGS_$(basetarget)) -@' 71 make ${pkgs.stdenv.hostPlatform.linux-kernel.baseConfig} ARCH="${pkgs.stdenv.hostPlatform.linuxArch}" 72 make dtbs ARCH="${pkgs.stdenv.hostPlatform.linuxArch}" 73 ''; 74 installPhase = '' 75 make dtbs_install INSTALL_DTBS_PATH=$out/dtbs ARCH="${pkgs.stdenv.hostPlatform.linuxArch}" 76 ''; 77 }; 78 79 filterDTBs = src: if isNull cfg.filter 80 then "${src}/dtbs" 81 else 82 pkgs.runCommand "dtbs-filtered" {} '' 83 mkdir -p $out 84 cd ${src}/dtbs 85 find . -type f -name '${cfg.filter}' -print0 \ 86 | xargs -0 cp -v --no-preserve=mode --target-directory $out --parents 87 ''; 88 89 # Compile single Device Tree overlay source 90 # file (.dts) into its compiled variant (.dtbo) 91 compileDTS = name: f: pkgs.callPackage({ dtc }: pkgs.stdenv.mkDerivation { 92 name = "${name}-dtbo"; 93 94 nativeBuildInputs = [ dtc ]; 95 96 buildCommand = '' 97 dtc -I dts ${f} -O dtb -@ -o $out 98 ''; 99 }) {}; 100 101 # Fill in `dtboFile` for each overlay if not set already. 102 # Existence of one of these is guarded by assertion below 103 withDTBOs = xs: flip map xs (o: o // { dtboFile = 104 if isNull o.dtboFile then 105 if !isNull o.dtsFile then compileDTS o.name o.dtsFile 106 else compileDTS o.name (pkgs.writeText "dts" o.dtsText) 107 else o.dtboFile; } ); 108 109in 110{ 111 imports = [ 112 (mkRemovedOptionModule [ "hardware" "deviceTree" "base" ] "Use hardware.deviceTree.kernelPackage instead") 113 ]; 114 115 options = { 116 hardware.deviceTree = { 117 enable = mkOption { 118 default = pkgs.stdenv.hostPlatform.linux-kernel.DTB or false; 119 type = types.bool; 120 description = '' 121 Build device tree files. These are used to describe the 122 non-discoverable hardware of a system. 123 ''; 124 }; 125 126 kernelPackage = mkOption { 127 default = config.boot.kernelPackages.kernel; 128 defaultText = literalExpression "config.boot.kernelPackages.kernel"; 129 example = literalExpression "pkgs.linux_latest"; 130 type = types.path; 131 description = '' 132 Kernel package containing the base device-tree (.dtb) to boot. Uses 133 device trees bundled with the Linux kernel by default. 134 ''; 135 }; 136 137 name = mkOption { 138 default = null; 139 example = "some-dtb.dtb"; 140 type = types.nullOr types.str; 141 description = '' 142 The name of an explicit dtb to be loaded, relative to the dtb base. 143 Useful in extlinux scenarios if the bootloader doesn't pick the 144 right .dtb file from FDTDIR. 145 ''; 146 }; 147 148 filter = mkOption { 149 type = types.nullOr types.str; 150 default = null; 151 example = "*rpi*.dtb"; 152 description = '' 153 Only include .dtb files matching glob expression. 154 ''; 155 }; 156 157 overlays = mkOption { 158 default = []; 159 example = literalExpression '' 160 [ 161 { name = "pps"; dtsFile = ./dts/pps.dts; } 162 { name = "spi"; 163 dtsText = "..."; 164 } 165 { name = "precompiled"; dtboFile = ./dtbos/example.dtbo; } 166 ] 167 ''; 168 type = types.listOf (types.coercedTo types.path (path: { 169 name = baseNameOf path; 170 dtboFile = path; 171 }) overlayType); 172 description = '' 173 List of overlays to apply to base device-tree (.dtb) files. 174 ''; 175 }; 176 177 package = mkOption { 178 default = null; 179 type = types.nullOr types.path; 180 internal = true; 181 description = '' 182 A path containing the result of applying `overlays` to `kernelPackage`. 183 ''; 184 }; 185 }; 186 }; 187 188 config = mkIf (cfg.enable) { 189 190 assertions = let 191 invalidOverlay = o: isNull o.dtsFile && isNull o.dtsText && isNull o.dtboFile; 192 in lib.singleton { 193 assertion = lib.all (o: !invalidOverlay o) cfg.overlays; 194 message = '' 195 deviceTree overlay needs one of dtsFile, dtsText or dtboFile set. 196 Offending overlay(s): 197 ${toString (map (o: o.name) (builtins.filter invalidOverlay cfg.overlays))} 198 ''; 199 }; 200 201 hardware.deviceTree.package = if (cfg.overlays != []) 202 then pkgs.deviceTree.applyOverlays (filterDTBs dtbsWithSymbols) (withDTBOs cfg.overlays) 203 else (filterDTBs cfg.kernelPackage); 204 }; 205}