diff options
Diffstat (limited to 'perl-install/standalone/service_harddrake')
| -rwxr-xr-x | perl-install/standalone/service_harddrake | 284 |
1 files changed, 284 insertions, 0 deletions
diff --git a/perl-install/standalone/service_harddrake b/perl-install/standalone/service_harddrake new file mode 100755 index 000000000..e5dbbd22e --- /dev/null +++ b/perl-install/standalone/service_harddrake @@ -0,0 +1,284 @@ +#!/usr/bin/perl + +use lib qw(/usr/lib/libDrakX); + +use strict; +use diagnostics; +use standalone; #- warning, standalone must be loaded very first, for 'explanations' +use c; +use common; +use interactive; +use detect_devices; +use harddrake::data; +use harddrake::autoconf; +use harddrake::sound; +use modules; +use Storable qw(store retrieve); + + +my $force = member('--force', @ARGV); + +my $mode = $ARGV[0] eq 'stop' && 'stop'; + +if ($mode eq 'stop') { + substInFile { $_ .= "audio\nsnd-usb-audio\n" if eof } '/etc/hotplug/blacklist'; + append_to_file('/etc/modprobe.conf', "blacklist audio\nblacklist snd-usb-audio\n") if cat_('/etc/modprobe.conf') !~ /^blacklist snd-usb-audio/m; + c::_exit(0); +} + +my $invert_do_it = $ARGV[0] eq 'X11' ? 1 : 0; +my ($hw_sysconfdir, $timeout) = ("/etc/sysconfig/harddrake2", $invert_do_it ? 600 : 25); +my $last_boot_config = "$hw_sysconfdir/previous_hw"; + +$last_boot_config .= '_X11' if $invert_do_it; + +my $modules_conf = modules::any_conf->read; + +my $isLaptop = detect_devices::isLaptop(); +my $curr_kernel = c::kernel_version(); +$curr_kernel =~ s/(^\d+\.\d+).*/$1/; + +my %previous_kernel_config = getVarsFromSh("$hw_sysconfdir/kernel"); +setVarsInSh("$hw_sysconfdir/kernel", { KERNEL => $curr_kernel, IS_LAPTOP => bool2text($isLaptop) }); +my %cfg = getVarsFromSh("$hw_sysconfdir/service.conf"); + +# autoreconfigure the mouse on major kernel change: +if ($curr_kernel ne $previous_kernel_config{KERNEL}) { + log::explanations("Autoconfiguring mouse since we switched between 2.4.x and 2.6.x kernels"); + harddrake::autoconf::mouse_conf($modules_conf); +} +# autoreconfigure laptop-dependent services when switching from laptop to desktop, and vice versa +if (!exists $previous_kernel_config{IS_LAPTOP} || $force || $isLaptop != text2bool($previous_kernel_config{IS_LAPTOP})) { + log::explanations("Autoconfiguring laptop tools since we switched between laptop and desktop systems"); + harddrake::autoconf::laptop($isLaptop); +} + +if (find { $_->{driver} =~ /Card:NVIDIA/ } detect_devices::probeall()) { + if (find { -e join('', "/lib/modules/", c::kernel_version(), "/kernel/drivers/$_") } map { ("extra/$_", "video/$_", "char/$_", "char/drm/$_") } qw(NVdriver nvidia.o nvidia.o.gz), map { $_, "$_.gz" } qw(nvidia.ko nvidia71xx.ko nvidia96xx.ko nvidia97xx.ko)) { + # do not automatically switch from nv to nvidia (in order to handle + # cases where nvidia module crashes the system): + # + # substInFile { + # log::explanations("switch XFree86 driver from nv to nvidia") if /Driver "nv"/; + # s!Driver "nv.*"!Driver "nvidia"!g; + # s!#*( Load.*glx)!\1!g; + # } $_ foreach "/etc/X11/XF86Config-4", "/etc/X11/XF86Config"; + } else { + substInFile { + log::explanations("switch X.org driver from nvidia to nv") if /Driver "nv.+"/; + s!Driver "nv.*"!Driver "nv"!g; + } $_ foreach grep { -e $_ } "/etc/X11/XF86Config-4", "/etc/X11/XF86Config", "/etc/X11/xorg.conf"; + + require Xconfig::card; + Xconfig::card::libgl_config_and_more({ Driver => 'nv' }); + } +} + +if (find { $_->{driver} =~ /ATI Radeon/ } detect_devices::probeall()) { + if (find { -e join('', "/lib/modules/", c::kernel_version(), "/kernel/drivers/$_") } map { ("extra/$_", "video/$_", "char/$_", "char/drm/$_") } map { $_, "$_.gz" } qw(fglrx.ko)) { + # do not automatically switch from nv to nvidia (in order to handle + # cases where nvidia module crashes the system): + # + # substInFile { + # log::explanations("switch XFree86 driver from nv to nvidia") if /Driver "nv"/; + # s!Driver "nv.*"!Driver "nvidia"!g; + # s!#*( Load.*glx)!\1!g; + # } $_ foreach "/etc/X11/XF86Config-4", "/etc/X11/XF86Config"; + } else { + require Xconfig::card; + my @cards = Xconfig::card::probe(); + my $driver = $cards[0]{Driver}; + substInFile { + log::explanations("switch X.org driver from fglrx to ati") if /Driver "nv.+"/; + s!Driver "fglrx"!Driver "$driver"!g; + } $_ foreach grep { -e $_ } "/etc/X11/XF86Config-4", "/etc/X11/XF86Config", "/etc/X11/xorg.conf"; + + require Xconfig::card; + Xconfig::card::libgl_config_and_more({ Driver => 'fglrx' }); + } +} + +my $is_globetrotter = -f '/usr/sbin/mdkmove'; + +# first run ? if not read old hw config +my $previous_config; + +if (-f $last_boot_config && -s $last_boot_config) { + eval { $previous_config = Storable::retrieve($last_boot_config) }; + log::explanations("resetting previous hardware file ($@)") if $@; +} + +$previous_config ||= {}; + +$previous_config = $$previous_config if ref($previous_config) !~ /HASH/; +my (%config, $wait); +my $in; +my $splash = -f '/proc/splash'; +my $splash_was_silent = cat_('/proc/splash') =~ /, silent : on/; + +# For each hw, class, detect device, compare and offer to reconfigure if needed +foreach my $hw_class (@harddrake::data::tree) { + my ($Ident, $item, $configurator, $detector, $do_it) = @$hw_class{qw(class string configurator detector checked_on_boot)}; + next if member($cfg{"DETECT_$Ident"}, qw(NO no)); + + $configurator ||= $hw_class->{configurator}; + + next unless $do_it ^ $invert_do_it; + # No detector ? (should never happen but who know ?) + ref($detector) eq 'CODE' or next; + + my %ID = map { + my $i = $_; + my $id = defined $i->{device} ? $i->{device} : join(':', map { $i->{$_} } qw(vendor id subvendor subid)); + $id => $i; + } eval { $detector->({}) }; + $config{$Ident} = \%ID; + next if !$is_globetrotter && !$force && is_empty_hash_ref($previous_config); # do not fsck on first run but if --force + + my $oldconfig = $force ? {} : $previous_config->{$Ident}; + + my $msg; + my @was_removed = difference2([ keys %$oldconfig ], [ keys %ID ]); + if (@was_removed) { + $msg .= N("Some devices in the \"%s\" hardware class were removed:\n", $item) . + join('', map { N("- %s was removed\n", harddrake::data::custom_id($oldconfig->{$_}, $item)) } @was_removed) . "\n"; + } + my @added = difference2([ keys %ID ], [ keys %$oldconfig ]); + $msg .= N("Some devices were added: %s\n", $item) if @added; + $msg .= N("- %s was added\n", harddrake::data::custom_id($ID{$_}, $item)) foreach @added; + log::explanations("removed $Ident: " . harddrake::data::custom_id($oldconfig->{$_}, $item)) foreach @was_removed; + log::explanations("added $Ident: " . harddrake::data::custom_id($ID{$_}, $item)) foreach @added; + + if ($Ident eq 'FIREWIRE_CONTROLLER' && any { $_->{driver} eq 'ohci1394' } @ID{@added}) { + modules::load_and_configure($modules_conf, 'ohci1394'); + $modules_conf->write; + } + + @added || @was_removed or $cfg{"DETECT_$Ident"} ne 'force' and next; + + next if $Ident eq 'MOUSE' && $curr_kernel ne $previous_kernel_config{KERNEL} && $cfg{"DETECT_$Ident"} ne 'force'; + + my @configurator_pool; + if (harddrake::data::is_removable($Ident)) { + foreach my $device (@ID{@added}) { + push @configurator_pool, harddrake::data::set_removable_auto_configurator($Ident, $device); + } + foreach my $device (@$oldconfig{@was_removed}) { + push @configurator_pool, harddrake::data::set_removable_remover($Ident, $device); + } + } else { + @configurator_pool = $configurator; + } + if ($Ident eq "AUDIO") { + # automatic sound slots configuration + rm_rf("/etc/asound.state") if -e "/etc/asound.state"; + harddrake::sound::configure_sound_slots($modules_conf); + next; + } elsif ($Ident eq "ETHERNET") { + $modules_conf->remove_alias_regexp('^(wlan|eth)[0-9]*$'); + modules::load_category($modules_conf, 'network/main|gigabit|usb|wireless|firewire|pcmcia'); + require network::connection::ethernet; + network::connection::ethernet::configure_eth_aliases($modules_conf); + require network::rfswitch; + network::rfswitch::configure(); + require network::shorewall; + network::shorewall::update_interfaces_list(); + $modules_conf->write; + next; + } elsif (member($Ident, qw(ATA_STORAGE CARD_READER RAID_STORAGE SATA_STORAGE SCSI_CONTROLLER))) { + # set scsi_hostadapterr in modprobe.conf: + modules::load_category($modules_conf, 'disk/' . { + ATA_STORAGE => 'ide', + SATA_STORAGE => 'sata', + SCSI_CONTROLLER => 'scsi', + RAID_STORAGE => 'hardware_raid', + CARD_READER => 'card_reader' + }->{$Ident}); + $modules_conf->write; + next; + } elsif (member($Ident, qw(AGP DVB TV))) { + my @old_drivers = uniq(map { $_->{driver} } values %$oldconfig); + my @new_drivers = uniq(map { $_->{driver} } values %ID); + # load DVB & TV drivers (eg: for One), not for AGP (done by X): + modules::load_category($modules_conf, 'multimedia/' . lc($Ident)) if member($Ident, qw(DVB TV)); + $modules_conf->remove_module(difference2(\@old_drivers, \@new_drivers)); + # add agpgart and the like modules to modprobe.preload if needed: + $modules_conf->write; + modules::load(difference2(\@new_drivers, \@old_drivers)); + next; + } elsif ($Ident eq "BLUETOOTH") { + harddrake::autoconf::bluetooth(scalar keys %ID); + } elsif ($Ident eq "PCMCIA_CONTROLLER") { + harddrake::autoconf::pcmcia(keys %ID ? first(values(%ID))->{driver} : ''); + } elsif ($Ident eq "USB_CONTROLLER") { + # nearly useless (only mkinitrd uses it): + modules::load_category($modules_conf, 'bus/usb'); + $modules_conf->write; + } elsif ($Ident eq "VIDEO") { + # explicitely NOT read the existing config (eg: new profile with globetrotter) + harddrake::autoconf::xconf($modules_conf, {}); + next; + } elsif ($Ident eq "MOUSE") { + harddrake::autoconf::mouse_conf($modules_conf); + next; + } elsif ($Ident eq "CPU") { + harddrake::autoconf::cpufreq(); + } + + next if $is_globetrotter && !$hw_class->{automatic}; + next unless $configurator_pool[0]; + if (ref($configurator) ne 'CODE' && !-x first(split /\s+/, $configurator_pool[0])) { + log::explanations(qw(skip $Ident configuration since "$configurator" is not executable)); + next; + } + my ($pid, $no, $res); + $hw_class->{automatic} ||= ref($configurator) eq 'CODE'; + + if (!$hw_class->{automatic}) { + $SIG{ALRM} = sub { $no = 1; kill 15, $pid }; + unless ($pid = fork()) { + $splash and eval { output('/proc/splash', 'verbose') } and $splash = 0; + exec("/usr/share/harddrake/confirm", $Ident, $timeout, $msg); + } + alarm($timeout); + wait(); + $res = $?; + alarm(0); + } else { + $res = 1; + } + if (ref($configurator) eq 'CODE') { + eval { $configurator->() }; + log::explanations(qw(cannot run "$configurator": $@)) if $@; + } elsif (!$no && $res) { + foreach my $program (@configurator_pool) { + if (fork()) { + wait(); + } else { + log::explanations(qq(run "$program")); + exec("$program 2>/dev/null") or do { + log::explanations(qq(cannot run "$program")); + require POSIX; + POSIX::_exit(); + }; + } + } + } + if (!$hw_class->{automatic}) { + require interactive; + undef $wait; + $in ||= interactive->vnew; + $wait = $in->wait_message(N("Please wait"), N("Hardware probing in progress")); + } + +} + +# output new hw config +log::explanations("created file $last_boot_config"); +Storable::store(\%config, $last_boot_config); + +# restore bootsplash mode +$splash_was_silent and eval { output('/proc/splash', 'silent') }; + + +$in->exit(0) if $in; |
