diff --git a/installer/nixos-hardware-scan.pl b/installer/nixos-hardware-scan.pl new file mode 100644 index 000000000000..5b2f6692d865 --- /dev/null +++ b/installer/nixos-hardware-scan.pl @@ -0,0 +1,174 @@ +#! @perl@ -w + +use File::Spec; +use File::Basename; + + +my @kernelModules = (); +my @initrdKernelModules = (); + + +# Read a file, returning undef if the file cannot be opened. +sub readFile { + my $filename = shift; + my $res; + if (open FILE, "<$filename") { + my $prev = $/; + undef $/; + $res = <FILE>; + $/ = $prev; + close FILE; + chomp $res; + } + return $res; +} + + +my $cpuinfo = readFile "/proc/cpuinfo"; + + +sub hasCPUFeature { + my $feature = shift; + return $cpuinfo =~ /^flags\s*:.* $feature( |$)/m; +} + + +# Detect the number of CPU cores. +my $cpus = scalar (grep {/^processor\s*:/} (split '\n', $cpuinfo)); + + +# CPU frequency scaling. Not sure about this test. +push @kernelModules, "acpi-cpufreq" if hasCPUFeature "acpi"; + + +# Virtualization support? +push @kernelModules, "kvm-intel" if hasCPUFeature "vmx"; +push @kernelModules, "kvm-amd" if hasCPUFeature "svm"; + + +# Look at the PCI devices and add necessary modules. Note that most +# modules are auto-detected so we don't need to list them here. +# However, some are needed in the initrd to boot the system. + +sub pciCheck { + my $path = shift; + my $vendor = readFile "$path/vendor"; + my $device = readFile "$path/device"; + my $class = readFile "$path/class"; + + my $module; + if (-e "$path/driver/module") { + $module = basename `readlink -f $path/driver/module`; + chomp $module; + } + + print "$path: $vendor $device $class"; + print " $module" if defined $module; + print "\n"; + + if (defined $module) { + # See the bottom of http://pciids.sourceforge.net/pci.ids for + # device classes. + if (# Mass-storage controller. Definitely important. + $class =~ /^0x01/ || + + # Firewire controller. A disk might be attached. + $class =~ /^0x0c00/ || + + # USB controller. Needed if we want to use the + # keyboard when things go wrong in the initrd. + $class =~ /^0x0c03/ + ) + { + push @initrdKernelModules, $module; + } + } +} + +foreach my $path (glob "/sys/bus/pci/devices/*") { + pciCheck $path; +} + + +# Idem for USB devices. + +sub usbCheck { + my $path = shift; + my $class = readFile "$path/bInterfaceClass"; + my $subclass = readFile "$path/bInterfaceSubClass"; + my $protocol = readFile "$path/bInterfaceProtocol"; + + my $module; + if (-e "$path/driver/module") { + $module = basename `readlink -f $path/driver/module`; + chomp $module; + } + + print "$path: $class $subclass $protocol"; + print " $module" if defined $module; + print "\n"; + + if (defined $module) { + if (# Mass-storage controller. Definitely important. + $class eq "08" || + + # Keyboard. Needed if we want to use the + # keyboard when things go wrong in the initrd. + ($class eq "03" && $protocol eq "01") + ) + { + push @initrdKernelModules, $module; + } + } +} + +foreach my $path (glob "/sys/bus/usb/devices/*") { + if (-e "$path/bInterfaceClass") { + usbCheck $path; + } +} + + + +# Generate the configuration file. + +sub removeDups { + my %seen; + my @res = (); + foreach my $s (@_) { + if (!defined $seen{$s}) { + $seen{$s} = ""; + push @res, $s; + } + } + return @res; +} + +sub toNixExpr { + my $res = ""; + foreach my $s (@_) { + $res .= " \"$s\""; + } + return $res; +} + +my $initrdKernelModules = toNixExpr(removeDups @initrdKernelModules); +my $kernelModules = toNixExpr(removeDups @kernelModules); + + +print <<EOF ; +# This is a generated file. Do not modify! +# Make changes to /etc/nixos/configuration.nix instead. +{ + boot = { + initrd = { + extraKernelModules = [ $initrdKernelModules ]; + }; + kernelModules = [ $kernelModules ]; + }; + + nix = { + maxJobs = $cpus; + }; +} +EOF diff --git a/installer/nixos-hardware-scan.sh b/installer/nixos-hardware-scan.sh deleted file mode 100644 index 06fbb11dfa1f..000000000000 --- a/installer/nixos-hardware-scan.sh +++ /dev/null @@ -1,144 +0,0 @@ -#! @shell@ -e - - -kernelModules= -initrdKernelModules= - -hasCPUFeature() { - local feature="$1" - cat /proc/cpuinfo | grep -q "^flags.* $feature\( \|$\)" -} - -needKernelModule() { - kernelModules="$kernelModules \"$1\"" -} - -needInitrdKernelModule() { - initrdKernelModules="$initrdKernelModules \"$1\"" -} - - -# Detect the number of CPU cores. -cpus="$(cat /proc/cpuinfo | grep '^processor' | wc -l)" - - -# CPU frequency scaling. Not sure about this test. -if hasCPUFeature "acpi"; then - needKernelModule "acpi-cpufreq" -fi - - -# Virtualization support? -if hasCPUFeature "vmx"; then - needKernelModule "kvm-intel" -fi - -if hasCPUFeature "svm"; then - needKernelModule "kvm-amd" -fi - - -# Look at the PCI devices and add necessary modules. Note that most -# modules are auto-detected so we don't need to list them here. -# However, some are needed in the initrd to boot the system. - -pciCheck() { - local path="$1" - local vendor="$(cat $path/vendor)" - local device="$(cat $path/device)" - local class="$(cat $path/class)" - - local module - if test -e "$path/driver/module"; then - module=$(basename $(readlink -f $path/driver/module)) - fi - - echo "$path: $vendor $device $class $module" - - if test -n "$module"; then - # See the bottom of http://pciids.sourceforge.net/pci.ids for - # device classes. - case $class in - 0x01*) - # Mass-storage controller. Definitely important. - needInitrdKernelModule $module - ;; - 0x0c00*) - # Firewire controller. A disk might be attached. - needInitrdKernelModule $module - ;; - 0x0c03*) - # USB controller. Needed if we want to use the - # keyboard when things go wrong in the initrd. - needInitrdKernelModule $module - ;; - esac - fi -} - -for path in /sys/bus/pci/devices/*; do - pciCheck "$path" -done - - -# Idem for USB devices. - -usbCheck() { - local path="$1" - local class="$(cat $path/bInterfaceClass)" - local subclass="$(cat $path/bInterfaceSubClass)" - local protocol="$(cat $path/bInterfaceProtocol)" - - local module - if test -e "$path/driver/module"; then - module=$(basename $(readlink -f $path/driver/module)) - fi - - echo "$path: $class $subclass $protocol $module" - - if test -n "$module"; then - # See http://www.linux-usb.org/usb.ids for - # classes/subclasses/protocols. - case $class:$subclass:$protocol in - 08:*) - # Mass-storage controller. Definitely important. - needInitrdKernelModule $module - ;; - 03:*:01) - # Keyboard. Needed if we want to use the - # keyboard when things go wrong in the initrd. - needInitrdKernelModule $module - ;; - esac - fi -} - -for path in /sys/bus/usb/devices/*; do - if test -e "$path/bInterfaceClass"; then - usbCheck "$path" - fi -done - - -# Remove duplicate modules. !!! preserve order -kernelModules=$(for i in $kernelModules; do echo $i; done | sort | uniq) -initrdKernelModules=$(for i in $initrdKernelModules; do echo $i; done | sort | uniq) - - -# Generation the configuration file. -cat <<EOF -# This is a generated file. Do not modify! -# Make changes to /etc/nixos/configuration.nix instead. -{ - boot = { - initrd = { - extraKernelModules = [ $(echo $initrdKernelModules) ]; - }; - kernelModules = [ $(echo $kernelModules) ]; - }; - - nix = { - maxJobs = $cpus; - }; -} -EOF