summaryrefslogtreecommitdiffstats
path: root/perl-install/modules.pm
diff options
context:
space:
mode:
Diffstat (limited to 'perl-install/modules.pm')
-rw-r--r--perl-install/modules.pm535
1 files changed, 216 insertions, 319 deletions
diff --git a/perl-install/modules.pm b/perl-install/modules.pm
index e143ee5e1..abeb0b366 100644
--- a/perl-install/modules.pm
+++ b/perl-install/modules.pm
@@ -1,4 +1,4 @@
-package modules; # $Id$
+package modules;
use strict;
@@ -7,60 +7,147 @@ use detect_devices;
use run_program;
use log;
use list_modules;
+use modules::any_conf;
-my %conf;
+sub modules_descriptions() {
+ my $f = '/lib/modules/' . c::kernel_version() . '/modules.description';
+ map { my ($m, $d) = /(\S+)\s+(.*)/; $m =~ s/-/_/g; ($m => $d) } cat_($f);
+}
+
+sub module2description { +{ modules_descriptions() }->{$_[0]} }
sub category2modules_and_description {
my ($categories) = @_;
- my $f = '/lib/modules/' . c::kernel_version() . '/modules.description';
- -e $f or $f = '/lib/modules.description';
- my %modules_descriptions = map { /(\S+)\s+(.*)/ } cat_($f);
+ my %modules_descriptions = modules_descriptions();
map { $_ => $modules_descriptions{$_} } category2modules($categories);
}
+my %mappings_24_26 = (
+ "usb_ohci" => "ohci_hcd",
+ "usb_uhci" => "uhci_hcd",
+ "uhci" => "uhci_hcd",
+ "printer" => "usblp",
+ "bcm4400" => "b44",
+ "3c559" => "3c359",
+ "3c90x" => "3c59x",
+ "dc395x_trm" => "dc395x",
+);
+my %mappings_26_24 = reverse %mappings_24_26;
+$mappings_26_24{uhci_hcd} = 'usb_uhci';
+
+my @parallel_zip_modules = qw(imm ppa);
+
+sub mapping_24_26 {
+ my ($modname) = @_;
+ $mappings_24_26{$modname} || $modname;
+}
+sub mapping_26_24 {
+ my ($modname) = @_;
+ $mappings_26_24{$modname} || $modname;
+}
+
+sub cond_mapping_24_26 {
+ my ($modname) = @_;
+ $mappings_24_26{$modname} || list_modules::filename2modname($modname);
+}
+
+sub module_is_available {
+ my ($module) = @_;
+ defined list_modules::modname2filename($module);
+}
+
#-###############################################################################
#- module loading
#-###############################################################################
-# handles dependencies
-# eg: load('vfat', 'reiserfs', [ ne2k => 'io=0xXXX', 'dma=5' ])
-sub load {
- #- keeping the order of modules
- my %options;
- my @l = map {
- my ($name, @options) = ref $_ ? @$_ : $_;
- $options{$name} = \@options;
- dependencies_closure($name);
- } @_;
-
- @l = difference2([ uniq(@l) ], [ loaded_modules() ]) or return;
-
- my $network_module = do {
- my ($network_modules, $other) = partition { module2category($_) =~ m,network/(main|usb), } @l;
- if (@$network_modules > 1) {
- # do it one by one
- load($_) foreach @$network_modules;
- load(@$other);
- return;
+
+sub filter_loaded_modules {
+ my ($lm) = @_;
+
+ my $l;
+
+ # try to detect built-in modules by looking at /sys/module
+ # unfortunately it does not work for all modules eg :
+ # - networks protocols like af_packet
+ # - filesystems
+ foreach my $mod (@$lm) {
+ $mod =~ s/-/_/g;
+ if (-d "/sys/module/$mod") {
+ log::l("$mod already loaded");
+ } elsif ($mod =~ /af_packet/) {
+ if (-f "/proc/net/packet") {
+ log::l("$mod already loaded");
+ } else {
+ push @$l, $mod;
+ }
+ } elsif (cat_("/proc/filesystems") =~ /$mod/) {
+ log::l("$mod already loaded");
+ } elsif ($mod =~ /serial/) {
+ # hack ... must find who tries to load the module serial
+ } else {
+ push @$l, $mod;
}
- $network_modules->[0];
- };
- my @network_devices = $network_module ? detect_devices::getNet() : ();
+ }
+ $l;
+}
- if ($::testing) {
- log::l("i would load module $_ (@{$options{$_}})") foreach @l;
- } elsif ($::isStandalone || $::live) {
- run_program::run('/sbin/modprobe', $_, @{$options{$_}})
- or !run_program::run('/sbin/modprobe', '-n', $_) #- ignore missing modules
- or die "insmod'ing module $_ failed" foreach @l;
+# handles dependencies
+sub load_raw {
+ my ($lm, $h_options) = @_;
+
+ my $l = filter_loaded_modules($lm);
+
+ if ($::testing || $::local_install) {
+ log::l("i would load module $_ ($h_options->{$_})") foreach @$l;
} else {
- load_raw(map { [ $_ => $options{$_} ] } @l);
+ run_program::run('/sbin/modprobe', $_, split(' ', $h_options->{$_}))
+ or !run_program::run('/sbin/modprobe', '-n', $_) #- ignore missing modules
+ or die "insmod'ing module $_ failed" foreach @$l;
+ }
+ if (any { /^(mousedev|printer)$/ } @$l) {
+ sleep 2;
+ } elsif (member('usb_storage', @$l)) {
+ #- usb_storage is only modprobed when we know there is some scsi devices
+ #- so trying hard to wait for devices to be detected
+ run_program::run('udevadm', 'settle');
}
- sleep 2 if grep { /^(usb-storage|mousedev|printer)$/ } @l;
+}
+sub load_with_options {
+ my ($l, $h_options) = @_;
- if ($network_module) {
- add_alias($_, $network_module) foreach difference2([ detect_devices::getNet() ], \@network_devices);
+ my @l = map {
+ if_(member($_, 'plip', @parallel_zip_modules), 'parport_pc'),
+ if_($_ eq 'vfat', 'nls_cp437', 'nls_iso8859_1'),
+ if_(member($_, qw(btrfs xfs)), 'crc32c', 'crc32c-intel'),
+ cond_mapping_24_26($_);
+ } @$l;
+
+ @l = filter_out_loaded_modules(@l) or return;
+
+ my %options = map { cond_mapping_24_26($_) => $h_options->{$_} } keys %$h_options;
+ load_raw(\@l, \%options);
+}
+sub load {
+ my (@l) = @_;
+ load_with_options(\@l, {});
+}
+
+# eg: load_and_configure($modules_conf, 'bt878', [ bttv => 'no_overlay=1' ])
+sub load_and_configure {
+ my ($conf, $module, $o_options) = @_;
+
+ my @l = filter_out_loaded_modules(cond_mapping_24_26($module));
+ load_raw(\@l, { cond_mapping_24_26($module) => $o_options });
+
+ if (member($module, @parallel_zip_modules)
+ && ! -d "/proc/sys/dev/parport/parport0/devices/$module") {
+ log::l("$module loaded but is not useful, removing");
+ unload($module);
+ return;
}
- when_load($_, @{$options{$_}}) foreach @l;
+
+ $conf->set_options($module, $o_options) if $o_options;
+
+ when_load($conf, $module);
}
sub unload {
@@ -72,332 +159,142 @@ sub unload {
}
sub load_category {
- my ($category, $wait_message, $probe_type) = @_;
-
- #- probe_category returns the PCMCIA cards. It doesn't know they are already
- #- loaded, so:
- read_already_loaded();
+ my ($conf, $category, $o_wait_message) = @_;
my @try_modules = (
if_($category =~ /scsi/,
- if_(arch() !~ /ppc/, 'imm', 'ppa'),
- if_(detect_devices::usbStorage(), 'usb-storage'),
- ),
- if_(arch() =~ /ppc/,
- if_($category =~ /scsi/, 'mesh', 'mac53c94'),
- if_($category =~ /net/, 'bmac', 'gmac', 'mace'),
- if_($category =~ /sound/, 'dmasound_awacs'),
+ if_(detect_devices::usbStorage(), 'usb_storage'),
),
);
- grep {
- $wait_message->($_->{description}, $_->{driver}) if $wait_message;
- eval { load([ $_->{driver}, $_->{options} ]) };
+ my @l = (
+ (map {
+ my $other = { ahci => 'ata_piix', ata_piix => 'ahci' }->{$_->{driver}};
+ $_->{try} = 1 if $other;
+ ($_, if_($other, { %$_, driver => $other }));
+ } detect_devices::probe_category($category)),
+ (map { { driver => $_, description => $_, try => 1 } } @try_modules),
+ );
+
+ foreach (@l) {
+ $o_wait_message->($_->{description}, $_->{driver}) if $o_wait_message;
+ eval { load_and_configure($conf, $_->{driver}, $_->{options}) };
$_->{error} = $@;
- !($@ && $_->{try});
- } probe_category($category, $probe_type),
- map { { driver => $_, description => $_, try => 1 } } @try_modules;
+ $_->{try} = 1 if member($_->{driver}, 'hptraid', 'ohci1394'); #- do not warn when this fails
+ }
+ eval { load_and_configure($conf, 'ide_generic') } if $category eq 'disk/ide';
+ grep { !($_->{error} && $_->{try}) } @l;
}
-sub probe_category {
- my ($category, $probe_type) = @_;
-
- my @modules = category2modules($category);
-
- grep {
- if ($category eq 'isdn') {
- my $b = $_->{driver} =~ /ISDN:([^,]*),?([^,]*),?(.*)/;
- if ($b) {
- $_->{driver} = $1;
- $_->{options} = $2;
- $_->{firmware} = $3;
- $_->{firmware} =~ s/firmware=//;
- $_->{driver} eq "hisax" and $_->{options} .= " id=HiSax";
- }
- $b;
- } else {
- member($_->{driver}, @modules);
- }
- } detect_devices::probeall($probe_type);
-}
+sub load_parallel_zip {
+ my ($conf) = @_;
-sub load_ide {
- eval { load("ide-cd") }
+ grep {
+ eval { load_and_configure($conf, $_); 1 };
+ } @parallel_zip_modules;
}
-
#-###############################################################################
#- modules.conf functions
#-###############################################################################
-sub get_alias {
- my ($alias) = @_;
- $conf{$alias}{alias};
-}
-sub get_probeall {
- my ($alias) = @_;
- $conf{$alias}{probeall};
-}
-sub get_options {
- my ($name) = @_;
- $conf{$name}{options};
-}
-sub set_options {
- my ($name, $new_option) = @_;
- $conf{$name}{options} = $new_option;
-}
-sub add_alias {
- my ($alias, $module) = @_;
- $module =~ /ignore/ and return;
- /\Q$alias/ && $conf{$_}{alias} && $conf{$_}{alias} eq $module and return $_ foreach keys %conf;
- log::l("adding alias $alias to $module");
- $conf{$alias}{alias} ||= $module;
- $conf{$module}{above} = 'snd-pcm-oss' if $module =~ /^snd-/;
- $alias;
-}
-sub add_probeall {
- my ($alias, $module) = @_;
-
- my $l = $conf{$alias}{probeall} ||= [];
- @$l = uniq(@$l, $module);
- log::l("setting probeall scsi_hostadapter to @$l");
-}
-
-sub remove_alias($) {
- my ($name) = @_;
- foreach (keys %conf) {
- $conf{$_}{alias} && $conf{$_}{alias} eq $name or next;
- delete $conf{$_}{alias};
- return 1;
- }
- 0;
-}
-
-sub read_conf {
- my ($file) = @_;
- my %c;
-
- foreach (cat_($file)) {
- next if /^\s*#/;
- my ($type, $alias, $val) = split(/\s+/, chomp_($_), 3) or next;
-
- $val = [ split ' ', $val ] if $type eq 'probeall';
-
- $c{$alias}{$type} = $val;
- }
- #- cheating here: not handling aliases of aliases
- while (my ($k, $v) = each %c) {
- if (my $a = $v->{alias}) {
- local $c{$a}{alias};
- delete $v->{probeall};
- add2hash($c{$a}, $v);
- }
- }
- #- convert old aliases to new probeall
- foreach my $name ('scsi_hostadapter', 'usb-interface') {
- my @old_aliases =
- map { $_->[0] } sort { $a->[1] <=> $b->[1] }
- map { if_(/^$name(\d*)/ && $c{$_}{alias}, [ $_, $1 || 0 ]) } keys %c;
- foreach my $alias (@old_aliases) {
- push @{$c{$name}{probeall} ||= []}, delete $c{$alias}{alias};
- }
- }
-
- \%c;
+sub write_preload_conf {
+ my ($conf) = @_;
+ my @l;
+ my $is_laptop = detect_devices::isLaptop();
+ my $manufacturer = detect_devices::dmidecode_category('System')->{Manufacturer};
+ push @l, 'scsi_hostadapter' if $conf->get_probeall('scsi_hostadapter');
+ push @l, detect_devices::probe_name('Module');
+ push @l, 'nvram' if $is_laptop;
+ push @l, map { $_->{driver} } detect_devices::probe_category($_) foreach qw(multimedia/dvb multimedia/tv various/agpgart various/laptop input/joystick various/crypto disk/card_reader);
+ push @l, 'padlock-aes', 'padlock-sha' if cat_("/proc/cpuinfo") =~ /rng_en/;
+ push @l, 'evdev' if detect_devices::hasTouchpad();
+ push @l, 'evdev' if any { $_->{HWHEEL} } detect_devices::getInputDevices();
+ push @l, 'hdaps' if $is_laptop && $manufacturer eq 'LENOVO';
+ append_to_modules_loaded_at_startup("$::prefix/etc/modprobe.preload", @l);
}
-sub mergein_conf {
- my ($file) = @_;
- my $modconfref = read_conf($file);
- while (my ($key, $value) = each %$modconfref) {
- $conf{$key}{alias} = $value->{alias} if !exists $conf{$key}{alias};
- $conf{$key}{options} = $value->{options} if $value->{options};
- push @{$conf{$key}{probeall} ||= []}, deref($value->{probeall});
- }
+sub append_to_modules_loaded_at_startup_for_all_kernels {
+ append_to_modules_loaded_at_startup($_, @_) foreach "$::prefix/etc/modprobe.preload";
}
-sub write_conf {
- my ($prefix) = @_;
-
- my $file = "$prefix/etc/modules.conf";
- rename "$prefix/etc/conf.modules", $file; #- make the switch to new name if needed
-
- #- Substitute new aliases in modules.conf (if config has changed)
- substInFile {
- my ($type,$alias,$module) = split(/\s+/, chomp_($_), 3);
- if ($type eq 'post-install' && $alias eq 'supermount') {
- #- remove the post-install supermount stuff.
- $_ = '';
- } elsif ($type eq 'alias' && $alias =~ /scsi_hostadapter|usb-interface/) {
- #- remove old aliases which are replaced by probeall
- $_ = '';
- } elsif (
- $conf{$alias}{$type} &&
- $conf{$alias}{$type} ne $module) {
- my $v = join(' ', uniq(deref($conf{$alias}{$type})));
- $_ = "$type $alias $v\n";
- }
- } $file;
-
- my $written = read_conf($file);
-
- local *F;
- open F, ">> $file" or die("cannot write module config file $file: $!\n");
- while (my ($mod, $h) = each %conf) {
- while (my ($type, $v) = each %$h) {
- my $v2 = join(' ', uniq(deref($v)));
- print F "$type $mod $v2\n"
- if $v2 && !$written->{$mod}{$type};
- }
- }
- my @l;
- push @l, 'scsi_hostadapter' if !is_empty_array_ref($conf{scsi_hostadapter}{probeall});
- push @l, 'bttv' if grep { $_->{driver} eq 'bttv' } detect_devices::probeall();
- append_to_etc_modules($prefix, @l);
-}
-
-sub append_to_etc_modules {
- my ($prefix, @l) = @_;
- my $l = join '|', map { '^\s*'.$_.'\s*$' } @l;
- log::l("to put in modules ", join(", ", @l));
+sub append_to_modules_loaded_at_startup {
+ my ($file, @l) = @_;
+ my $l = join '|', map { '^\s*' . $_ . '\s*$' } @l;
+ log::l("to put in $file ", join(", ", @l));
substInFile {
$_ = '' if $l && /$l/;
$_ .= join '', map { "$_\n" } @l if eof;
- } "$prefix/etc/modules";
-}
-
-sub read_stage1_conf {
- mergein_conf($_[0]);
+ } $file;
}
-#-###############################################################################
-#- pcmcia various
-#-###############################################################################
-sub configure_pcmcia {
- my ($pcic) = @_;
-
- #- try to setup pcmcia if cardmgr is not running.
- my $running if 0;
- return if $running;
- $running = 1;
-
- if (c::kernel_version() =~ /^2\.2/) {
- my $msg = _("PCMCIA support no longer exist for 2.2 kernels. Please use a 2.4 kernel.");
- log::l($msg);
- return $msg;
+sub set_preload_modules {
+ my ($service, @modules) = @_;
+ my $preload_file = "$::prefix/etc/modprobe.preload.d/$service";
+ if (@modules) {
+ output_p($preload_file, join("\n", @modules, ''));
+ } else {
+ unlink($preload_file);
}
-
- log::l("i try to configure pcmcia services");
-
- symlink "/tmp/stage2/$_", $_ foreach "/etc/pcmcia";
-
- eval {
- load("pcmcia_core");
- load($pcic);
- load("ds");
- };
-
- #- run cardmgr in foreground while it is configuring the card.
- run_program::run("cardmgr", "-f", "-m" ,"/modules");
- sleep(3);
-
- #- make sure to be aware of loaded module by cardmgr.
- read_already_loaded();
-}
-
-sub write_pcmcia {
- my ($prefix, $pcmcia) = @_;
-
- #- should be set after installing the package above otherwise the file will be renamed.
- setVarsInSh("$prefix/etc/sysconfig/pcmcia", {
- PCMCIA => bool2yesno($pcmcia),
- PCIC => $pcmcia,
- PCIC_OPTS => "",
- CORE_OPTS => "",
- });
+ eval { load(@modules) } if @modules && !$::isInstall;
}
#-###############################################################################
#- internal functions
#-###############################################################################
-sub loaded_modules {
+sub loaded_modules() {
map { /(\S+)/ } cat_("/proc/modules");
}
+sub filter_out_loaded_modules {
+ my (@l) = @_;
+ difference2([ uniq(@l) ], [ map { my $s = $_; $s =~ s/_/-/g; $s, $_ } loaded_modules() ]);
+}
+
sub read_already_loaded {
- when_load($_) foreach reverse loaded_modules();
+ my ($conf) = @_;
+ when_load($conf, $_) foreach reverse loaded_modules();
}
sub when_load {
- my ($name, @options) = @_;
- my $category = module2category($name);
+ my ($conf, $name) = @_;
- if ($category =~ m,disk/(scsi|hardware_raid|usb),) {
- add_probeall('scsi_hostadapter', $name);
- eval { load('sd_mod') };
+ if (my $category = module2category($name)) {
+ when_load_category($conf, $name, $category);
}
- add_alias('sound-slot-0', $name) if $category =~ /sound/;
- load('snd-pcm-oss') if $name =~ /^snd-/;
- add_probeall('usb-interface', $name) if $name =~ /usb-[uo]hci/ || $name eq 'ehci-hcd';
- $conf{$name}{options} = join " ", @options if @options;
-}
-
-sub cz_file {
- "/lib/modules" . (arch() eq 'sparc64' && "64") . ".cz-" . c::kernel_version();
-}
-sub extract_modules {
- my ($dir, @modules) = @_;
- my $cz = cz_file();
- if (!-e $cz) {
- unlink $_ foreach glob_("/lib/modules*.cz*");
- require install_any;
- install_any::getAndSaveFile("Mandrake/mdkinst$cz", $cz) or die "failed to get modules $cz: $!";
+ if (my @above = $conf->get_above($name)) {
+ load(@above); #- eg: for snd-pcm-oss set by set_sound_slot()
}
- eval {
- require packdrake;
- my $packer = new packdrake($cz, quiet => 1);
- $packer->extract_archive($dir, map { "$_.o" } @modules);
- };
}
-sub load_raw {
- my @l = @_;
-
- extract_modules('/tmp', map { $_->[0] } @l);
- my @failed = grep {
- my $m = "/tmp/$_->[0].o";
- if (-e $m && run_program::run(["/usr/bin/insmod_", "insmod"], '2>', '/dev/tty5', $m, @{$_->[1]})) {
- unlink $m;
- '';
- } else {
- log::l("missing module $_->[0]") if !-e $m;
- -e $m;
- }
- } @l;
-
- die "insmod'ing module " . join(", ", map { $_->[0] } @failed) . " failed" if @failed;
+sub when_load_category {
+ my ($conf, $name, $category) = @_;
- foreach (@l) {
- if ($_->[0] =~ /usb-[uo]hci/) {
- eval {
- require fs; fs::mount('/proc/bus/usb', '/proc/bus/usb', 'usbdevfs');
- #- ensure keyboard is working, the kernel must do the job the BIOS was doing
- sleep 2;
- load("usbkbd", "keybdev") if detect_devices::usbKeyboards();
- }
- }
+ if ($category =~ m,disk/ide,) {
+ $conf->add_probeall('ide-controller', $name);
+ eval { load('ide_gd_mod') };
+ } elsif ($category =~ m,disk/(scsi|hardware_raid|sata|firewire|virtual),) {
+ $conf->add_probeall('scsi_hostadapter', $name);
+ eval { load('sd_mod') };
+ } elsif ($category eq 'bus/usb') {
+ $conf->add_probeall('usb-interface', $name);
+ -f '/sys/kernel/debug/usb/devices' or eval {
+ require fs::mount; fs::mount::sys_kernel_debug('');
+ #- ensure keyboard is working, the kernel must do the job the BIOS was doing
+ sleep 4;
+ load("usbhid") if detect_devices::usbKeyboards();
+ };
+ } elsif ($category eq 'bus/firewire') {
+ $conf->set_alias('ieee1394-controller', $name);
+ } elsif ($category =~ /sound/) {
+ my $sound_alias = find { /^sound-slot-[0-9]+$/ && $conf->get_alias($_) eq $name } $conf->modules;
+ $sound_alias ||= 'sound-slot-0';
+ $conf->set_sound_slot($sound_alias, $name);
+ } elsif ($category =~ m!disk/card_reader!) {
+ my @modules = ('mmc_block', if_($name =~ /tifm_7xx1/, 'tifm_sd'));
+ $conf->set_above($name, join(' ', @modules));
}
}
-sub get_parameters {
- my %conf;
- foreach (split(' ', get_options($_[0]))) {
- /(.*)=(.*)/;
- $conf{$1} = $2;
- };
- %conf;
-}
-
-
1;