Blame view

scripts/kconfig/streamline_config.pl 10.2 KB
dcc60243e   Steven Rostedt   kconfig: add stre...
1
2
  #!/usr/bin/perl -w
  #
cce1dac87   Uwe Kleine-König   trivial: Fix Stev...
3
  # Copyright 2005-2009 - Steven Rostedt
dcc60243e   Steven Rostedt   kconfig: add stre...
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
  # Licensed under the terms of the GNU GPL License version 2
  #
  #  It's simple enough to figure out how this works.
  #  If not, then you can ask me at stripconfig@goodmis.org
  #
  # What it does?
  #
  #   If you have installed a Linux kernel from a distribution
  #   that turns on way too many modules than you need, and
  #   you only want the modules you use, then this program
  #   is perfect for you.
  #
  #   It gives you the ability to turn off all the modules that are
  #   not loaded on your system.
  #
  # Howto:
  #
  #  1. Boot up the kernel that you want to stream line the config on.
  #  2. Change directory to the directory holding the source of the
  #       kernel that you just booted.
  #  3. Copy the configuraton file to this directory as .config
  #  4. Have all your devices that you need modules for connected and
  #      operational (make sure that their corresponding modules are loaded)
  #  5. Run this script redirecting the output to some other file
  #       like config_strip.
  #  6. Back up your old config (if you want too).
  #  7. copy the config_strip file to .config
  #  8. Run "make oldconfig"
  #
  #  Now your kernel is ready to be built with only the modules that
  #  are loaded.
  #
  # Here's what I did with my Debian distribution.
  #
  #    cd /usr/src/linux-2.6.10
  #    cp /boot/config-2.6.10-1-686-smp .config
  #    ~/bin/streamline_config > config_strip
  #    mv .config config_sav
  #    mv config_strip .config
  #    make oldconfig
  #
cf5a189d4   hiromu   kconfig: Fix miss...
45
  use strict;
22d550ae8   Arnaud Lacombe   kconfig/streamlin...
46
  use Getopt::Long;
cf5a189d4   hiromu   kconfig: Fix miss...
47

dcc60243e   Steven Rostedt   kconfig: add stre...
48
  my $config = ".config";
dcc60243e   Steven Rostedt   kconfig: add stre...
49

cdfc47950   Steven Rostedt   kconfig: search f...
50
51
52
53
54
  my $uname = `uname -r`;
  chomp $uname;
  
  my @searchconfigs = (
  	{
a9024838d   Steven Rostedt   kconfig: make loc...
55
56
57
58
  	    "file" => ".config",
  	    "exec" => "cat",
  	},
  	{
cdfc47950   Steven Rostedt   kconfig: search f...
59
60
61
62
  	    "file" => "/proc/config.gz",
  	    "exec" => "zcat",
  	},
  	{
810b2be65   Steven Rostedt   kconfig: test for...
63
64
65
66
  	    "file" => "/boot/config-$uname",
  	    "exec" => "cat",
  	},
  	{
cdfc47950   Steven Rostedt   kconfig: search f...
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
  	    "file" => "/boot/vmlinuz-$uname",
  	    "exec" => "scripts/extract-ikconfig",
  	    "test" => "scripts/extract-ikconfig",
  	},
  	{
  	    "file" => "vmlinux",
  	    "exec" => "scripts/extract-ikconfig",
  	    "test" => "scripts/extract-ikconfig",
  	},
  	{
  	    "file" => "/lib/modules/$uname/kernel/kernel/configs.ko",
  	    "exec" => "scripts/extract-ikconfig",
  	    "test" => "scripts/extract-ikconfig",
  	},
  	{
  	    "file" => "kernel/configs.ko",
  	    "exec" => "scripts/extract-ikconfig",
  	    "test" => "scripts/extract-ikconfig",
  	},
  	{
  	    "file" => "kernel/configs.o",
  	    "exec" => "scripts/extract-ikconfig",
  	    "test" => "scripts/extract-ikconfig",
  	},
cdfc47950   Steven Rostedt   kconfig: search f...
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
  );
  
  sub find_config {
      foreach my $conf (@searchconfigs) {
  	my $file = $conf->{"file"};
  
  	next if ( ! -f "$file");
  
  	if (defined($conf->{"test"})) {
  	    `$conf->{"test"} $conf->{"file"} 2>/dev/null`;
  	    next if ($?);
  	}
  
  	my $exec = $conf->{"exec"};
  
  	print STDERR "using config: '$file'
  ";
  
  	open(CIN, "$exec $file |") || die "Failed to run $exec $file";
  	return;
      }
      die "No config file found";
  }
  
  find_config;
22d550ae8   Arnaud Lacombe   kconfig/streamlin...
116
117
118
119
120
121
  # Parse options
  my $localmodconfig = 0;
  my $localyesconfig = 0;
  
  GetOptions("localmodconfig" => \$localmodconfig,
  	   "localyesconfig" => \$localyesconfig);
463bf9000   Steven Rostedt   kconfig: Fix make...
122
123
124
  # Get the build source and top level Kconfig file (passed in)
  my $ksource = $ARGV[0];
  my $kconfig = $ARGV[1];
f597a7182   Arnaud Lacombe   kconfig/streamlin...
125
  my $lsmod_file = $ENV{'LSMOD'};
463bf9000   Steven Rostedt   kconfig: Fix make...
126

174319281   Toralf Förster   kconfig: Hide err...
127
128
  my @makefiles = `find $ksource -name Makefile 2>/dev/null`;
  chomp @makefiles;
dcc60243e   Steven Rostedt   kconfig: add stre...
129
130
131
132
133
  my %depends;
  my %selects;
  my %prompts;
  my %objects;
  my $var;
13d7e9385   Steven Rostedt   kconfig: Check fo...
134
135
  my $iflevel = 0;
  my @ifdeps;
dcc60243e   Steven Rostedt   kconfig: add stre...
136

dcc60243e   Steven Rostedt   kconfig: add stre...
137
138
139
140
141
142
143
144
145
  # prevent recursion
  my %read_kconfigs;
  
  sub read_kconfig {
      my ($kconfig) = @_;
  
      my $state = "NONE";
      my $config;
      my @kconfigs;
20d190473   Steven Rostedt   kconfig: Fix stre...
146
147
      my $cont = 0;
      my $line;
4908980b2   Steven Rostedt   kconfig: Make loc...
148
149
150
151
152
153
154
155
156
157
158
      my $source = "$ksource/$kconfig";
      my $last_source = "";
  
      # Check for any environment variables used
      while ($source =~ /\$(\w+)/ && $last_source ne $source) {
  	my $env = $1;
  	$last_source = $source;
  	$source =~ s/\$$env/$ENV{$env}/;
      }
  
      open(KIN, "$source") || die "Can't open $kconfig";
dcc60243e   Steven Rostedt   kconfig: add stre...
159
160
      while (<KIN>) {
  	chomp;
20d190473   Steven Rostedt   kconfig: Fix stre...
161
162
163
164
165
166
167
168
169
170
171
172
  	# Make sure that lines ending with \ continue
  	if ($cont) {
  	    $_ = $line . " " . $_;
  	}
  
  	if (s/\\$//) {
  	    $cont = 1;
  	    $line = $_;
  	    next;
  	}
  
  	$cont = 0;
dcc60243e   Steven Rostedt   kconfig: add stre...
173
174
175
176
177
178
  	# collect any Kconfig sources
  	if (/^source\s*"(.*)"/) {
  	    $kconfigs[$#kconfigs+1] = $1;
  	}
  
  	# configs found
8ef17fa2e   Steven Rostedt   kconfig: Have str...
179
  	if (/^\s*(menu)?config\s+(\S+)\s*$/) {
dcc60243e   Steven Rostedt   kconfig: add stre...
180
  	    $state = "NEW";
8ef17fa2e   Steven Rostedt   kconfig: Have str...
181
  	    $config = $2;
dcc60243e   Steven Rostedt   kconfig: add stre...
182

13d7e9385   Steven Rostedt   kconfig: Check fo...
183
184
185
186
187
188
189
190
  	    for (my $i = 0; $i < $iflevel; $i++) {
  		if ($i) {
  		    $depends{$config} .= " " . $ifdeps[$i];
  		} else {
  		    $depends{$config} = $ifdeps[$i];
  		}
  		$state = "DEP";
  	    }
dcc60243e   Steven Rostedt   kconfig: add stre...
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
  	# collect the depends for the config
  	} elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) {
  	    $state = "DEP";
  	    $depends{$config} = $1;
  	} elsif ($state eq "DEP" && /^\s*depends\s+on\s+(.*)$/) {
  	    $depends{$config} .= " " . $1;
  
  	# Get the configs that select this config
  	} elsif ($state ne "NONE" && /^\s*select\s+(\S+)/) {
  	    if (defined($selects{$1})) {
  		$selects{$1} .= " " . $config;
  	    } else {
  		$selects{$1} = $config;
  	    }
  
  	# configs without prompts must be selected
  	} elsif ($state ne "NONE" && /^\s*tristate\s\S/) {
  	    # note if the config has a prompt
ccece60ac   hiromu yagura   kconfig: Fix vari...
209
  	    $prompts{$config} = 1;
dcc60243e   Steven Rostedt   kconfig: add stre...
210

13d7e9385   Steven Rostedt   kconfig: Check fo...
211
212
213
214
215
216
217
218
219
220
221
222
223
224
  	# Check for if statements
  	} elsif (/^if\s+(.*\S)\s*$/) {
  	    my $deps = $1;
  	    # remove beginning and ending non text
  	    $deps =~ s/^[^a-zA-Z0-9_]*//;
  	    $deps =~ s/[^a-zA-Z0-9_]*$//;
  
  	    my @deps = split /[^a-zA-Z0-9_]+/, $deps;
  
  	    $ifdeps[$iflevel++] = join ':', @deps;
  
  	} elsif (/^endif/) {
  
  	    $iflevel-- if ($iflevel);
dcc60243e   Steven Rostedt   kconfig: add stre...
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
  	# stop on "help"
  	} elsif (/^\s*help\s*$/) {
  	    $state = "NONE";
  	}
      }
      close(KIN);
  
      # read in any configs that were found.
      foreach $kconfig (@kconfigs) {
  	if (!defined($read_kconfigs{$kconfig})) {
  	    $read_kconfigs{$kconfig} = 1;
  	    read_kconfig($kconfig);
  	}
      }
  }
  
  if ($kconfig) {
      read_kconfig($kconfig);
  }
  
  # Read all Makefiles to map the configs to the objects
  foreach my $makefile (@makefiles) {
dcc60243e   Steven Rostedt   kconfig: add stre...
247

20d190473   Steven Rostedt   kconfig: Fix stre...
248
      my $cont = 0;
dcc60243e   Steven Rostedt   kconfig: add stre...
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
      open(MIN,$makefile) || die "Can't open $makefile";
      while (<MIN>) {
  	my $objs;
  
  	# is this a line after a line with a backslash?
  	if ($cont && /(\S.*)$/) {
  	    $objs = $1;
  	}
  	$cont = 0;
  
  	# collect objects after obj-$(CONFIG_FOO_BAR)
  	if (/obj-\$\((CONFIG_[^\)]*)\)\s*[+:]?=\s*(.*)/) {
  	    $var = $1;
  	    $objs = $2;
  	}
  	if (defined($objs)) {
  	    # test if the line ends with a backslash
  	    if ($objs =~ m,(.*)\\$,) {
  		$objs = $1;
  		$cont = 1;
  	    }
  
  	    foreach my $obj (split /\s+/,$objs) {
  		$obj =~ s/-/_/g;
  		if ($obj =~ /(.*)\.o$/) {
1d1d1feaf   Toralf Foerster   kconfig: Fix typo...
274
  		    # Objects may be enabled by more than one config.
dcc60243e   Steven Rostedt   kconfig: add stre...
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
  		    # Store configs in an array.
  		    my @arr;
  
  		    if (defined($objects{$1})) {
  			@arr = @{$objects{$1}};
  		    }
  
  		    $arr[$#arr+1] = $var;
  
  		    # The objects have a hash mapping to a reference
  		    # of an array of configs.
  		    $objects{$1} = \@arr;
  		}
  	    }
  	}
      }
      close(MIN);
  }
  
  my %modules;
615f0833a   Steven Rostedt   kconfig: Add LSMO...
295
296
  if (defined($lsmod_file)) {
      if ( ! -f $lsmod_file) {
f597a7182   Arnaud Lacombe   kconfig/streamlin...
297
298
299
300
301
  	if ( -f $ENV{'objtree'}."/".$lsmod_file) {
  	    $lsmod_file = $ENV{'objtree'}."/".$lsmod_file;
  	} else {
  		die "$lsmod_file not found";
  	}
615f0833a   Steven Rostedt   kconfig: Add LSMO...
302
303
304
305
306
307
308
      }
      if ( -x $lsmod_file) {
  	# the file is executable, run it
  	open(LIN, "$lsmod_file|");
      } else {
  	# Just read the contents
  	open(LIN, "$lsmod_file");
88f66ea98   Steven Rostedt   kconfig: Look in ...
309
      }
615f0833a   Steven Rostedt   kconfig: Add LSMO...
310
311
312
313
  } else {
  
      # see what modules are loaded on this system
      my $lsmod;
cf5a189d4   hiromu   kconfig: Fix miss...
314
      foreach my $dir ( ("/sbin", "/bin", "/usr/sbin", "/usr/bin") ) {
615f0833a   Steven Rostedt   kconfig: Add LSMO...
315
316
317
318
  	if ( -x "$dir/lsmod" ) {
  	    $lsmod = "$dir/lsmod";
  	    last;
  	}
88f66ea98   Steven Rostedt   kconfig: Look in ...
319
  }
615f0833a   Steven Rostedt   kconfig: Add LSMO...
320
321
322
323
324
325
      if (!defined($lsmod)) {
  	# try just the path
  	$lsmod = "lsmod";
      }
  
      open(LIN,"$lsmod|") || die "Can not call lsmod with $lsmod";
88f66ea98   Steven Rostedt   kconfig: Look in ...
326
  }
dcc60243e   Steven Rostedt   kconfig: add stre...
327
328
329
330
331
332
333
334
335
336
337
338
339
  while (<LIN>) {
  	next if (/^Module/);  # Skip the first line.
  	if (/^(\S+)/) {
  		$modules{$1} = 1;
  	}
  }
  close (LIN);
  
  # add to the configs hash all configs that are needed to enable
  # a loaded module.
  my %configs;
  foreach my $module (keys(%modules)) {
      if (defined($objects{$module})) {
e5199edb9   Toralf Foerster   kconfig: Make a v...
340
  	my @arr = @{$objects{$module}};
dcc60243e   Steven Rostedt   kconfig: add stre...
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
  	foreach my $conf (@arr) {
  	    $configs{$conf} = $module;
  	}
      } else {
  	# Most likely, someone has a custom (binary?) module loaded.
  	print STDERR "$module config not found!!
  ";
      }
  }
  
  my $valid = "A-Za-z_0-9";
  my $repeat = 1;
  
  #
  # Note, we do not care about operands (like: &&, ||, !) we want to add any
  # config that is in the depend list of another config. This script does
  # not enable configs that are not already enabled. If we come across a
  # config A that depends on !B, we can still add B to the list of depends
  # to keep on. If A was on in the original config, B would not have been
  # and B would not be turned on by this script.
  #
  sub parse_config_dep_select
  {
      my ($p) = @_;
  
      while ($p =~ /[$valid]/) {
  
  	if ($p =~ /^[^$valid]*([$valid]+)/) {
  	    my $conf = "CONFIG_" . $1;
  
  	    $p =~ s/^[^$valid]*[$valid]+//;
  
  	    if (!defined($configs{$conf})) {
  		# We must make sure that this config has its
  		# dependencies met.
  		$repeat = 1; # do again
  		$configs{$conf} = 1;
  	    }
  	} else {
  	    die "this should never happen";
  	}
      }
  }
  
  while ($repeat) {
      $repeat = 0;
  
      foreach my $config (keys %configs) {
  	$config =~ s/^CONFIG_//;
74398d322   Steven Rostedt   kconfig: streamli...
390
391
392
  	if (defined($depends{$config})) {
  	    # This config has dependencies. Make sure they are also included
  	    parse_config_dep_select $depends{$config};
dcc60243e   Steven Rostedt   kconfig: add stre...
393
  	}
ccece60ac   hiromu yagura   kconfig: Fix vari...
394
  	if (defined($prompts{$config}) || !defined($selects{$config})) {
dcc60243e   Steven Rostedt   kconfig: add stre...
395
396
397
398
399
400
401
402
403
404
405
406
407
  	    next;
  	}
  
  	# config has no prompt and must be selected.
  	parse_config_dep_select $selects{$config};
      }
  }
  
  my %setconfigs;
  
  # Finally, read the .config file and turn off any module enabled that
  # we could not find a reason to keep enabled.
  while(<CIN>) {
744ffcbe8   Steven Rostedt   kconfig: enable C...
408
409
410
411
412
413
414
  
      if (/CONFIG_IKCONFIG/) {
  	if (/# CONFIG_IKCONFIG is not set/) {
  	    # enable IKCONFIG at least as a module
  	    print "CONFIG_IKCONFIG=m
  ";
  	    # don't ask about PROC
d08ca2771   Steven Rostedt   kconfig: unset IK...
415
416
  	    print "# CONFIG_IKCONFIG_PROC is not set
  ";
744ffcbe8   Steven Rostedt   kconfig: enable C...
417
418
419
420
421
422
423
424
  	} else {
  	    print;
  	}
  	next;
      }
  
      if (/^(CONFIG.*)=(m|y)/) {
  	if (defined($configs{$1})) {
22d550ae8   Arnaud Lacombe   kconfig/streamlin...
425
426
427
428
429
  	    if ($localyesconfig) {
  	        $setconfigs{$1} = 'y';
  	    } else {
  	        $setconfigs{$1} = $2;
  	    }
744ffcbe8   Steven Rostedt   kconfig: enable C...
430
431
432
  	} elsif ($2 eq "m") {
  	    print "# $1 is not set
  ";
d08ca2771   Steven Rostedt   kconfig: unset IK...
433
  	    next;
dcc60243e   Steven Rostedt   kconfig: add stre...
434
  	}
744ffcbe8   Steven Rostedt   kconfig: enable C...
435
      }
d08ca2771   Steven Rostedt   kconfig: unset IK...
436
      print;
dcc60243e   Steven Rostedt   kconfig: add stre...
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
  }
  close(CIN);
  
  # Integrity check, make sure all modules that we want enabled do
  # indeed have their configs set.
  loop:
  foreach my $module (keys(%modules)) {
      if (defined($objects{$module})) {
  	my @arr = @{$objects{$module}};
  	foreach my $conf (@arr) {
  	    if (defined($setconfigs{$conf})) {
  		next loop;
  	    }
  	}
  	print STDERR "module $module did not have configs";
  	foreach my $conf (@arr) {
  	    print STDERR " " , $conf;
  	}
  	print STDERR "
  ";
      }
  }