at 23.05-pre 22 kB view raw
1#! @perl@ 2 3use strict; 4use Cwd 'abs_path'; 5use File::Spec; 6use File::Path; 7use File::Basename; 8use File::Slurp; 9use File::stat; 10 11umask(0022); 12 13sub uniq { 14 my %seen; 15 my @res = (); 16 foreach my $s (@_) { 17 if (!defined $seen{$s}) { 18 $seen{$s} = 1; 19 push @res, $s; 20 } 21 } 22 return @res; 23} 24 25sub runCommand { 26 my ($cmd) = @_; 27 open FILE, "$cmd 2>&1 |" or die "Failed to execute: $cmd\n"; 28 my @ret = <FILE>; 29 close FILE; 30 return ($?, @ret); 31} 32 33# Process the command line. 34my $outDir = "/etc/nixos"; 35my $rootDir = ""; # = / 36my $force = 0; 37my $noFilesystems = 0; 38my $showHardwareConfig = 0; 39 40for (my $n = 0; $n < scalar @ARGV; $n++) { 41 my $arg = $ARGV[$n]; 42 if ($arg eq "--help") { 43 exec "man nixos-generate-config" or die; 44 } 45 elsif ($arg eq "--dir") { 46 $n++; 47 $outDir = $ARGV[$n]; 48 die "$0: ‘--dir’ requires an argument\n" unless defined $outDir; 49 } 50 elsif ($arg eq "--root") { 51 $n++; 52 $rootDir = $ARGV[$n]; 53 die "$0: ‘--root’ requires an argument\n" unless defined $rootDir; 54 die "$0: no need to specify `/` with `--root`, it is the default\n" if $rootDir eq "/"; 55 $rootDir =~ s/\/*$//; # remove trailing slashes 56 $rootDir = File::Spec->rel2abs($rootDir); # resolve absolute path 57 } 58 elsif ($arg eq "--force") { 59 $force = 1; 60 } 61 elsif ($arg eq "--no-filesystems") { 62 $noFilesystems = 1; 63 } 64 elsif ($arg eq "--show-hardware-config") { 65 $showHardwareConfig = 1; 66 } 67 else { 68 die "$0: unrecognized argument ‘$arg’\n"; 69 } 70} 71 72 73my @attrs = (); 74my @kernelModules = (); 75my @initrdKernelModules = (); 76my @initrdAvailableKernelModules = (); 77my @modulePackages = (); 78my @imports; 79 80 81sub debug { 82 return unless defined $ENV{"DEBUG"}; 83 print STDERR @_; 84} 85 86 87# nixpkgs.system 88my ($status, @systemLines) = runCommand("@nixInstantiate@ --impure --eval --expr builtins.currentSystem"); 89if ($status != 0 || join("", @systemLines) =~ /error/) { 90 die "Failed to retrieve current system type from nix.\n"; 91} 92chomp(my $system = @systemLines[0]); 93push @attrs, "nixpkgs.hostPlatform = lib.mkDefault $system;"; 94 95 96my $cpuinfo = read_file "/proc/cpuinfo"; 97 98 99sub hasCPUFeature { 100 my $feature = shift; 101 return $cpuinfo =~ /^flags\s*:.* $feature( |$)/m; 102} 103 104 105sub cpuManufacturer { 106 my $id = shift; 107 return $cpuinfo =~ /^vendor_id\s*:.* $id$/m; 108} 109 110 111# Determine CPU governor to use 112if (-e "/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors") { 113 my $governors = read_file("/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors"); 114 # ondemand governor is not available on sandy bridge or later Intel CPUs 115 my @desired_governors = ("ondemand", "powersave"); 116 my $e; 117 118 foreach $e (@desired_governors) { 119 if (index($governors, $e) != -1) { 120 last if (push @attrs, "powerManagement.cpuFreqGovernor = lib.mkDefault \"$e\";"); 121 } 122 } 123} 124 125 126# Virtualization support? 127push @kernelModules, "kvm-intel" if hasCPUFeature "vmx"; 128push @kernelModules, "kvm-amd" if hasCPUFeature "svm"; 129 130push @attrs, "hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;" if cpuManufacturer "AuthenticAMD"; 131push @attrs, "hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;" if cpuManufacturer "GenuineIntel"; 132 133 134# Look at the PCI devices and add necessary modules. Note that most 135# modules are auto-detected so we don't need to list them here. 136# However, some are needed in the initrd to boot the system. 137 138my $videoDriver; 139 140sub pciCheck { 141 my $path = shift; 142 my $vendor = read_file "$path/vendor"; chomp $vendor; 143 my $device = read_file "$path/device"; chomp $device; 144 my $class = read_file "$path/class"; chomp $class; 145 146 my $module; 147 if (-e "$path/driver/module") { 148 $module = basename `readlink -f $path/driver/module`; 149 chomp $module; 150 } 151 152 debug "$path: $vendor $device $class"; 153 debug " $module" if defined $module; 154 debug "\n"; 155 156 if (defined $module) { 157 # See the bottom of http://pciids.sourceforge.net/pci.ids for 158 # device classes. 159 if (# Mass-storage controller. Definitely important. 160 $class =~ /^0x01/ || 161 162 # Firewire controller. A disk might be attached. 163 $class =~ /^0x0c00/ || 164 165 # USB controller. Needed if we want to use the 166 # keyboard when things go wrong in the initrd. 167 $class =~ /^0x0c03/ 168 ) 169 { 170 push @initrdAvailableKernelModules, $module; 171 } 172 } 173 174 # broadcom STA driver (wl.ko) 175 # list taken from http://www.broadcom.com/docs/linux_sta/README.txt 176 if ($vendor eq "0x14e4" && 177 ($device eq "0x4311" || $device eq "0x4312" || $device eq "0x4313" || 178 $device eq "0x4315" || $device eq "0x4327" || $device eq "0x4328" || 179 $device eq "0x4329" || $device eq "0x432a" || $device eq "0x432b" || 180 $device eq "0x432c" || $device eq "0x432d" || $device eq "0x4353" || 181 $device eq "0x4357" || $device eq "0x4358" || $device eq "0x4359" || 182 $device eq "0x4331" || $device eq "0x43a0" || $device eq "0x43b1" 183 ) ) 184 { 185 push @modulePackages, "config.boot.kernelPackages.broadcom_sta"; 186 push @kernelModules, "wl"; 187 } 188 189 # broadcom FullMac driver 190 # list taken from 191 # https://wireless.wiki.kernel.org/en/users/Drivers/brcm80211#brcmfmac 192 if ($vendor eq "0x14e4" && 193 ($device eq "0x43a3" || $device eq "0x43df" || $device eq "0x43ec" || 194 $device eq "0x43d3" || $device eq "0x43d9" || $device eq "0x43e9" || 195 $device eq "0x43ba" || $device eq "0x43bb" || $device eq "0x43bc" || 196 $device eq "0xaa52" || $device eq "0x43ca" || $device eq "0x43cb" || 197 $device eq "0x43cc" || $device eq "0x43c3" || $device eq "0x43c4" || 198 $device eq "0x43c5" 199 ) ) 200 { 201 # we need e.g. brcmfmac43602-pcie.bin 202 push @imports, "(modulesPath + \"/hardware/network/broadcom-43xx.nix\")"; 203 } 204 205 # In case this is a virtio scsi device, we need to explicitly make this available. 206 if ($vendor eq "0x1af4" && $device eq "0x1004") { 207 push @initrdAvailableKernelModules, "virtio_scsi"; 208 } 209 210 # Can't rely on $module here, since the module may not be loaded 211 # due to missing firmware. Ideally we would check modules.pcimap 212 # here. 213 push @attrs, "networking.enableIntel2200BGFirmware = true;" if 214 $vendor eq "0x8086" && 215 ($device eq "0x1043" || $device eq "0x104f" || $device eq "0x4220" || 216 $device eq "0x4221" || $device eq "0x4223" || $device eq "0x4224"); 217 218 push @attrs, "networking.enableIntel3945ABGFirmware = true;" if 219 $vendor eq "0x8086" && 220 ($device eq "0x4229" || $device eq "0x4230" || 221 $device eq "0x4222" || $device eq "0x4227"); 222 223 # Assume that all NVIDIA cards are supported by the NVIDIA driver. 224 # There may be exceptions (e.g. old cards). 225 # FIXME: do we want to enable an unfree driver here? 226 #$videoDriver = "nvidia" if $vendor eq "0x10de" && $class =~ /^0x03/; 227} 228 229foreach my $path (glob "/sys/bus/pci/devices/*") { 230 pciCheck $path; 231} 232 233# Idem for USB devices. 234 235sub usbCheck { 236 my $path = shift; 237 my $class = read_file "$path/bInterfaceClass"; chomp $class; 238 my $subclass = read_file "$path/bInterfaceSubClass"; chomp $subclass; 239 my $protocol = read_file "$path/bInterfaceProtocol"; chomp $protocol; 240 241 my $module; 242 if (-e "$path/driver/module") { 243 $module = basename `readlink -f $path/driver/module`; 244 chomp $module; 245 } 246 247 debug "$path: $class $subclass $protocol"; 248 debug " $module" if defined $module; 249 debug "\n"; 250 251 if (defined $module) { 252 if (# Mass-storage controller. Definitely important. 253 $class eq "08" || 254 255 # Keyboard. Needed if we want to use the 256 # keyboard when things go wrong in the initrd. 257 ($class eq "03" && $protocol eq "01") 258 ) 259 { 260 push @initrdAvailableKernelModules, $module; 261 } 262 } 263} 264 265foreach my $path (glob "/sys/bus/usb/devices/*") { 266 if (-e "$path/bInterfaceClass") { 267 usbCheck $path; 268 } 269} 270 271 272# Add the modules for all block and MMC devices. 273foreach my $path (glob "/sys/class/{block,mmc_host}/*") { 274 my $module; 275 if (-e "$path/device/driver/module") { 276 $module = basename `readlink -f $path/device/driver/module`; 277 chomp $module; 278 push @initrdAvailableKernelModules, $module; 279 } 280} 281 282# Add bcache module, if needed. 283my @bcacheDevices = glob("/dev/bcache*"); 284if (scalar @bcacheDevices > 0) { 285 push @initrdAvailableKernelModules, "bcache"; 286} 287 288# Prevent unbootable systems if LVM snapshots are present at boot time. 289if (`lsblk -o TYPE` =~ "lvm") { 290 push @initrdKernelModules, "dm-snapshot"; 291} 292 293my $virt = `@detectvirt@`; 294chomp $virt; 295 296 297# Check if we're a VirtualBox guest. If so, enable the guest 298# additions. 299if ($virt eq "oracle") { 300 push @attrs, "virtualisation.virtualbox.guest.enable = true;" 301} 302 303# Check if we're a Parallels guest. If so, enable the guest additions. 304# It is blocked by https://github.com/systemd/systemd/pull/23859 305if ($virt eq "parallels") { 306 push @attrs, "hardware.parallels.enable = true;"; 307 push @attrs, "nixpkgs.config.allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [ \"prl-tools\" ];"; 308} 309 310# Likewise for QEMU. 311if ($virt eq "qemu" || $virt eq "kvm" || $virt eq "bochs") { 312 push @imports, "(modulesPath + \"/profiles/qemu-guest.nix\")"; 313} 314 315# Also for Hyper-V. 316if ($virt eq "microsoft") { 317 push @attrs, "virtualisation.hypervGuest.enable = true;" 318} 319 320 321# Pull in NixOS configuration for containers. 322if ($virt eq "systemd-nspawn") { 323 push @attrs, "boot.isContainer = true;"; 324} 325 326 327# Provide firmware for devices that are not detected by this script, 328# unless we're in a VM/container. 329push @imports, "(modulesPath + \"/installer/scan/not-detected.nix\")" 330 if $virt eq "none"; 331 332 333# For a device name like /dev/sda1, find a more stable path like 334# /dev/disk/by-uuid/X or /dev/disk/by-label/Y. 335sub findStableDevPath { 336 my ($dev) = @_; 337 return $dev if substr($dev, 0, 1) ne "/"; 338 return $dev unless -e $dev; 339 340 my $st = stat($dev) or return $dev; 341 342 foreach my $dev2 (glob("/dev/disk/by-uuid/*"), glob("/dev/mapper/*"), glob("/dev/disk/by-label/*")) { 343 my $st2 = stat($dev2) or next; 344 return $dev2 if $st->rdev == $st2->rdev; 345 } 346 347 return $dev; 348} 349 350push @attrs, "services.xserver.videoDrivers = [ \"$videoDriver\" ];" if $videoDriver; 351 352# Generate the swapDevices option from the currently activated swap 353# devices. 354my @swaps = read_file("/proc/swaps", err_mode => 'carp'); 355my @swapDevices; 356if (@swaps) { 357 shift @swaps; 358 foreach my $swap (@swaps) { 359 my @fields = split ' ', $swap; 360 my $swapFilename = $fields[0]; 361 my $swapType = $fields[1]; 362 next unless -e $swapFilename; 363 my $dev = findStableDevPath $swapFilename; 364 if ($swapType =~ "partition") { 365 # zram devices are more likely created by configuration.nix, so 366 # ignore them here 367 next if ($swapFilename =~ /^\/dev\/zram/); 368 push @swapDevices, "{ device = \"$dev\"; }"; 369 } elsif ($swapType =~ "file") { 370 # swap *files* are more likely specified in configuration.nix, so 371 # ignore them here. 372 } else { 373 die "Unsupported swap type: $swapType\n"; 374 } 375 } 376} 377 378 379# Generate the fileSystems option from the currently mounted 380# filesystems. 381sub in { 382 my ($d1, $d2) = @_; 383 return $d1 eq $d2 || substr($d1, 0, length($d2) + 1) eq "$d2/"; 384} 385 386my $fileSystems; 387my %fsByDev; 388foreach my $fs (read_file("/proc/self/mountinfo")) { 389 chomp $fs; 390 my @fields = split / /, $fs; 391 my $mountPoint = $fields[4]; 392 $mountPoint =~ s/\\040/ /g; # account for mount points with spaces in the name (\040 is the escape character) 393 $mountPoint =~ s/\\011/\t/g; # account for mount points with tabs in the name (\011 is the escape character) 394 next unless -d $mountPoint; 395 my @mountOptions = split /,/, $fields[5]; 396 397 next if !in($mountPoint, $rootDir); 398 $mountPoint = substr($mountPoint, length($rootDir)); # strip the root directory (e.g. /mnt) 399 $mountPoint = "/" if $mountPoint eq ""; 400 401 # Skip special filesystems. 402 next if in($mountPoint, "/proc") || in($mountPoint, "/dev") || in($mountPoint, "/sys") || in($mountPoint, "/run") || $mountPoint eq "/var/lib/nfs/rpc_pipefs"; 403 404 # Skip the optional fields. 405 my $n = 6; $n++ while $fields[$n] ne "-"; $n++; 406 my $fsType = $fields[$n]; 407 my $device = $fields[$n + 1]; 408 my @superOptions = split /,/, $fields[$n + 2]; 409 $device =~ s/\\040/ /g; # account for devices with spaces in the name (\040 is the escape character) 410 $device =~ s/\\011/\t/g; # account for mount points with tabs in the name (\011 is the escape character) 411 412 # Skip the read-only bind-mount on /nix/store. 413 next if $mountPoint eq "/nix/store" && (grep { $_ eq "rw" } @superOptions) && (grep { $_ eq "ro" } @mountOptions); 414 415 # Maybe this is a bind-mount of a filesystem we saw earlier? 416 if (defined $fsByDev{$fields[2]}) { 417 # Make sure this isn't a btrfs subvolume. 418 my $msg = `@btrfs@ subvol show $rootDir$mountPoint`; 419 if ($? != 0 || $msg =~ /ERROR:/s) { 420 my $path = $fields[3]; $path = "" if $path eq "/"; 421 my $base = $fsByDev{$fields[2]}; 422 $base = "" if $base eq "/"; 423 $fileSystems .= <<EOF; 424 fileSystems.\"$mountPoint\" = 425 { device = \"$base$path\"; 426 fsType = \"none\"; 427 options = \[ \"bind\" \]; 428 }; 429 430EOF 431 next; 432 } 433 } 434 $fsByDev{$fields[2]} = $mountPoint; 435 436 # We don't know how to handle FUSE filesystems. 437 if ($fsType eq "fuseblk" || $fsType eq "fuse") { 438 print STDERR "warning: don't know how to emit ‘fileSystem’ option for FUSE filesystem ‘$mountPoint’\n"; 439 next; 440 } 441 442 # Is this a mount of a loopback device? 443 my @extraOptions; 444 if ($device =~ /\/dev\/loop(\d+)/) { 445 my $loopnr = $1; 446 my $backer = read_file "/sys/block/loop$loopnr/loop/backing_file"; 447 if (defined $backer) { 448 chomp $backer; 449 $device = $backer; 450 push @extraOptions, "loop"; 451 } 452 } 453 454 # Is this a btrfs filesystem? 455 if ($fsType eq "btrfs") { 456 my ($status, @info) = runCommand("@btrfs@ subvol show $rootDir$mountPoint"); 457 if ($status != 0 || join("", @info) =~ /ERROR:/) { 458 die "Failed to retrieve subvolume info for $mountPoint\n"; 459 } 460 my @ids = join("\n", @info) =~ m/^(?!\/\n).*Subvolume ID:[ \t\n]*([0-9]+)/s; 461 if ($#ids > 0) { 462 die "Btrfs subvol name for $mountPoint listed multiple times in mount\n" 463 } elsif ($#ids == 0) { 464 my @paths = join("", @info) =~ m/^([^\n]*)/; 465 if ($#paths > 0) { 466 die "Btrfs returned multiple paths for a single subvolume id, mountpoint $mountPoint\n"; 467 } elsif ($#paths != 0) { 468 die "Btrfs did not return a path for the subvolume at $mountPoint\n"; 469 } 470 push @extraOptions, "subvol=$paths[0]"; 471 } 472 } 473 474 # Don't emit tmpfs entry for /tmp, because it most likely comes from the 475 # boot.tmpOnTmpfs option in configuration.nix (managed declaratively). 476 next if ($mountPoint eq "/tmp" && $fsType eq "tmpfs"); 477 478 # Emit the filesystem. 479 $fileSystems .= <<EOF; 480 fileSystems.\"$mountPoint\" = 481 { device = \"${\(findStableDevPath $device)}\"; 482 fsType = \"$fsType\"; 483EOF 484 485 if (scalar @extraOptions > 0) { 486 $fileSystems .= <<EOF; 487 options = \[ ${\join " ", map { "\"" . $_ . "\"" } uniq(@extraOptions)} \]; 488EOF 489 } 490 491 $fileSystems .= <<EOF; 492 }; 493 494EOF 495 496 # If this filesystem is on a LUKS device, then add a 497 # boot.initrd.luks.devices entry. 498 if (-e $device) { 499 my $deviceName = basename(abs_path($device)); 500 if (-e "/sys/class/block/$deviceName" 501 && read_file("/sys/class/block/$deviceName/dm/uuid", err_mode => 'quiet') =~ /^CRYPT-LUKS/) 502 { 503 my @slaves = glob("/sys/class/block/$deviceName/slaves/*"); 504 if (scalar @slaves == 1) { 505 my $slave = "/dev/" . basename($slaves[0]); 506 if (-e $slave) { 507 my $dmName = read_file("/sys/class/block/$deviceName/dm/name"); 508 chomp $dmName; 509 # Ensure to add an entry only once 510 my $luksDevice = " boot.initrd.luks.devices.\"$dmName\".device"; 511 if ($fileSystems !~ /^\Q$luksDevice\E/m) { 512 $fileSystems .= "$luksDevice = \"${\(findStableDevPath $slave)}\";\n\n"; 513 } 514 } 515 } 516 } 517 } 518} 519 520# For lack of a better way to determine it, guess whether we should use a 521# bigger font for the console from the display mode on the first 522# framebuffer. A way based on the physical size/actual DPI reported by 523# the monitor would be nice, but I don't know how to do this without X :) 524my $fb_modes_file = "/sys/class/graphics/fb0/modes"; 525if (-f $fb_modes_file && -r $fb_modes_file) { 526 my $modes = read_file($fb_modes_file); 527 $modes =~ m/([0-9]+)x([0-9]+)/; 528 my $console_width = $1, my $console_height = $2; 529 if ($console_width > 1920) { 530 push @attrs, "# high-resolution display"; 531 push @attrs, 'hardware.video.hidpi.enable = lib.mkDefault true;'; 532 } 533} 534 535 536# Generate the hardware configuration file. 537 538sub toNixStringList { 539 my $res = ""; 540 foreach my $s (@_) { 541 $res .= " \"$s\""; 542 } 543 return $res; 544} 545sub toNixList { 546 my $res = ""; 547 foreach my $s (@_) { 548 $res .= " $s"; 549 } 550 return $res; 551} 552 553sub multiLineList { 554 my $indent = shift; 555 return " [ ]" if !@_; 556 my $res = "\n${indent}[ "; 557 my $first = 1; 558 foreach my $s (@_) { 559 $res .= "$indent " if !$first; 560 $first = 0; 561 $res .= "$s\n"; 562 } 563 $res .= "$indent]"; 564 return $res; 565} 566 567my $initrdAvailableKernelModules = toNixStringList(uniq @initrdAvailableKernelModules); 568my $initrdKernelModules = toNixStringList(uniq @initrdKernelModules); 569my $kernelModules = toNixStringList(uniq @kernelModules); 570my $modulePackages = toNixList(uniq @modulePackages); 571 572my $fsAndSwap = ""; 573if (!$noFilesystems) { 574 $fsAndSwap = "\n$fileSystems "; 575 $fsAndSwap .= "swapDevices =" . multiLineList(" ", @swapDevices) . ";\n"; 576} 577 578my $networkingDhcpConfig = generateNetworkingDhcpConfig(); 579 580my $hwConfig = <<EOF; 581# Do not modify this file! It was generated by ‘nixos-generate-config’ 582# and may be overwritten by future invocations. Please make changes 583# to /etc/nixos/configuration.nix instead. 584{ config, lib, pkgs, modulesPath, ... }: 585 586{ 587 imports =${\multiLineList(" ", @imports)}; 588 589 boot.initrd.availableKernelModules = [$initrdAvailableKernelModules ]; 590 boot.initrd.kernelModules = [$initrdKernelModules ]; 591 boot.kernelModules = [$kernelModules ]; 592 boot.extraModulePackages = [$modulePackages ]; 593$fsAndSwap 594$networkingDhcpConfig 595${\join "", (map { " $_\n" } (uniq @attrs))}} 596EOF 597 598sub generateNetworkingDhcpConfig { 599 # FIXME disable networking.useDHCP by default when switching to networkd. 600 my $config = <<EOF; 601 # Enables DHCP on each ethernet and wireless interface. In case of scripted networking 602 # (the default) this is the recommended approach. When using systemd-networkd it's 603 # still possible to use this option, but it's recommended to use it in conjunction 604 # with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`. 605 networking.useDHCP = lib.mkDefault true; 606EOF 607 608 foreach my $path (glob "/sys/class/net/*") { 609 my $dev = basename($path); 610 if ($dev ne "lo") { 611 $config .= " # networking.interfaces.$dev.useDHCP = lib.mkDefault true;\n"; 612 } 613 } 614 615 return $config; 616} 617 618sub generateXserverConfig { 619 my $xserverEnabled = "@xserverEnabled@"; 620 621 my $config = ""; 622 if ($xserverEnabled eq "1") { 623 $config = <<EOF; 624 # Enable the X11 windowing system. 625 services.xserver.enable = true; 626EOF 627 } else { 628 $config = <<EOF; 629 # Enable the X11 windowing system. 630 # services.xserver.enable = true; 631EOF 632 } 633} 634 635if ($showHardwareConfig) { 636 print STDOUT $hwConfig; 637} else { 638 if ($outDir eq "/etc/nixos") { 639 $outDir = "$rootDir$outDir"; 640 } else { 641 $outDir = File::Spec->rel2abs($outDir); 642 $outDir =~ s/\/*$//; # remove trailing slashes 643 } 644 645 my $fn = "$outDir/hardware-configuration.nix"; 646 print STDERR "writing $fn...\n"; 647 mkpath($outDir, 0, 0755); 648 write_file($fn, $hwConfig); 649 650 # Generate a basic configuration.nix, unless one already exists. 651 $fn = "$outDir/configuration.nix"; 652 if ($force || ! -e $fn) { 653 print STDERR "writing $fn...\n"; 654 655 my $bootLoaderConfig = ""; 656 if (-e "/sys/firmware/efi/efivars") { 657 $bootLoaderConfig = <<EOF; 658 # Use the systemd-boot EFI boot loader. 659 boot.loader.systemd-boot.enable = true; 660 boot.loader.efi.canTouchEfiVariables = true; 661EOF 662 } elsif (-e "/boot/extlinux") { 663 $bootLoaderConfig = <<EOF; 664 # Use the extlinux boot loader. (NixOS wants to enable GRUB by default) 665 boot.loader.grub.enable = false; 666 # Enables the generation of /boot/extlinux/extlinux.conf 667 boot.loader.generic-extlinux-compatible.enable = true; 668EOF 669 } elsif ($virt ne "systemd-nspawn") { 670 $bootLoaderConfig = <<EOF; 671 # Use the GRUB 2 boot loader. 672 boot.loader.grub.enable = true; 673 boot.loader.grub.version = 2; 674 # boot.loader.grub.efiSupport = true; 675 # boot.loader.grub.efiInstallAsRemovable = true; 676 # boot.loader.efi.efiSysMountPoint = "/boot/efi"; 677 # Define on which hard drive you want to install Grub. 678 # boot.loader.grub.device = "/dev/sda"; # or "nodev" for efi only 679EOF 680 } 681 682 my $networkingDhcpConfig = generateNetworkingDhcpConfig(); 683 684 my $xserverConfig = generateXserverConfig(); 685 686 (my $desktopConfiguration = <<EOF)=~s/^/ /gm; 687@desktopConfiguration@ 688EOF 689 690 write_file($fn, <<EOF); 691@configuration@ 692EOF 693 print STDERR "For more hardware-specific settings, see https://github.com/NixOS/nixos-hardware.\n" 694 } else { 695 print STDERR "warning: not overwriting existing $fn\n"; 696 } 697} 698 699# workaround for a bug in substituteAll