0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045 use warnings;
0046 use strict;
0047 use Getopt::Long;
0048
0049
0050
0051 my $debugprint = 0;
0052 $debugprint = 1 if (defined($ENV{LOCALMODCONFIG_DEBUG}));
0053
0054 sub dprint {
0055 return if (!$debugprint);
0056 print STDERR @_;
0057 }
0058
0059 my $uname = `uname -r`;
0060 chomp $uname;
0061
0062 my @searchconfigs = (
0063 {
0064 "file" => ".config",
0065 "exec" => "cat",
0066 },
0067 {
0068 "file" => "/proc/config.gz",
0069 "exec" => "zcat",
0070 },
0071 {
0072 "file" => "/boot/config-$uname",
0073 "exec" => "cat",
0074 },
0075 {
0076 "file" => "/boot/vmlinuz-$uname",
0077 "exec" => "scripts/extract-ikconfig",
0078 "test" => "scripts/extract-ikconfig",
0079 },
0080 {
0081 "file" => "vmlinux",
0082 "exec" => "scripts/extract-ikconfig",
0083 "test" => "scripts/extract-ikconfig",
0084 },
0085 {
0086 "file" => "/lib/modules/$uname/kernel/kernel/configs.ko",
0087 "exec" => "scripts/extract-ikconfig",
0088 "test" => "scripts/extract-ikconfig",
0089 },
0090 {
0091 "file" => "kernel/configs.ko",
0092 "exec" => "scripts/extract-ikconfig",
0093 "test" => "scripts/extract-ikconfig",
0094 },
0095 {
0096 "file" => "kernel/configs.o",
0097 "exec" => "scripts/extract-ikconfig",
0098 "test" => "scripts/extract-ikconfig",
0099 },
0100 );
0101
0102 sub read_config {
0103 foreach my $conf (@searchconfigs) {
0104 my $file = $conf->{"file"};
0105
0106 next if ( ! -f "$file");
0107
0108 if (defined($conf->{"test"})) {
0109 `$conf->{"test"} $conf->{"file"} 2>/dev/null`;
0110 next if ($?);
0111 }
0112
0113 my $exec = $conf->{"exec"};
0114
0115 print STDERR "using config: '$file'\n";
0116
0117 open(my $infile, '-|', "$exec $file") || die "Failed to run $exec $file";
0118 my @x = <$infile>;
0119 close $infile;
0120 return @x;
0121 }
0122 die "No config file found";
0123 }
0124
0125 my @config_file = read_config;
0126
0127
0128 my $localmodconfig = 0;
0129 my $localyesconfig = 0;
0130
0131 GetOptions("localmodconfig" => \$localmodconfig,
0132 "localyesconfig" => \$localyesconfig);
0133
0134
0135 my $ksource = ($ARGV[0] ? $ARGV[0] : '.');
0136 my $kconfig = $ARGV[1];
0137 my $lsmod_file = $ENV{'LSMOD'};
0138
0139 my @makefiles = `find $ksource -name Makefile -or -name Kbuild 2>/dev/null`;
0140 chomp @makefiles;
0141
0142 my %depends;
0143 my %selects;
0144 my %prompts;
0145 my %objects;
0146 my %config2kfile;
0147 my $var;
0148 my $iflevel = 0;
0149 my @ifdeps;
0150
0151
0152 my %read_kconfigs;
0153
0154 sub read_kconfig {
0155 my ($kconfig) = @_;
0156
0157 my $state = "NONE";
0158 my $config;
0159
0160 my $cont = 0;
0161 my $line;
0162
0163 my $source = "$ksource/$kconfig";
0164 my $last_source = "";
0165
0166
0167 while ($source =~ /\$\((\w+)\)/ && $last_source ne $source) {
0168 my $env = $1;
0169 $last_source = $source;
0170 $source =~ s/\$\($env\)/$ENV{$env}/;
0171 }
0172
0173 open(my $kinfile, '<', $source) || die "Can't open $source";
0174 while (<$kinfile>) {
0175 chomp;
0176
0177
0178 if ($cont) {
0179 $_ = $line . " " . $_;
0180 }
0181
0182 if (s/\\$//) {
0183 $cont = 1;
0184 $line = $_;
0185 next;
0186 }
0187
0188 $cont = 0;
0189
0190
0191 if (/^source\s+"?([^"]+)/) {
0192 my $kconfig = $1;
0193
0194 if (!defined($read_kconfigs{$kconfig})) {
0195 $read_kconfigs{$kconfig} = 1;
0196 read_kconfig($kconfig);
0197 }
0198 next;
0199 }
0200
0201
0202 if (/^\s*(menu)?config\s+(\S+)\s*$/) {
0203 $state = "NEW";
0204 $config = $2;
0205 $config2kfile{"CONFIG_$config"} = $kconfig;
0206
0207
0208 for (my $i = 0; $i < $iflevel; $i++) {
0209 if ($i) {
0210 $depends{$config} .= " " . $ifdeps[$i];
0211 } else {
0212 $depends{$config} = $ifdeps[$i];
0213 }
0214 $state = "DEP";
0215 }
0216
0217
0218 } elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) {
0219 $state = "DEP";
0220 $depends{$config} = $1;
0221 } elsif ($state eq "DEP" && /^\s*depends\s+on\s+(.*)$/) {
0222 $depends{$config} .= " " . $1;
0223 } elsif ($state eq "DEP" && /^\s*def(_(bool|tristate)|ault)\s+(\S.*)$/) {
0224 my $dep = $3;
0225 if ($dep !~ /^\s*(y|
0226
0227
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241 \b)/) {
0242
0243 $prompts{$config} = 1;
0244
0245
0246 } elsif (/^if\s+(.*\S)\s*$/) {
0247 my $deps = $1;
0248
0249 $deps =~ s/^[^a-zA-Z0-9_]*//;
0250 $deps =~ s/[^a-zA-Z0-9_]*$//;
0251
0252 my @deps = split /[^a-zA-Z0-9_]+/, $deps;
0253
0254 $ifdeps[$iflevel++] = join ':', @deps;
0255
0256 } elsif (/^endif/) {
0257
0258 $iflevel-- if ($iflevel);
0259
0260
0261 } elsif (/^\s*(---)?help(---)?\s*$/ || /^(comment|choice|menu)\b/) {
0262 $state = "NONE";
0263 }
0264 }
0265 close($kinfile);
0266 }
0267
0268 if ($kconfig) {
0269 read_kconfig($kconfig);
0270 }
0271
0272
0273 sub convert_vars {
0274 my ($line, %vars) = @_;
0275
0276 my $process = "";
0277
0278 while ($line =~ s/^(.*?)(\$\((.*?)\))//) {
0279 my $start = $1;
0280 my $variable = $2;
0281 my $var = $3;
0282
0283 if (defined($vars{$var})) {
0284 $process .= $start . $vars{$var};
0285 } else {
0286 $process .= $start . $variable;
0287 }
0288 }
0289
0290 $process .= $line;
0291
0292 return $process;
0293 }
0294
0295
0296 foreach my $makefile (@makefiles) {
0297
0298 my $line = "";
0299 my %make_vars;
0300
0301 open(my $infile, '<', $makefile) || die "Can't open $makefile";
0302 while (<$infile>) {
0303
0304 chomp;
0305 if (/^(.*)\\$/) {
0306 $line .= $1;
0307 next;
0308 }
0309
0310 $line .= $_;
0311 $_ = $line;
0312 $line = "";
0313
0314 my $objs;
0315
0316
0317 $_ = convert_vars($_, %make_vars);
0318
0319
0320 if (/obj-\$\((CONFIG_[^\)]*)\)\s*[+:]?=\s*(.*)/) {
0321 $var = $1;
0322 $objs = $2;
0323
0324
0325 } elsif (/^\s*(\S+)\s*[:]?=\s*(.*\S)/) {
0326 $make_vars{$1} = $2;
0327 }
0328 if (defined($objs)) {
0329 foreach my $obj (split /\s+/,$objs) {
0330 $obj =~ s/-/_/g;
0331 if ($obj =~ /(.*)\.o$/) {
0332
0333
0334 my @arr;
0335
0336 if (defined($objects{$1})) {
0337 @arr = @{$objects{$1}};
0338 }
0339
0340 $arr[$#arr+1] = $var;
0341
0342
0343
0344 $objects{$1} = \@arr;
0345 }
0346 }
0347 }
0348 }
0349 close($infile);
0350 }
0351
0352 my %modules;
0353 my $linfile;
0354
0355 if (defined($lsmod_file)) {
0356 if ( ! -f $lsmod_file) {
0357 if ( -f $ENV{'objtree'}."/".$lsmod_file) {
0358 $lsmod_file = $ENV{'objtree'}."/".$lsmod_file;
0359 } else {
0360 die "$lsmod_file not found";
0361 }
0362 }
0363
0364 my $otype = ( -x $lsmod_file) ? '-|' : '<';
0365 open($linfile, $otype, $lsmod_file);
0366
0367 } else {
0368
0369
0370 my $lsmod;
0371
0372 foreach my $dir ( ("/sbin", "/bin", "/usr/sbin", "/usr/bin") ) {
0373 if ( -x "$dir/lsmod" ) {
0374 $lsmod = "$dir/lsmod";
0375 last;
0376 }
0377 }
0378 if (!defined($lsmod)) {
0379
0380 $lsmod = "lsmod";
0381 }
0382
0383 open($linfile, '-|', $lsmod) || die "Can not call lsmod with $lsmod";
0384 }
0385
0386 while (<$linfile>) {
0387 next if (/^Module/);
0388 if (/^(\S+)/) {
0389 $modules{$1} = 1;
0390 }
0391 }
0392 close ($linfile);
0393
0394
0395
0396
0397 my %configs;
0398 foreach my $module (keys(%modules)) {
0399 if (defined($objects{$module})) {
0400 my @arr = @{$objects{$module}};
0401 foreach my $conf (@arr) {
0402 $configs{$conf} = $module;
0403 dprint "$conf added by direct ($module)\n";
0404 if ($debugprint) {
0405 my $c=$conf;
0406 $c =~ s/^CONFIG_//;
0407 if (defined($depends{$c})) {
0408 dprint " deps = $depends{$c}\n";
0409 } else {
0410 dprint " no deps\n";
0411 }
0412 }
0413 }
0414 } else {
0415
0416 print STDERR "$module config not found!!\n";
0417 }
0418 }
0419
0420
0421
0422
0423 my %orig_configs;
0424 my $valid = "A-Za-z_0-9";
0425
0426 foreach my $line (@config_file) {
0427 $_ = $line;
0428
0429 if (/(CONFIG_[$valid]*)=(
0430
0431
0432
0433
0434
0435
0436
0437
0438
0439 |, !) we want to add any
0440
0441
0442
0443
0444
0445
0446 sub parse_config_depends
0447 {
0448 my ($p) = @_;
0449
0450 while ($p =~ /[$valid]/) {
0451
0452 if ($p =~ /^[^$valid]*([$valid]+)/) {
0453 my $conf = "CONFIG_" . $1;
0454
0455 $p =~ s/^[^$valid]*[$valid]+//;
0456
0457
0458 if (!defined($orig_configs{$conf}) || $orig_configs{$conf} eq "y") {
0459 next;
0460 }
0461
0462 if (!defined($configs{$conf})) {
0463
0464
0465 $repeat = 1;
0466 dprint "$conf selected by depend $depconfig\n";
0467 $configs{$conf} = 1;
0468 }
0469 } else {
0470 die "this should never happen";
0471 }
0472 }
0473 }
0474
0475
0476
0477
0478
0479
0480
0481
0482
0483
0484
0485 sub parse_config_selects
0486 {
0487 my ($config, $p) = @_;
0488
0489 my $next_config;
0490
0491 while ($p =~ /[$valid]/) {
0492
0493 if ($p =~ /^[^$valid]*([$valid]+)/) {
0494 my $conf = "CONFIG_" . $1;
0495
0496 $p =~ s/^[^$valid]*[$valid]+//;
0497
0498
0499 if (!defined($orig_configs{$conf})) {
0500 dprint "$conf not set for $config select\n";
0501 next;
0502 }
0503
0504
0505 if (defined($orig_configs{$conf}) && $orig_configs{$conf} ne "m") {
0506 dprint "$conf (non module) selects config, we are good\n";
0507
0508 return;
0509 }
0510 if (defined($configs{$conf})) {
0511 dprint "$conf selects $config so we are good\n";
0512
0513 return;
0514 }
0515
0516 if (!defined($next_config)) {
0517 $next_config = $conf;
0518 }
0519 } else {
0520 die "this should never happen";
0521 }
0522 }
0523
0524
0525 if (!defined($next_config)) {
0526 print STDERR "WARNING: $config is required, but nothing in the\n";
0527 print STDERR " current config selects it.\n";
0528 return;
0529 }
0530
0531
0532
0533 $repeat = 1;
0534
0535 $configs{$next_config} = 1;
0536 dprint "$next_config selected by select $config\n";
0537 }
0538
0539 my %process_selects;
0540
0541
0542 sub loop_depend {
0543 $repeat = 1;
0544
0545 while ($repeat) {
0546 $repeat = 0;
0547
0548 forloop:
0549 foreach my $config (keys %configs) {
0550
0551
0552 if (defined($orig_configs{$config}) && $orig_configs{$config} ne "m") {
0553 next forloop;
0554 }
0555
0556 $config =~ s/^CONFIG_//;
0557 $depconfig = $config;
0558
0559 if (defined($depends{$config})) {
0560
0561 parse_config_depends $depends{$config};
0562 }
0563
0564
0565
0566 if (!defined($prompts{$config}) && defined($selects{$config})) {
0567 $process_selects{$config} = 1;
0568 }
0569 }
0570 }
0571 }
0572
0573 sub loop_select {
0574
0575 foreach my $config (keys %process_selects) {
0576 $config =~ s/^CONFIG_//;
0577
0578 dprint "Process select $config\n";
0579
0580
0581 parse_config_selects $config, $selects{$config};
0582 }
0583 }
0584
0585 while ($repeat) {
0586
0587 loop_depend;
0588
0589 $repeat = 0;
0590
0591
0592 loop_select;
0593 }
0594
0595 my %setconfigs;
0596 my @preserved_kconfigs;
0597 if (defined($ENV{'LMC_KEEP'})) {
0598 @preserved_kconfigs = split(/:/,$ENV{LMC_KEEP});
0599 }
0600
0601 sub in_preserved_kconfigs {
0602 my $kconfig = $config2kfile{$_[0]};
0603 if (!defined($kconfig)) {
0604 return 0;
0605 }
0606 foreach my $excl (@preserved_kconfigs) {
0607 if($kconfig =~ /^$excl/) {
0608 return 1;
0609 }
0610 }
0611 return 0;
0612 }
0613
0614
0615
0616 foreach my $line (@config_file) {
0617 $_ = $line;
0618
0619 if (/CONFIG_IKCONFIG/) {
0620 if (/
0621
0622 print "CONFIG_IKCONFIG=m\n";
0623
0624 print "# CONFIG_IKCONFIG_PROC is not set\n";
0625 } else {
0626 print;
0627 }
0628 next;
0629 }
0630
0631 if (/CONFIG_MODULE_SIG_KEY="(.+)"/) {
0632 my $orig_cert = $1;
0633 my $default_cert = "certs/signing_key.pem";
0634
0635
0636 if (!defined($depends{"MODULE_SIG_KEY"}) ||
0637 $depends{"MODULE_SIG_KEY"} !~ /"\Q$default_cert\E"/) {
0638 print STDERR "WARNING: MODULE_SIG_KEY assertion failure, ",
0639 "update needed to ", __FILE__, " line ", __LINE__, "\n";
0640 print;
0641 } elsif ($orig_cert ne $default_cert && ! -f $orig_cert) {
0642 print STDERR "Module signature verification enabled but ",
0643 "module signing key \"$orig_cert\" not found. Resetting ",
0644 "signing key to default value.\n";
0645 print "CONFIG_MODULE_SIG_KEY=\"$default_cert\"\n";
0646 } else {
0647 print;
0648 }
0649 next;
0650 }
0651
0652 if (/CONFIG_SYSTEM_TRUSTED_KEYS="(.+)"/) {
0653 my $orig_keys = $1;
0654
0655 if (! -f $orig_keys) {
0656 print STDERR "System keyring enabled but keys \"$orig_keys\" ",
0657 "not found. Resetting keys to default value.\n";
0658 print "CONFIG_SYSTEM_TRUSTED_KEYS=\"\"\n";
0659 } else {
0660 print;
0661 }
0662 next;
0663 }
0664
0665 if (/^(CONFIG.*)=(
0666
0667
0668
0669
0670
0671
0672
0673
0674
0675
0676
0677
0678
0679
0680
0681
0682
0683
0684
0685
0686
0687
0688
0689
0690
0691
0692
0693
0694
0695
0696
0697
0698
0699
0700
0701
0702
0703
0704
0705
0706