forked from mirrors/nixpkgs
* Rewrote the hardware scanner in Perl.
svn path=/nixos/trunk/; revision=10405
This commit is contained in:
parent
c1f619a087
commit
7363895f6d
174
installer/nixos-hardware-scan.pl
Normal file
174
installer/nixos-hardware-scan.pl
Normal file
|
@ -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
|
|
@ -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
|
|
Loading…
Reference in a new issue