summaryrefslogtreecommitdiffstats
path: root/kernel/modules.pl
blob: b8207087a672f6fcbeda46db7cdeab89d430e9b2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
use strict;


BEGIN {
    #- for testing purpose
    (my $f = __FILE__) =~ s|/[^/]*$||;
    push @INC, $f;
}

use MDK::Common;
use list_modules;

#- seldom used modules
#- we don't bother making a special floppy for those
my %modules_only_for_all_img = (

  'network/main' => [
    qw(olympic acenic),
    qw(aironet4500_card com20020-pci hamachi starfire winbond-840),

    # token ring
    qw(tmspci ibmtr abyss),

    if_(arch() =~ /x86_64/, qw(orinoco_plx)), # don't support laptop for now
    if_(arch() =~ /x86_64/, qw(hp100 epic100)), # old (nico)
    if_(arch() =~ /alpha|ppc/, qw(sb1000)),
    qw(iph5526),

    qw(ac3200 at1700 atp ni5010 ni52 ni65),  #- unused from Jeff
  ],

  'bus/pcmcia' => [
    if_(arch() =~ /x86_64/, qw(pcmcia_core ds tcic yenta_socket)), # don't support laptop for now
    if_(arch() =~ /x86_64/, qw(i82092 i82365)), # doco says "older laptops"
  ],

  'disk/scsi' => [
    # ISA cards:
    qw(NCR53c406a aha152x psi240i qlogicfas qlogicfc wd7000 sim710 t128 ultrastor), '53c7,8xx',
    qw(qla2x00 in2000 pas16 a100u2w seagate g_NCR5380),
    if_(arch() =~ /x86_64/, qw(53c7,8xx nsp32 initio advansys atp870u)), #- old
    qw(AM53C974), # deprecated by tmscsim
    qw(u14-34f), #- duplicate from ultrastor.o
    #- still used, keeping them: qw(aha1542 sym53c416),
    qw(lpfcdd), #- HUGE!!

    qw(dc395x_trm mptscsih BusLogic fdomain),
    qw(pci2220i eata eata_pio eata_dma),
    'aic7xxx_old', 'qlogicisp',
    'dtc',
  ],

  'disk/hardware_raid' => [
    if_(arch() =~ /x86_64/, qw(ataraid)), #- old
    qw(i2o_block qla2200 qla2300 cpqfc DAC960 gdth pdc-ultra),
  ],
);

#- modules that will only be available in stage2
#-   those modules are NOT in all.img, network.img...
#-   there should only be modules that can't be used on stage1
#-   completly unused modules should be removed directly from the kernel
#-     (and so be removed from stage2 too)
my %modules_removed_from_stage1 = (
  'network/main' => [
     'plip'
  ],

  'disk/hardware_raid' => [
    qw(imm ppa),
  ],
);

my @modules_always_on_stage1 = qw(floppy);


sub flatten_and_check {
    my ($h) = @_;
    map { 
	my $category = $_;
	my @l = @{$h->{$category}};
	if (my @bad = difference2(\@l, [ category2modules($category) ])) {
	    foreach (@bad) {
		if (my $cat = module2category($_)) {
		    warn "ERROR in modules.pl: module $_ is in category $cat, not in $category\n";
		} else {
		    warn "ERROR in modules.pl: unknown module $_\n";
		}
	    }
	    exit 1;
	}
	@l;
    } keys %$h;
}

my @modules_only_for_all_img    = flatten_and_check(\%modules_only_for_all_img);
my @modules_removed_from_stage1 = flatten_and_check(\%modules_removed_from_stage1);


my %images = (
    pcmcia  => 'fs/cdrom disk/cdrom|raw|pcmcia bus/pcmcia',
    cdrom   => 'fs/cdrom disk/cdrom|raw|scsi',
    network  => 'bus/usb|usb_keyboard|pcmcia disk/raw|usb',
    network_drivers => 'fs/network network/main|pcmcia|usb|raw|gigabit',
    all     => 'fs/cdrom disk/cdrom|raw bus/usb|usb_keyboard disk/usb|scsi fs/loopback|local bus/pcmcia disk/pcmcia|hardware_raid fs/network network/main|pcmcia|usb|raw|gigabit bus/firewire disk/firewire',
);

my $verbose = $ARGV[0] eq '-v' && shift;
my ($f, @para) = @ARGV;
$::{$f}->(@para);

sub image2modules {
    my ($image) = @_;
    my $l = $images{$image};

    my @modules = if_($image !~ /drivers/, @modules_always_on_stage1);
    push @modules, map { category2modules($_) } split(' ', $l);
	
    @modules = difference2(\@modules, \@modules_removed_from_stage1);

    if ($image !~ /all/) {
	@modules = difference2(\@modules, \@modules_only_for_all_img);
    }

    @modules;
}

sub remove_unneeded_modules {
    my ($kern_ver) = @_;

    #- need creating a first time the modules.dep for all modules
    #- it will be redone in make_modules_dep when unneeded modules are removed
    make_modules_dep($kern_ver);
    load_dependencies("all.kernels/$kern_ver/modules.dep");

    my $ext = module_extension($kern_ver);

    my @all = list_modules::all_modules();
    my @all_with_deps = map { dependencies_closure($_) } @all;
    my %wanted_modules = map {; "$_.$ext" => 1 } @all_with_deps;
    foreach (all("all.kernels/$kern_ver/modules")) {
	$wanted_modules{$_} or unlink "all.kernels/$kern_ver/modules/$_";	
    }
}

sub make_modules_per_image {
    my ($kern_ver) = @_;

    make_modules_dep($kern_ver);
    load_dependencies("all.kernels/$kern_ver/modules.dep");

    my $ext = module_extension($kern_ver);

    foreach my $image (keys %images) {
	my @modules_with_deps = uniq(map { dependencies_closure($_) } image2modules($image));
	my @l = map { "$_.$ext" } @modules_with_deps;

	my $dir = "all.kernels/$kern_ver/modules";
	@l = grep { -e "$dir/$_" } @l;

	if ($image =~ /all/) {
	    system("cd $dir ; tar cf ../${image}_modules.tar @l") == 0 or die "tar failed\n";
	} else {
	    my $gi_base_dir = chomp_(`pwd`) . '/..';
	    system("cd $dir ; $gi_base_dir/mdk-stage1/mar/mar -c ../${image}_modules.mar @l") == 0 or die "mar failed\n";
	}
    }
}

sub make_modules_dep {
    my ($kern_ver) = @_;

    my @l =
      kernel_is_26($kern_ver) ?
	cat_("all.kernels/$kern_ver/lib/modules/$kern_ver/modules.dep") :
	`/sbin/depmod-24 -F all.kernels/$kern_ver/boot/System.map-$kern_ver -e *.o | perl -pe 's/\\\n//'`;

    @l = map {
	if (/(\S+):\s+(.*)/) {
	    my ($module, @deps) = map { m!.*/(.*)\.k?o(\.gz)$! && $1 } $1, split(' ', $2);
	    if (member($module, 'plip', 'ppa', 'imm')) {
		@deps = map { $_ eq 'parport' ? 'parport_pc' : $_ } @deps;
	    } elsif ($module eq 'vfat') {
		push @deps, 'nls_cp437', 'nls_iso8859-1';
	    }
	    if_(@deps, join(' ', "$module:", @deps));
	} else {
	    ();
	}
    } @l;

    output("all.kernels/$kern_ver/modules.dep", map { "$_\n" } @l);
}

sub make_modules_description {
    my ($kern_ver) = @_;
    my $ext = module_extension($kern_ver);
    my $dir = "all.kernels/$kern_ver/modules";

    my @l;
    if (kernel_is_26(`uname -r`)) { #- modinfo behaves differently depending on the build kernel used
	my $name;
	@l = map {
	    $name = $1 if m!^filename:\s*(.*)\.$ext!;
	    if_($name && /^description:\s*(.*)/, "$name\t$1");
	} `cd $dir ; /sbin/modinfo *.$ext`;
    } else {
	@l = map {
	    if_(/(.*?)\.$ext "(.*)"/, "$1\t$2\n");
	} `cd $dir ; /sbin/modinfo-24 -f '%{filename} %{description}\n' *.$ext`;
    }
    output("modules.description", @l);
}

sub pci_modules4stage1 {
    my ($category) = @_;
    my @modules = difference2([ category2modules($category) ], \@modules_removed_from_stage1);
    print "$_\n" foreach uniq(map { dependencies_closure($_) } @modules);
}

sub check() {
    my $error;
    my %listed;
    while (my ($t1, $l) = each %list_modules::l) {
	while (my ($t2, $l) = each %$l) {
	    ref $l or die "bad $l in $t1/$t2";
	    foreach (@$l) {
		$listed{$_} = "$t1/$t2"; 
	    }
	}
    }

    my %module2category;
    my %deprecated_modules = %listed;
    my $not_listed = sub {
	my ($msg, $verbose, @l) = @_;
	my %not_listed;
	foreach (@l) {
	    my ($mod) = m|([^/]*)\.k?o(\.gz)?$| or next;
	    delete $deprecated_modules{$mod};
	    next if $listed{$mod};
	    s|.*?mdk(BOOT)?/||;
	    s|kernel/||; s|drivers/||; s|3rdparty/||;
	    $_ = dirname $_;
	    $_ = dirname $_ if $mod eq basename($_);
	    $module2category{$mod} = $_;
	    push @{$not_listed{$_}}, $mod;
	}
	if ($verbose) {
	    print "$msg $_: ", join(" ", @{$not_listed{$_}}), "\n" foreach sort keys %not_listed;
	}
    };
    $not_listed->('NOT LISTED', 1, `cd all.kernels/2.6* ; find -name "*.k?o" -o -name "*.k?o.gz"`);
    $not_listed->('not listed', $verbose, `rpm -qpl /RPMS/kernel-2.6*`);
    if (%deprecated_modules) {
	my %per_cat;
	push @{$per_cat{$listed{$_}}}, $_ foreach keys %deprecated_modules;
	foreach my $cat (sort keys %per_cat) {
	    print "bad/old modules ($cat) : ", join(" ", sort @{$per_cat{$cat}}), "\n";
	}
    }

    {
	require '/usr/bin/merge2pcitable.pl';
	my $pcitable = read_pcitable("/usr/share/ldetect-lst/pcitable");
	my $usbtable = read_pcitable("/usr/share/ldetect-lst/usbtable");

	my @l1 = uniq grep { !/:/ && $_ ne 'unknown' } map { $_->[0] } values %$pcitable;
	if (my @l = difference2(\@l1, [ keys %listed ])) {
	    my %not_listed;
	    push @{$not_listed{$module2category{$_}}}, $_ foreach @l;
	    if (my $l = delete $not_listed{''}) {
		print "bad/old pcitable modules : ", join(" ", @$l), "\n";
	    }
	    print STDERR "PCITABLE MODULES NOT LISTED $_: ", join(" ", @{$not_listed{$_}}), "\n" foreach sort keys %not_listed;
	    #$error = 1;
	}

	my @l2 = uniq grep { !/:/ && $_ ne 'unknown' } map { $_->[0] } values %$usbtable;
	if (my @l = difference2(\@l2, [ keys %listed ])) {
	    my %not_listed;
	    push @{$not_listed{$module2category{$_}}}, $_ foreach @l;
	    if ($verbose) {
		print "usbtable modules not listed $_: ", join(" ", @{$not_listed{$_}}), "\n" foreach sort keys %not_listed;
	    }
	}
    }

    exit $error;
}