at 24.11-pre 6.9 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 filter = mkOption { 18 type = types.nullOr types.str; 19 default = null; 20 example = "*rpi*.dtb"; 21 description = '' 22 Only apply to .dtb files matching glob expression. 23 ''; 24 }; 25 26 dtsFile = mkOption { 27 type = types.nullOr types.path; 28 description = '' 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 = '' 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 = '' 62 Path to .dtbo compiled overlay file. 63 ''; 64 }; 65 }; 66 }; 67 68 filterDTBs = src: if cfg.filter == null 69 then src 70 else 71 pkgs.runCommand "dtbs-filtered" {} '' 72 mkdir -p $out 73 cd ${src} 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.dtbSource; 79 80 # Fill in `dtboFile` for each overlay if not set already. 81 # Existence of one of these is guarded by assertion below 82 withDTBOs = xs: flip map xs (o: o // { dtboFile = 83 let 84 includePaths = ["${getDev cfg.kernelPackage}/lib/modules/${cfg.kernelPackage.modDirVersion}/source/scripts/dtc/include-prefixes"] ++ cfg.dtboBuildExtraIncludePaths; 85 extraPreprocessorFlags = cfg.dtboBuildExtraPreprocessorFlags; 86 in 87 if o.dtboFile == null then 88 let 89 dtsFile = if o.dtsFile == null then (pkgs.writeText "dts" o.dtsText) else o.dtsFile; 90 in 91 pkgs.deviceTree.compileDTS { 92 name = "${o.name}-dtbo"; 93 inherit includePaths extraPreprocessorFlags dtsFile; 94 } 95 else o.dtboFile; } ); 96 97in 98{ 99 imports = [ 100 (mkRemovedOptionModule [ "hardware" "deviceTree" "base" ] "Use hardware.deviceTree.kernelPackage instead") 101 ]; 102 103 options = { 104 hardware.deviceTree = { 105 enable = mkOption { 106 default = pkgs.stdenv.hostPlatform.linux-kernel.DTB or false; 107 type = types.bool; 108 description = '' 109 Build device tree files. These are used to describe the 110 non-discoverable hardware of a system. 111 ''; 112 }; 113 114 kernelPackage = mkOption { 115 default = config.boot.kernelPackages.kernel; 116 defaultText = literalExpression "config.boot.kernelPackages.kernel"; 117 example = literalExpression "pkgs.linux_latest"; 118 type = types.path; 119 description = '' 120 Kernel package where device tree include directory is from. Also used as default source of dtb package to apply overlays to 121 ''; 122 }; 123 124 dtboBuildExtraPreprocessorFlags = mkOption { 125 default = []; 126 example = literalExpression "[ \"-DMY_DTB_DEFINE\" ]"; 127 type = types.listOf types.str; 128 description = '' 129 Additional flags to pass to the preprocessor during dtbo compilations 130 ''; 131 }; 132 133 dtboBuildExtraIncludePaths = mkOption { 134 default = []; 135 example = literalExpression '' 136 [ 137 ./my_custom_include_dir_1 138 ./custom_include_dir_2 139 ] 140 ''; 141 type = types.listOf types.path; 142 description = '' 143 Additional include paths that will be passed to the preprocessor when creating the final .dts to compile into .dtbo 144 ''; 145 }; 146 147 dtbSource = mkOption { 148 default = "${cfg.kernelPackage}/dtbs"; 149 defaultText = literalExpression "\${cfg.kernelPackage}/dtbs"; 150 type = types.path; 151 description = '' 152 Path to dtb directory that overlays and other processing will be applied to. Uses 153 device trees bundled with the Linux kernel by default. 154 ''; 155 }; 156 157 name = mkOption { 158 default = null; 159 example = "some-dtb.dtb"; 160 type = types.nullOr types.str; 161 description = '' 162 The name of an explicit dtb to be loaded, relative to the dtb base. 163 Useful in extlinux scenarios if the bootloader doesn't pick the 164 right .dtb file from FDTDIR. 165 ''; 166 }; 167 168 filter = mkOption { 169 type = types.nullOr types.str; 170 default = null; 171 example = "*rpi*.dtb"; 172 description = '' 173 Only include .dtb files matching glob expression. 174 ''; 175 }; 176 177 overlays = mkOption { 178 default = []; 179 example = literalExpression '' 180 [ 181 { name = "pps"; dtsFile = ./dts/pps.dts; } 182 { name = "spi"; 183 dtsText = "..."; 184 } 185 { name = "precompiled"; dtboFile = ./dtbos/example.dtbo; } 186 ] 187 ''; 188 type = types.listOf (types.coercedTo types.path (path: { 189 name = baseNameOf path; 190 filter = null; 191 dtboFile = path; 192 }) overlayType); 193 description = '' 194 List of overlays to apply to base device-tree (.dtb) files. 195 ''; 196 }; 197 198 package = mkOption { 199 default = null; 200 type = types.nullOr types.path; 201 internal = true; 202 description = '' 203 A path containing the result of applying `overlays` to `kernelPackage`. 204 ''; 205 }; 206 }; 207 }; 208 209 config = mkIf (cfg.enable) { 210 211 assertions = let 212 invalidOverlay = o: (o.dtsFile == null) && (o.dtsText == null) && (o.dtboFile == null); 213 in lib.singleton { 214 assertion = lib.all (o: !invalidOverlay o) cfg.overlays; 215 message = '' 216 deviceTree overlay needs one of dtsFile, dtsText or dtboFile set. 217 Offending overlay(s): 218 ${toString (map (o: o.name) (builtins.filter invalidOverlay cfg.overlays))} 219 ''; 220 }; 221 222 hardware.deviceTree.package = if (cfg.overlays != []) 223 then pkgs.deviceTree.applyOverlays filteredDTBs (withDTBOs cfg.overlays) 224 else filteredDTBs; 225 }; 226}