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