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