/[soft]/drakx/trunk/perl-install/standalone/service_harddrake
ViewVC logotype

Contents of /drakx/trunk/perl-install/standalone/service_harddrake

Parent Directory Parent Directory | Revision Log Revision Log


Revision 916 - (show annotations) (download)
Sun Apr 17 14:33:45 2011 UTC (13 years ago) by anssi
File size: 14836 byte(s)
service_harddrake: Adapt from bootsplash to plymouth.
1 #!/usr/bin/perl
2
3 use lib qw(/usr/lib/libDrakX);
4
5 # prevent firing up drakbug (doesn't work w/o X11):
6 BEGIN { $ENV{DISABLE_DRAKBUG} = 1 }
7
8 use strict;
9 use diagnostics;
10
11 # fix translating reasons for 2nd stage warning
12 use lang;
13 BEGIN {
14 my $locale = lang::read($>);
15 lang::set($locale);
16 }
17
18 use standalone; #- warning, standalone must be loaded very first, for 'explanations'
19 use c;
20 use common;
21 use interactive;
22 use detect_devices;
23 use harddrake::data;
24 use harddrake::autoconf;
25 use harddrake::sound;
26 use Xconfig::card;
27 use modules;
28 use Storable qw(store retrieve);
29
30
31 my $force = member('--force', @ARGV);
32
33 my $invert_do_it = $ARGV[0] eq 'X11' ? 1 : 0;
34 my ($hw_sysconfdir, $timeout) = ("/etc/sysconfig/harddrake2", $invert_do_it ? 600 : 25);
35 my $last_boot_config = "$hw_sysconfdir/previous_hw";
36
37 $last_boot_config .= '_X11' if $invert_do_it;
38
39 # first run ? if not read old hw config
40 my $previous_config;
41 if (-f $last_boot_config && -s $last_boot_config) {
42 eval { $previous_config = Storable::retrieve($last_boot_config) };
43 log::explanations("resetting previous hardware file ($@)") if $@;
44 }
45 $previous_config ||= {};
46 $previous_config = $$previous_config if ref($previous_config) !~ /HASH/;
47 my $first_run = is_empty_hash_ref($previous_config);
48
49 my $modules_conf = modules::any_conf->read;
50
51 my $isLaptop = detect_devices::isLaptop();
52 my $curr_kernel = c::kernel_version();
53 my ($kernel_major) = $curr_kernel =~ /^(\d+\.\d+)/;
54
55 my %previous_kernel_config = getVarsFromSh("$hw_sysconfdir/kernel");
56 my %previous_xorg_config = getVarsFromSh("$hw_sysconfdir/xorg");
57 setVarsInSh("$hw_sysconfdir/kernel", { KERNEL => $kernel_major, IS_LAPTOP => bool2text($isLaptop) });
58 my %cfg = getVarsFromSh("$hw_sysconfdir/service.conf");
59
60 # default to 'yes' on upgrade:
61 $cfg{AUTORECONFIGURE_RIGHT_XORG_DRIVER} = 'yes' if !exists $cfg{AUTORECONFIGURE_RIGHT_XORG_DRIVER};
62
63 # autoreconfigure laptop-dependent services when switching from laptop to desktop, and vice versa
64 if (!exists $previous_kernel_config{IS_LAPTOP} || $force || $isLaptop != text2bool($previous_kernel_config{IS_LAPTOP})) {
65 log::explanations("Autoconfiguring laptop tools since we switched between laptop and desktop systems");
66 harddrake::autoconf::laptop($isLaptop);
67 }
68
69 my $known_kernels = "$hw_sysconfdir/kernels";
70 if (!member($curr_kernel, chomp_(cat_($known_kernels)))) {
71 harddrake::autoconf::fix_aliases($modules_conf) if !$first_run;
72 append_to_file($known_kernels, "$curr_kernel\n");
73 }
74
75 sub get_xorg_driver() {
76 my $x = Xconfig::xfree->read;
77 if ($x) {
78 my ($dev_section) = grep { $_->{name} eq 'Device' } @{$x->{raw}};
79 $dev_section && $dev_section->{l}{Driver}{val};
80 }
81 }
82
83 sub schedule_warn_about_switch {
84 my ($reason) = @_;
85 output('/var/run/harddrake-notify-x11-free-driver-switch', $reason);
86 }
87
88 my $lib = arch() =~ /x86_64/ ? "lib64" : "lib";
89
90 sub find_xorg_driver {
91 my ($new_driver) = @_;
92 # nvidia driver has special place:
93 -e "/usr/$lib/xorg/modules/drivers/${new_driver}_drv.so"
94 || -e "/usr/$lib/xorg/extra-modules/${new_driver}_drv.so";
95 }
96
97 sub switch_x_driver {
98 my ($old_driver, $new_driver, $reason) = @_;
99 if (!find_xorg_driver($new_driver)) {
100 log::explanations("would switch X.org driver from '$old_driver' to '$new_driver' ($reason); but new driver is not installed");
101 return;
102 }
103 cp_af('/etc/X11/xorg.conf', "/etc/X11/xorg.conf.mga$^T");
104 substInFile { s!Driver "($old_driver)"!Driver "$new_driver"!g } '/etc/X11/xorg.conf';
105 log::explanations("switch X.org driver from '$old_driver' to '$new_driver' ($reason)");
106 Xconfig::card::libgl_config_and_more({ Driver => $new_driver });
107 }
108
109 sub should_reconfigure_x_driver {
110 my ($card_data, $device, $current_driver) = @_;
111 my $reason;
112 my $reconfigure;
113 my $new_key = $card_data->{Driver} . $card_data->{Driver2};
114 setVarsInSh("$hw_sysconfdir/xorg", { XORG_DRV => $new_key });
115 # auto reconfigure x11 only on first time default driver have changed:
116 if ($previous_xorg_config{XORG_DRV} ne $new_key) {
117 if (!member($current_driver, $card_data->{Driver}, $card_data->{Driver2}, 'fbdev', 'vesa')) {
118 $reason = N("The graphic card '%s' is no more supported by the '%s' driver",
119 $device->{description}, $current_driver);
120 $reconfigure = 1;
121 }
122 } elsif ((stat('/etc/X11/xorg.conf'))[9] < (stat('/etc/product.id'))[9]) {
123 # when switching to a new release (product.id is newer than xorg.conf),
124 # regenerate xorg.conf even if the driver used is vesa or fbdev, this
125 # way we handle switches like "no driver for the card in older releases
126 # but good driver in new release", see bug #53753
127 if (!member($current_driver, $card_data->{Driver}, $card_data->{Driver2})) {
128 $reason = N("New release, reconfiguring X for %s", $device->{description});
129 $reconfigure = 1;
130 }
131 }
132
133 ($reconfigure, $reason);
134 }
135
136 my @cards = (
137 {
138 ldetect_driver_regexp => 'Card:NVIDIA',
139 xorg_driver_regexp => 'nv.+',
140 module_names => [ qw(NVdriver nvidia.o nvidia.ko nvidia71xx.ko nvidia96xx.ko nvidia97xx.ko nvidia173.ko nvidia-current.ko) ]
141 },
142 {
143 ldetect_driver_regexp => 'Card:ATI Radeon',
144 xorg_driver_regexp => 'fglrx',
145 module_names => [ qw(fglrx.ko fglrx-hd2000.ko) ]
146 }
147 );
148
149
150 my @devices;
151 @devices = grep { $_->{driver} =~ /^Card:/ } detect_devices::probeall()
152 if -f '/etc/X11/xorg.conf';
153
154 # do not auto reconfigure if more than one graphic card:
155 $cfg{AUTORECONFIGURE_RIGHT_XORG_DRIVER} = 'no' if scalar(@devices) > 1;
156
157 foreach my $device (@devices) {
158 next if !text2bool($cfg{AUTORECONFIGURE_RIGHT_XORG_DRIVER});
159
160 my $id = $device->{driver} =~ /Card:(.*)/ && $1;
161 my $card_data = Xconfig::card::readCardsDB("/usr/share/ldetect-lst/Cards+")->{$id};
162 my $current_driver = get_xorg_driver();
163
164 # nvidia proprietary driver in ldetect-lst can be 'nvidia173', 'nvidia-current', ...
165 # but really is just 'nvidia' in xorg.conf:
166 $card_data->{Driver2} =~ s/(nvidia).*/$1/;
167
168 # auto reconfigure x11 only on first time default driver have changed:
169 my ($should_reconfigure, $reason) = should_reconfigure_x_driver($card_data, $device, $current_driver);
170 if ($should_reconfigure) {
171 switch_x_driver($current_driver, $card_data->{Driver}, $reason);
172 schedule_warn_about_switch($reason) if any { $current_driver =~ $_->{xorg_driver_regexp} } @cards;
173 # Update $current_driver with the new one
174 $current_driver = $card_data->{Driver};
175 }
176
177 # nv->nouveau or non_kms_nouveau->kms_nouveau can't have "Disable dri"!
178 if ($current_driver eq "nouveau") {
179 my $raw_x = Xconfig::xfree->read;
180 if ($raw_x) {
181 if (member("dri", $raw_x->get_disabled_modules)) {
182 $raw_x->remove_disable_module("dri");
183 $raw_x->write;
184 }
185 }
186 }
187 }
188
189
190 foreach my $card (@cards) {
191 my $device = find { $_->{driver} =~ /$card->{ldetect_driver_regexp}/ } @devices;
192 next if !$device;
193
194 if (find { -e join('', "/lib/modules/", c::kernel_version(), $_) }
195 map { ("/dkms/$_", "/dkms-binary/$_", "/kernel/$_") } map { "/drivers/$_" } map { ("extra/$_", "video/$_", "char/$_", "char/drm/$_") } map { $_, "$_.gz" } @{$card->{module_names}}) {
196
197 # do not automatically switch from nv to nvidia (in order to handle
198 # cases where nvidia module crashes the system):
199 #
200 # substInFile {
201 # log::explanations("switch XFree86 driver from nv to nvidia") if /Driver "nv"/;
202 # s!Driver "nv.*"!Driver "nvidia"!g;
203 # s!#*( Load.*glx)!\1!g;
204 # } $_ foreach "/etc/X11/XF86Config-4", "/etc/X11/XF86Config";
205 } else {
206 my @cards = Xconfig::card::probe();
207 my $driver = $cards[0]{Driver};
208 my $old_driver = cat_('/etc/X11/xorg.conf') =~ /Driver "($card->{xorg_driver_regexp})"/ && $1;
209 if ($old_driver) {
210 my $reason = N("The proprietary kernel driver was not found for '%s' X.org driver",
211 $old_driver);
212 switch_x_driver($card->{xorg_driver_regexp}, $driver, $reason);
213 schedule_warn_about_switch($reason);
214 }
215 }
216 }
217
218 my $is_globetrotter = -f '/usr/sbin/mdkmove';
219
220 my (%config, $wait);
221 my $in;
222 my $plymouth = -x '/bin/plymouth';
223
224 # For each hw, class, detect device, compare and offer to reconfigure if needed
225 foreach my $hw_class (@harddrake::data::tree) {
226 my ($Ident, $item, $configurator, $detector, $do_it) = @$hw_class{qw(class string configurator detector checked_on_boot)};
227 next if member($cfg{"DETECT_$Ident"}, qw(NO no));
228
229 $configurator ||= $hw_class->{configurator};
230
231 next unless $do_it ^ $invert_do_it;
232 # No detector ? (should never happen but who know ?)
233 ref($detector) eq 'CODE' or next;
234
235 my %ID = map {
236 my $i = $_;
237 my $id = defined $i->{device} ? $i->{device} : join(':', map { $i->{$_} } qw(vendor id subvendor subid));
238 $id => $i;
239 } eval { $detector->({}) };
240 $config{$Ident} = \%ID;
241 next if !$is_globetrotter && !$force && $first_run; # do not fsck on first run but if --force
242
243 my $oldconfig = $force ? {} : $previous_config->{$Ident};
244
245 my $msg;
246 my @was_removed = difference2([ keys %$oldconfig ], [ keys %ID ]);
247 if (@was_removed) {
248 $msg .= N("Some devices in the \"%s\" hardware class were removed:\n", $item) .
249 join('', map { N("- %s was removed\n", harddrake::data::custom_id($oldconfig->{$_}, $item)) } @was_removed) . "\n";
250 }
251 my @added = difference2([ keys %ID ], [ keys %$oldconfig ]);
252 $msg .= N("Some devices were added: %s\n", $item) if @added;
253 $msg .= N("- %s was added\n", harddrake::data::custom_id($ID{$_}, $item)) foreach @added;
254 log::explanations("removed $Ident: " . harddrake::data::custom_id($oldconfig->{$_}, $item)) foreach @was_removed;
255 log::explanations("added $Ident: " . harddrake::data::custom_id($ID{$_}, $item)) foreach @added;
256
257 if ($Ident eq 'FIREWIRE_CONTROLLER' && any { $_->{driver} eq 'ohci1394' } @ID{@added}) {
258 modules::load_and_configure($modules_conf, 'ohci1394');
259 $modules_conf->write;
260 }
261
262 @added || @was_removed or $cfg{"DETECT_$Ident"} ne 'force' and next;
263
264 next if $Ident eq 'MOUSE' && $kernel_major ne $previous_kernel_config{KERNEL} && $cfg{"DETECT_$Ident"} ne 'force';
265
266 my @configurator_pool = $configurator;
267
268 if ($Ident eq "AUDIO") {
269 # automatic sound slots configuration
270 rm_rf("/etc/asound.state") if -e "/etc/asound.state";
271 harddrake::sound::configure_sound_slots($modules_conf);
272 next;
273 } elsif ($Ident eq "ETHERNET") {
274 $modules_conf->remove_alias_regexp('^(wlan|eth)[0-9]*$');
275 modules::load_category($modules_conf, 'network/main|gigabit|usb|wireless|firewire|pcmcia');
276 require network::connection::ethernet;
277 network::connection::ethernet::configure_eth_aliases($modules_conf);
278 require network::rfswitch;
279 network::rfswitch::configure();
280 require network::shorewall;
281 network::shorewall::update_interfaces_list();
282 $modules_conf->write;
283 next;
284 } elsif (member($Ident, qw(ATA_STORAGE CARD_READER RAID_STORAGE SATA_STORAGE SCSI_CONTROLLER))) {
285 # set scsi_hostadapter in modprobe.conf:
286 modules::load_category($modules_conf, 'disk/' . {
287 ATA_STORAGE => 'ide',
288 SATA_STORAGE => 'sata',
289 SCSI_CONTROLLER => 'scsi',
290 RAID_STORAGE => 'hardware_raid',
291 CARD_READER => 'card_reader'
292 }->{$Ident});
293 $modules_conf->write;
294 next;
295 } elsif (member($Ident, qw(AGP DVB TV))) {
296 my @old_drivers = uniq(map { $_->{driver} } values %$oldconfig);
297 my @new_drivers = uniq(map { $_->{driver} } values %ID);
298 # load DVB & TV drivers (eg: for One), not for AGP (done by X):
299 modules::load_category($modules_conf, 'multimedia/' . lc($Ident)) if member($Ident, qw(DVB TV));
300 $modules_conf->remove_module(difference2(\@old_drivers, \@new_drivers));
301 # add agpgart and the like modules to modprobe.preload if needed:
302 $modules_conf->write;
303 foreach (difference2(\@new_drivers, \@old_drivers)) {
304 eval { modules::load($_) };
305 warn "warning: $@" if $@;
306 }
307 next;
308 } elsif ($Ident eq "BLUETOOTH") {
309 harddrake::autoconf::bluetooth(scalar keys %ID);
310 } elsif ($Ident eq "PCMCIA_CONTROLLER") {
311 harddrake::autoconf::pcmcia(keys %ID ? first(values(%ID))->{driver} : '');
312 } elsif ($Ident eq "USB_CONTROLLER") {
313 # nearly useless (only mkinitrd uses it):
314 modules::load_category($modules_conf, 'bus/usb');
315 $modules_conf->write;
316 } elsif ($Ident eq "VIDEO") {
317 # explicitely NOT read the existing config (eg: new profile with globetrotter)
318 harddrake::autoconf::xconf($modules_conf, {}, member($cfg{SETUP_FB}, qw(NO no)), $cfg{RESOLUTION_WANTED});
319 next;
320 } elsif ($Ident eq "MOUSE") {
321 harddrake::autoconf::mouse_conf($modules_conf);
322 next;
323 } elsif ($Ident eq "CPU") {
324 harddrake::autoconf::cpufreq();
325 } elsif ($Ident eq "FLOPPY") {
326 harddrake::autoconf::floppy();
327 }
328
329 next if $is_globetrotter && !$hw_class->{automatic};
330 next unless $configurator_pool[0];
331 if (ref($configurator) ne 'CODE' && !-x first(split /\s+/, $configurator_pool[0])) {
332 log::explanations(qw(skip $Ident configuration since "$configurator" is not executable));
333 next;
334 }
335 my ($pid, $no, $res);
336 $hw_class->{automatic} ||= ref($configurator) eq 'CODE';
337
338 if (!$hw_class->{automatic}) {
339 $SIG{ALRM} = sub { $no = 1; kill 15, $pid };
340 unless ($pid = fork()) {
341 $plymouth and system('plymouth', 'hide-splash');
342 exec("/usr/share/harddrake/confirm", $Ident, $timeout, $msg);
343 }
344 alarm($timeout);
345 wait();
346 $res = $?;
347 alarm(0);
348 } else {
349 $res = 1;
350 }
351 if (ref($configurator) eq 'CODE') {
352 eval { $configurator->() };
353 log::explanations(qw(cannot run "$configurator": $@)) if $@;
354 } elsif (!$no && $res) {
355 foreach my $program (@configurator_pool) {
356 if (fork()) {
357 wait();
358 } else {
359 log::explanations(qq(run "$program"));
360 exec("$program 2>/dev/null") or do {
361 log::explanations(qq(cannot run "$program"));
362 require POSIX;
363 POSIX::_exit();
364 };
365 }
366 }
367 }
368 if (!$hw_class->{automatic}) {
369 require interactive;
370 undef $wait;
371 $in ||= interactive->vnew;
372 $wait = $in->wait_message(N("Please wait"), N("Hardware probing in progress"));
373 }
374
375 }
376
377 # output new hw config
378 log::explanations("created file $last_boot_config");
379 Storable::store(\%config, $last_boot_config);
380
381 $in->exit(0) if $in;

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.30