summaryrefslogtreecommitdiffstats
path: root/kernel/modules.pl
blob: 575318c299d84e8166e995a3f4605a35dd9ad001 (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
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(acenic),
    qw(aironet4500_card com20020-pci hamachi starfire winbond-840),

    if_(arch() =~ /alpha|ppc/, qw(sb1000)),
    qw(iph5526),

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

  '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 dc395x_trm dmx3191d qla1280 BusLogic fdomain),
    qw(pci2220i eata eata_pio eata_dma),
    'aic7xxx_old', 'qlogicisp',
    'dtc',
  ],
  'disk/sata' => [
    qw(ahci ata_piix sata_nv sata_promise sata_sil sata_sis sata_svw sata_sx4 sata_uli sata_via sata_vsc sx8),
  ],

  'disk/hardware_raid' => [
    qw(i2o_block qla2200 qla2300 cpqfc DAC960 gdth pdc-ultra mptscsih),
  ],
);

#- 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|loopback disk/cdrom|raw|pcmcia bus/pcmcia',
    cdrom   => 'fs/cdrom|loopback disk/cdrom|raw|scsi',
    network  => 'bus/usb|usb_keyboard|pcmcia disk/raw|usb',
    network_drivers => 'fs/network|loopback network/main|pcmcia|usb|raw|gigabit',
    ka => 'fs/network network/main|raw|gigabit',
    all     => 'fs/cdrom disk/cdrom|raw bus/usb|usb_keyboard disk/usb|scsi fs/loopback|local bus/pcmcia disk/ide|pcmcia|sata|hardware_raid fs/network network/main|pcmcia|usb|raw|gigabit|wireless|tokenring 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(" ", sort @{$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;
	    print STDERR "usbtable modules not listed $_: ", join(" ", sort @{$not_listed{$_}}), "\n" foreach sort keys %not_listed;
	}
    }

    exit $error;
}