diff options
Diffstat (limited to 'perl-install/modules.pm')
-rw-r--r-- | perl-install/modules.pm | 549 |
1 files changed, 206 insertions, 343 deletions
diff --git a/perl-install/modules.pm b/perl-install/modules.pm index 47c3bec8c..abeb0b366 100644 --- a/perl-install/modules.pm +++ b/perl-install/modules.pm @@ -1,20 +1,17 @@ -package modules; # $Id$ +package modules; use strict; -use vars qw(%conf); use common; use detect_devices; use run_program; use log; use list_modules; - -%conf = (); +use modules::any_conf; sub modules_descriptions() { my $f = '/lib/modules/' . c::kernel_version() . '/modules.description'; - -e $f or $f = '/lib/modules.description'; - map { /(\S+)\s+(.*)/ } cat_($f); + map { my ($m, $d) = /(\S+)\s+(.*)/; $m =~ s/-/_/g; ($m => $d) } cat_($f); } sub module2description { +{ modules_descriptions() }->{$_[0]} } @@ -25,49 +22,132 @@ sub category2modules_and_description { 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) ], [ map { my $s = $_; $s =~ s/_/-/g; $s, $_ } loaded_modules() ]) or return; - - my $network_module = do { - my ($network_modules, $other) = partition { module2category($_) =~ m,network/(main|gigabit|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() : (); - - if ($::testing || $::blank) { - log::l("i would load module $_ (" . join(" ", @{$options{$_}}) . ")") foreach @l; - } elsif ($::isStandalone || $::move) { - run_program::run('/sbin/modprobe', $_, @{$options{$_}}) - or !run_program::run('/sbin/modprobe', '-n', $_) #- ignore missing modules - or die "insmod'ing module $_ failed" foreach @l; + } + $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; } - sleep 2 if any { /^(usb-storage|mousedev|printer)$/ } @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'); + } +} +sub load_with_options { + my ($l, $h_options) = @_; + + 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 ($network_module) { - add_alias($_, $network_module) foreach difference2([ detect_devices::getNet() ], \@network_devices); + 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 { @@ -79,219 +159,67 @@ sub unload { } sub load_category { - my ($category, $o_wait_message) = @_; - - #- 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', 'airport'), - if_($category =~ /sound/, 'dmasound_pmac'), + if_(detect_devices::usbStorage(), 'usb_storage'), ), ); - grep { + 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([ $_->{driver}, if_($_->{options}, $_->{options}) ]) }; + eval { load_and_configure($conf, $_->{driver}, $_->{options}) }; $_->{error} = $@; - $_->{try} = 1 if member($_->{driver}, 'hptraid', 'ohci1394'); #- don't warn when this fails - - !($_->{error} && $_->{try}); - } probe_category($category), - 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) = @_; - - my @modules = category2modules($category); - - grep { - if ($category eq 'network/isdn') { - my $b = $_->{driver} =~ /ISDN:([^,]*),?([^,]*)(?:,firmware=(.*))?/; - if ($b) { - $_->{driver} = $1; - $_->{options} = $2; - $_->{firmware} = $3; - $_->{driver} eq "hisax" and $_->{options} .= " id=HiSax"; - } - $b; - } else { - member($_->{driver}, @modules); - } - } detect_devices::probeall(); -} +sub load_parallel_zip { + my ($conf) = @_; + 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 $alias to @$l"); -} - -sub remove_alias($) { - my ($name) = @_; - remove_alias_regexp("^$name\$"); -} - -sub remove_alias_regexp($) { - my ($aliased) = @_; - foreach (keys %conf) { - delete $conf{$_}{alias} if /$aliased/; - } -} - -sub remove_alias_regexp_byname($) { - my ($name) = @_; - foreach (keys %conf) { - delete $conf{$_} if /$name/; - } -} - -sub remove_module($) { - my ($name) = @_; - remove_alias($name); - delete $conf{$name}; - 0; -} - -sub read_conf { - my ($file) = @_; - my %c; - - foreach (cat_($file)) { - next if /^\s*#/; - s/#.*$//; - my ($type, $alias, $val) = split(/\s+/, chomp_($_), 3) or next; - $val =~ s/\s+$//; - - $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}; - } - } - # Convert alsa driver from old naming system to new one (snd-card-XXX => snd-XXX) - # Ensure correct upgrade for snd-via683 and snd-via8233 drivers - foreach my $alias (sort keys %c) { - $c{$alias}{alias} =~ s/^snd-card/snd/; - $c{$alias}{alias} = 'snd-via82xx' if $c{$alias}{alias} =~ /^snd-via686|^snd-via8233/; - } - - \%c; -} - -sub mergein_conf { - my ($file) = @_; - my $modconfref = read_conf($file); - while (my ($key, $value) = each %$modconfref) { - $conf{$key}{alias} ||= $value->{alias}; - $conf{$key}{options} = $value->{options} if $value->{options}; - push @{$conf{$key}{probeall} ||= []}, deref($value->{probeall}); - } -} - -sub write_conf() { - 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 ($type eq 'above') { - # Convert alsa driver from old naming system to new one (snd-card-XXX => snd-XXX) - # Ensure correct upgrade for snd-via683 and snd-via8233 drivers - s/snd-card/snd/g; - s/snd-via686|snd-via8233/snd-via82xx/g; - } elsif ($conf{$alias}{$type} && $conf{$alias}{$type} ne $module) { - my $v = join(' ', uniq(deref($conf{$alias}{$type}))); - $_ = "$type $alias $v\n"; - } elsif ($type eq 'alias' && !defined $conf{$alias}{alias}) { - $_ = ''; - } - } $file; - - my $written = read_conf($file); - - open(my $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}; - } - } +sub write_preload_conf { + my ($conf) = @_; my @l; - push @l, 'scsi_hostadapter' if !is_empty_array_ref($conf{scsi_hostadapter}{probeall}); - push @l, 'bttv' if detect_devices::matching_driver('^bttv$'); - append_to_modules_loaded_at_startup("$::prefix/etc/modules", @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); +} - #- use module-init-tools script for the moment - run_program::rooted($::prefix, "/sbin/generate-modprobe.conf", ">", "/etc/modprobe.conf") if -e "$::prefix/etc/modprobe.conf"; +sub append_to_modules_loaded_at_startup_for_all_kernels { + append_to_modules_loaded_at_startup($_, @_) foreach "$::prefix/etc/modprobe.preload"; } sub append_to_modules_loaded_at_startup { my ($file, @l) = @_; - my $l = join '|', map { '^\s*'.$_.'\s*$' } @l; + my $l = join '|', map { '^\s*' . $_ . '\s*$' } @l; log::l("to put in $file ", join(", ", @l)); substInFile { @@ -300,49 +228,15 @@ sub append_to_modules_loaded_at_startup { } $file; } -sub read_stage1_conf { - mergein_conf($_[0]); -} - -#-############################################################################### -#- 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; - - 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 => "", - }); +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); + } + eval { load(@modules) } if @modules && !$::isInstall; } @@ -352,86 +246,55 @@ sub write_pcmcia { sub loaded_modules() { map { /(\S+)/ } cat_("/proc/modules"); } -sub read_already_loaded() { - when_load($_) foreach reverse loaded_modules(); +sub filter_out_loaded_modules { + my (@l) = @_; + difference2([ uniq(@l) ], [ map { my $s = $_; $s =~ s/_/-/g; $s, $_ } loaded_modules() ]); } -my $module_extension = c::kernel_version() =~ /^\Q2.4/ ? 'o' : 'ko'; - -sub name2file { - my ($name) = @_; - "$name.$module_extension"; +sub read_already_loaded { + my ($conf) = @_; + when_load($conf, $_) foreach reverse loaded_modules(); } sub when_load { - my ($name, @options) = @_; - - if ($name =~ /[uo]hci/) { - -f '/proc/bus/usb/devices' or 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 4; - load("usbkbd", "keybdev") if detect_devices::usbKeyboards(); - } - } - - load('snd-pcm-oss') if $name =~ /^snd-/; - add_alias('ieee1394-controller', $name) if member($name, 'ohci1394'); - add_probeall('usb-interface', $name) if member($name, qw(usb-uhci usb-ohci ehci-hcd uhci-hcd ohci-hcd)); - - $conf{$name}{options} = join " ", @options if @options; + my ($conf, $name) = @_; if (my $category = module2category($name)) { - if ($category =~ m,disk/(scsi|hardware_raid|usb|firewire),) { - add_probeall('scsi_hostadapter', $name) if $name ne 'usb-storage'; - eval { load('sd_mod') }; - } - add_alias('sound-slot-0', $name) if $category =~ /sound/; + when_load_category($conf, $name, $category); } -} - -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 { name2file($_) } @modules); - map { $dir . '/' . name2file($_) } @modules; - }; -} - -sub load_raw { - my @l = @_; - - extract_modules('/tmp', map { $_->[0] } @l); - my @failed = grep { - my $m = '/tmp/' . name2file($_->[0]); - 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 get_parameters { - map { if_(/(.*)=(.*)/, $1 => $2) } split(' ', get_options($_[0])); +sub when_load_category { + my ($conf, $name, $category) = @_; + + 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)); + } } - 1; |