at 22.05-pre 12 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 7 inherit (config.boot) kernelPatches; 8 inherit (config.boot.kernel) features randstructSeed; 9 inherit (config.boot.kernelPackages) kernel; 10 11 kernelModulesConf = pkgs.writeText "nixos.conf" 12 '' 13 ${concatStringsSep "\n" config.boot.kernelModules} 14 ''; 15 16in 17 18{ 19 20 ###### interface 21 22 options = { 23 24 boot.kernel.features = mkOption { 25 default = {}; 26 example = literalExpression "{ debug = true; }"; 27 internal = true; 28 description = '' 29 This option allows to enable or disable certain kernel features. 30 It's not API, because it's about kernel feature sets, that 31 make sense for specific use cases. Mostly along with programs, 32 which would have separate nixos options. 33 `grep features pkgs/os-specific/linux/kernel/common-config.nix` 34 ''; 35 }; 36 37 boot.kernelPackages = mkOption { 38 default = pkgs.linuxPackages; 39 type = types.unspecified // { merge = mergeEqualOption; }; 40 apply = kernelPackages: kernelPackages.extend (self: super: { 41 kernel = super.kernel.override (originalArgs: { 42 inherit randstructSeed; 43 kernelPatches = (originalArgs.kernelPatches or []) ++ kernelPatches; 44 features = lib.recursiveUpdate super.kernel.features features; 45 }); 46 }); 47 # We don't want to evaluate all of linuxPackages for the manual 48 # - some of it might not even evaluate correctly. 49 defaultText = literalExpression "pkgs.linuxPackages"; 50 example = literalExpression "pkgs.linuxKernel.packages.linux_5_10"; 51 description = '' 52 This option allows you to override the Linux kernel used by 53 NixOS. Since things like external kernel module packages are 54 tied to the kernel you're using, it also overrides those. 55 This option is a function that takes Nixpkgs as an argument 56 (as a convenience), and returns an attribute set containing at 57 the very least an attribute <varname>kernel</varname>. 58 Additional attributes may be needed depending on your 59 configuration. For instance, if you use the NVIDIA X driver, 60 then it also needs to contain an attribute 61 <varname>nvidia_x11</varname>. 62 ''; 63 }; 64 65 boot.kernelPatches = mkOption { 66 type = types.listOf types.attrs; 67 default = []; 68 example = literalExpression "[ pkgs.kernelPatches.ubuntu_fan_4_4 ]"; 69 description = "A list of additional patches to apply to the kernel."; 70 }; 71 72 boot.kernel.randstructSeed = mkOption { 73 type = types.str; 74 default = ""; 75 example = "my secret seed"; 76 description = '' 77 Provides a custom seed for the <varname>RANDSTRUCT</varname> security 78 option of the Linux kernel. Note that <varname>RANDSTRUCT</varname> is 79 only enabled in NixOS hardened kernels. Using a custom seed requires 80 building the kernel and dependent packages locally, since this 81 customization happens at build time. 82 ''; 83 }; 84 85 boot.kernelParams = mkOption { 86 type = types.listOf (types.strMatching ''([^"[:space:]]|"[^"]*")+'' // { 87 name = "kernelParam"; 88 description = "string, with spaces inside double quotes"; 89 }); 90 default = [ ]; 91 description = "Parameters added to the kernel command line."; 92 }; 93 94 boot.consoleLogLevel = mkOption { 95 type = types.int; 96 default = 4; 97 description = '' 98 The kernel console <literal>loglevel</literal>. All Kernel Messages with a log level smaller 99 than this setting will be printed to the console. 100 ''; 101 }; 102 103 boot.vesa = mkOption { 104 type = types.bool; 105 default = false; 106 description = '' 107 (Deprecated) This option, if set, activates the VESA 800x600 video 108 mode on boot and disables kernel modesetting. It is equivalent to 109 specifying <literal>[ "vga=0x317" "nomodeset" ]</literal> in the 110 <option>boot.kernelParams</option> option. This option is 111 deprecated as of 2020: Xorg now works better with modesetting, and 112 you might want a different VESA vga setting, anyway. 113 ''; 114 }; 115 116 boot.extraModulePackages = mkOption { 117 type = types.listOf types.package; 118 default = []; 119 example = literalExpression "[ config.boot.kernelPackages.nvidia_x11 ]"; 120 description = "A list of additional packages supplying kernel modules."; 121 }; 122 123 boot.kernelModules = mkOption { 124 type = types.listOf types.str; 125 default = []; 126 description = '' 127 The set of kernel modules to be loaded in the second stage of 128 the boot process. Note that modules that are needed to 129 mount the root file system should be added to 130 <option>boot.initrd.availableKernelModules</option> or 131 <option>boot.initrd.kernelModules</option>. 132 ''; 133 }; 134 135 boot.initrd.availableKernelModules = mkOption { 136 type = types.listOf types.str; 137 default = []; 138 example = [ "sata_nv" "ext3" ]; 139 description = '' 140 The set of kernel modules in the initial ramdisk used during the 141 boot process. This set must include all modules necessary for 142 mounting the root device. That is, it should include modules 143 for the physical device (e.g., SCSI drivers) and for the file 144 system (e.g., ext3). The set specified here is automatically 145 closed under the module dependency relation, i.e., all 146 dependencies of the modules list here are included 147 automatically. The modules listed here are available in the 148 initrd, but are only loaded on demand (e.g., the ext3 module is 149 loaded automatically when an ext3 filesystem is mounted, and 150 modules for PCI devices are loaded when they match the PCI ID 151 of a device in your system). To force a module to be loaded, 152 include it in <option>boot.initrd.kernelModules</option>. 153 ''; 154 }; 155 156 boot.initrd.kernelModules = mkOption { 157 type = types.listOf types.str; 158 default = []; 159 description = "List of modules that are always loaded by the initrd."; 160 }; 161 162 boot.initrd.includeDefaultModules = mkOption { 163 type = types.bool; 164 default = true; 165 description = '' 166 This option, if set, adds a collection of default kernel modules 167 to <option>boot.initrd.availableKernelModules</option> and 168 <option>boot.initrd.kernelModules</option>. 169 ''; 170 }; 171 172 system.modulesTree = mkOption { 173 type = types.listOf types.path; 174 internal = true; 175 default = []; 176 description = '' 177 Tree of kernel modules. This includes the kernel, plus modules 178 built outside of the kernel. Combine these into a single tree of 179 symlinks because modprobe only supports one directory. 180 ''; 181 # Convert the list of path to only one path. 182 apply = pkgs.aggregateModules; 183 }; 184 185 system.requiredKernelConfig = mkOption { 186 default = []; 187 example = literalExpression '' 188 with config.lib.kernelConfig; [ 189 (isYes "MODULES") 190 (isEnabled "FB_CON_DECOR") 191 (isEnabled "BLK_DEV_INITRD") 192 ] 193 ''; 194 internal = true; 195 type = types.listOf types.attrs; 196 description = '' 197 This option allows modules to specify the kernel config options that 198 must be set (or unset) for the module to work. Please use the 199 lib.kernelConfig functions to build list elements. 200 ''; 201 }; 202 203 }; 204 205 206 ###### implementation 207 208 config = mkMerge 209 [ (mkIf config.boot.initrd.enable { 210 boot.initrd.availableKernelModules = 211 optionals config.boot.initrd.includeDefaultModules ([ 212 # Note: most of these (especially the SATA/PATA modules) 213 # shouldn't be included by default since nixos-generate-config 214 # detects them, but I'm keeping them for now for backwards 215 # compatibility. 216 217 # Some SATA/PATA stuff. 218 "ahci" 219 "sata_nv" 220 "sata_via" 221 "sata_sis" 222 "sata_uli" 223 "ata_piix" 224 "pata_marvell" 225 226 # Standard SCSI stuff. 227 "sd_mod" 228 "sr_mod" 229 230 # SD cards and internal eMMC drives. 231 "mmc_block" 232 233 # Support USB keyboards, in case the boot fails and we only have 234 # a USB keyboard, or for LUKS passphrase prompt. 235 "uhci_hcd" 236 "ehci_hcd" 237 "ehci_pci" 238 "ohci_hcd" 239 "ohci_pci" 240 "xhci_hcd" 241 "xhci_pci" 242 "usbhid" 243 "hid_generic" "hid_lenovo" "hid_apple" "hid_roccat" 244 "hid_logitech_hidpp" "hid_logitech_dj" "hid_microsoft" 245 246 ] ++ optionals pkgs.stdenv.hostPlatform.isx86 [ 247 # Misc. x86 keyboard stuff. 248 "pcips2" "atkbd" "i8042" 249 250 # x86 RTC needed by the stage 2 init script. 251 "rtc_cmos" 252 ]); 253 254 boot.initrd.kernelModules = 255 optionals config.boot.initrd.includeDefaultModules [ 256 # For LVM. 257 "dm_mod" 258 ]; 259 }) 260 261 (mkIf (!config.boot.isContainer) { 262 system.build = { inherit kernel; }; 263 264 system.modulesTree = [ kernel ] ++ config.boot.extraModulePackages; 265 266 # Implement consoleLogLevel both in early boot and using sysctl 267 # (so you don't need to reboot to have changes take effect). 268 boot.kernelParams = 269 [ "loglevel=${toString config.boot.consoleLogLevel}" ] ++ 270 optionals config.boot.vesa [ "vga=0x317" "nomodeset" ]; 271 272 boot.kernel.sysctl."kernel.printk" = mkDefault config.boot.consoleLogLevel; 273 274 boot.kernelModules = [ "loop" "atkbd" ]; 275 276 # The Linux kernel >= 2.6.27 provides firmware. 277 hardware.firmware = [ kernel ]; 278 279 # Create /etc/modules-load.d/nixos.conf, which is read by 280 # systemd-modules-load.service to load required kernel modules. 281 environment.etc = 282 { "modules-load.d/nixos.conf".source = kernelModulesConf; 283 }; 284 285 systemd.services.systemd-modules-load = 286 { wantedBy = [ "multi-user.target" ]; 287 restartTriggers = [ kernelModulesConf ]; 288 serviceConfig = 289 { # Ignore failed module loads. Typically some of the 290 # modules in ‘boot.kernelModules’ are "nice to have but 291 # not required" (e.g. acpi-cpufreq), so we don't want to 292 # barf on those. 293 SuccessExitStatus = "0 1"; 294 }; 295 }; 296 297 lib.kernelConfig = { 298 isYes = option: { 299 assertion = config: config.isYes option; 300 message = "CONFIG_${option} is not yes!"; 301 configLine = "CONFIG_${option}=y"; 302 }; 303 304 isNo = option: { 305 assertion = config: config.isNo option; 306 message = "CONFIG_${option} is not no!"; 307 configLine = "CONFIG_${option}=n"; 308 }; 309 310 isModule = option: { 311 assertion = config: config.isModule option; 312 message = "CONFIG_${option} is not built as a module!"; 313 configLine = "CONFIG_${option}=m"; 314 }; 315 316 ### Usually you will just want to use these two 317 # True if yes or module 318 isEnabled = option: { 319 assertion = config: config.isEnabled option; 320 message = "CONFIG_${option} is not enabled!"; 321 configLine = "CONFIG_${option}=y"; 322 }; 323 324 # True if no or omitted 325 isDisabled = option: { 326 assertion = config: config.isDisabled option; 327 message = "CONFIG_${option} is not disabled!"; 328 configLine = "CONFIG_${option}=n"; 329 }; 330 }; 331 332 # The config options that all modules can depend upon 333 system.requiredKernelConfig = with config.lib.kernelConfig; 334 [ 335 # !!! Should this really be needed? 336 (isYes "MODULES") 337 (isYes "BINFMT_ELF") 338 ] ++ (optional (randstructSeed != "") (isYes "GCC_PLUGIN_RANDSTRUCT")); 339 340 # nixpkgs kernels are assumed to have all required features 341 assertions = if config.boot.kernelPackages.kernel ? features then [] else 342 let cfg = config.boot.kernelPackages.kernel.config; in map (attrs: 343 { assertion = attrs.assertion cfg; inherit (attrs) message; } 344 ) config.system.requiredKernelConfig; 345 346 }) 347 348 ]; 349 350}