linux/scripts/kconfig/streamline_config.pl
<<
>>
Prefs
   1#!/usr/bin/perl -w
   2#
   3# Copyright 2005-2009 - Steven Rostedt
   4# Licensed under the terms of the GNU GPL License version 2
   5#
   6#  It's simple enough to figure out how this works.
   7#  If not, then you can ask me at stripconfig@goodmis.org
   8#
   9# What it does?
  10#
  11#   If you have installed a Linux kernel from a distribution
  12#   that turns on way too many modules than you need, and
  13#   you only want the modules you use, then this program
  14#   is perfect for you.
  15#
  16#   It gives you the ability to turn off all the modules that are
  17#   not loaded on your system.
  18#
  19# Howto:
  20#
  21#  1. Boot up the kernel that you want to stream line the config on.
  22#  2. Change directory to the directory holding the source of the
  23#       kernel that you just booted.
  24#  3. Copy the configuraton file to this directory as .config
  25#  4. Have all your devices that you need modules for connected and
  26#      operational (make sure that their corresponding modules are loaded)
  27#  5. Run this script redirecting the output to some other file
  28#       like config_strip.
  29#  6. Back up your old config (if you want too).
  30#  7. copy the config_strip file to .config
  31#  8. Run "make oldconfig"
  32#
  33#  Now your kernel is ready to be built with only the modules that
  34#  are loaded.
  35#
  36# Here's what I did with my Debian distribution.
  37#
  38#    cd /usr/src/linux-2.6.10
  39#    cp /boot/config-2.6.10-1-686-smp .config
  40#    ~/bin/streamline_config > config_strip
  41#    mv .config config_sav
  42#    mv config_strip .config
  43#    make oldconfig
  44#
  45use strict;
  46use Getopt::Long;
  47
  48# set the environment variable LOCALMODCONFIG_DEBUG to get
  49# debug output.
  50my $debugprint = 0;
  51$debugprint = 1 if (defined($ENV{LOCALMODCONFIG_DEBUG}));
  52
  53sub dprint {
  54    return if (!$debugprint);
  55    print STDERR @_;
  56}
  57
  58my $config = ".config";
  59
  60my $uname = `uname -r`;
  61chomp $uname;
  62
  63my @searchconfigs = (
  64        {
  65            "file" => ".config",
  66            "exec" => "cat",
  67        },
  68        {
  69            "file" => "/proc/config.gz",
  70            "exec" => "zcat",
  71        },
  72        {
  73            "file" => "/boot/config-$uname",
  74            "exec" => "cat",
  75        },
  76        {
  77            "file" => "/boot/vmlinuz-$uname",
  78            "exec" => "scripts/extract-ikconfig",
  79            "test" => "scripts/extract-ikconfig",
  80        },
  81        {
  82            "file" => "vmlinux",
  83            "exec" => "scripts/extract-ikconfig",
  84            "test" => "scripts/extract-ikconfig",
  85        },
  86        {
  87            "file" => "/lib/modules/$uname/kernel/kernel/configs.ko",
  88            "exec" => "scripts/extract-ikconfig",
  89            "test" => "scripts/extract-ikconfig",
  90        },
  91        {
  92            "file" => "kernel/configs.ko",
  93            "exec" => "scripts/extract-ikconfig",
  94            "test" => "scripts/extract-ikconfig",
  95        },
  96        {
  97            "file" => "kernel/configs.o",
  98            "exec" => "scripts/extract-ikconfig",
  99            "test" => "scripts/extract-ikconfig",
 100        },
 101);
 102
 103sub find_config {
 104    foreach my $conf (@searchconfigs) {
 105        my $file = $conf->{"file"};
 106
 107        next if ( ! -f "$file");
 108
 109        if (defined($conf->{"test"})) {
 110            `$conf->{"test"} $conf->{"file"} 2>/dev/null`;
 111            next if ($?);
 112        }
 113
 114        my $exec = $conf->{"exec"};
 115
 116        print STDERR "using config: '$file'\n";
 117
 118        open(CIN, "$exec $file |") || die "Failed to run $exec $file";
 119        return;
 120    }
 121    die "No config file found";
 122}
 123
 124find_config;
 125
 126# Read in the entire config file into config_file
 127my @config_file = <CIN>;
 128close CIN;
 129
 130# Parse options
 131my $localmodconfig = 0;
 132my $localyesconfig = 0;
 133
 134GetOptions("localmodconfig" => \$localmodconfig,
 135           "localyesconfig" => \$localyesconfig);
 136
 137# Get the build source and top level Kconfig file (passed in)
 138my $ksource = $ARGV[0];
 139my $kconfig = $ARGV[1];
 140my $lsmod_file = $ENV{'LSMOD'};
 141
 142my @makefiles = `find $ksource -name Makefile 2>/dev/null`;
 143chomp @makefiles;
 144
 145my %depends;
 146my %selects;
 147my %prompts;
 148my %objects;
 149my $var;
 150my $iflevel = 0;
 151my @ifdeps;
 152
 153# prevent recursion
 154my %read_kconfigs;
 155
 156sub read_kconfig {
 157    my ($kconfig) = @_;
 158
 159    my $state = "NONE";
 160    my $config;
 161    my @kconfigs;
 162
 163    my $cont = 0;
 164    my $line;
 165
 166    my $source = "$ksource/$kconfig";
 167    my $last_source = "";
 168
 169    # Check for any environment variables used
 170    while ($source =~ /\$(\w+)/ && $last_source ne $source) {
 171        my $env = $1;
 172        $last_source = $source;
 173        $source =~ s/\$$env/$ENV{$env}/;
 174    }
 175
 176    open(KIN, "$source") || die "Can't open $kconfig";
 177    while (<KIN>) {
 178        chomp;
 179
 180        # Make sure that lines ending with \ continue
 181        if ($cont) {
 182            $_ = $line . " " . $_;
 183        }
 184
 185        if (s/\\$//) {
 186            $cont = 1;
 187            $line = $_;
 188            next;
 189        }
 190
 191        $cont = 0;
 192
 193        # collect any Kconfig sources
 194        if (/^source\s*"(.*)"/) {
 195            $kconfigs[$#kconfigs+1] = $1;
 196        }
 197
 198        # configs found
 199        if (/^\s*(menu)?config\s+(\S+)\s*$/) {
 200            $state = "NEW";
 201            $config = $2;
 202
 203            # Add depends for 'if' nesting
 204            for (my $i = 0; $i < $iflevel; $i++) {
 205                if ($i) {
 206                    $depends{$config} .= " " . $ifdeps[$i];
 207                } else {
 208                    $depends{$config} = $ifdeps[$i];
 209                }
 210                $state = "DEP";
 211            }
 212
 213        # collect the depends for the config
 214        } elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) {
 215            $state = "DEP";
 216            $depends{$config} = $1;
 217        } elsif ($state eq "DEP" && /^\s*depends\s+on\s+(.*)$/) {
 218            $depends{$config} .= " " . $1;
 219
 220        # Get the configs that select this config
 221        } elsif ($state ne "NONE" && /^\s*select\s+(\S+)/) {
 222            my $conf = $1;
 223            if (defined($selects{$conf})) {
 224                $selects{$conf} .= " " . $config;
 225            } else {
 226                $selects{$conf} = $config;
 227            }
 228
 229        # configs without prompts must be selected
 230        } elsif ($state ne "NONE" && /^\s*tristate\s\S/) {
 231            # note if the config has a prompt
 232            $prompts{$config} = 1;
 233
 234        # Check for if statements
 235        } elsif (/^if\s+(.*\S)\s*$/) {
 236            my $deps = $1;
 237            # remove beginning and ending non text
 238            $deps =~ s/^[^a-zA-Z0-9_]*//;
 239            $deps =~ s/[^a-zA-Z0-9_]*$//;
 240
 241            my @deps = split /[^a-zA-Z0-9_]+/, $deps;
 242
 243            $ifdeps[$iflevel++] = join ':', @deps;
 244
 245        } elsif (/^endif/) {
 246
 247            $iflevel-- if ($iflevel);
 248
 249        # stop on "help"
 250        } elsif (/^\s*help\s*$/) {
 251            $state = "NONE";
 252        }
 253    }
 254    close(KIN);
 255
 256    # read in any configs that were found.
 257    foreach $kconfig (@kconfigs) {
 258        if (!defined($read_kconfigs{$kconfig})) {
 259            $read_kconfigs{$kconfig} = 1;
 260            read_kconfig($kconfig);
 261        }
 262    }
 263}
 264
 265if ($kconfig) {
 266    read_kconfig($kconfig);
 267}
 268
 269# Makefiles can use variables to define their dependencies
 270sub convert_vars {
 271    my ($line, %vars) = @_;
 272
 273    my $process = "";
 274
 275    while ($line =~ s/^(.*?)(\$\((.*?)\))//) {
 276        my $start = $1;
 277        my $variable = $2;
 278        my $var = $3;
 279
 280        if (defined($vars{$var})) {
 281            $process .= $start . $vars{$var};
 282        } else {
 283            $process .= $start . $variable;
 284        }
 285    }
 286
 287    $process .= $line;
 288
 289    return $process;
 290}
 291
 292# Read all Makefiles to map the configs to the objects
 293foreach my $makefile (@makefiles) {
 294
 295    my $line = "";
 296    my %make_vars;
 297
 298    open(MIN,$makefile) || die "Can't open $makefile";
 299    while (<MIN>) {
 300        # if this line ends with a backslash, continue
 301        chomp;
 302        if (/^(.*)\\$/) {
 303            $line .= $1;
 304            next;
 305        }
 306
 307        $line .= $_;
 308        $_ = $line;
 309        $line = "";
 310
 311        my $objs;
 312
 313        # Convert variables in a line (could define configs)
 314        $_ = convert_vars($_, %make_vars);
 315
 316        # collect objects after obj-$(CONFIG_FOO_BAR)
 317        if (/obj-\$\((CONFIG_[^\)]*)\)\s*[+:]?=\s*(.*)/) {
 318            $var = $1;
 319            $objs = $2;
 320
 321        # check if variables are set
 322        } elsif (/^\s*(\S+)\s*[:]?=\s*(.*\S)/) {
 323            $make_vars{$1} = $2;
 324        }
 325        if (defined($objs)) {
 326            foreach my $obj (split /\s+/,$objs) {
 327                $obj =~ s/-/_/g;
 328                if ($obj =~ /(.*)\.o$/) {
 329                    # Objects may be enabled by more than one config.
 330                    # Store configs in an array.
 331                    my @arr;
 332
 333                    if (defined($objects{$1})) {
 334                        @arr = @{$objects{$1}};
 335                    }
 336
 337                    $arr[$#arr+1] = $var;
 338
 339                    # The objects have a hash mapping to a reference
 340                    # of an array of configs.
 341                    $objects{$1} = \@arr;
 342                }
 343            }
 344        }
 345    }
 346    close(MIN);
 347}
 348
 349my %modules;
 350
 351if (defined($lsmod_file)) {
 352    if ( ! -f $lsmod_file) {
 353        if ( -f $ENV{'objtree'}."/".$lsmod_file) {
 354            $lsmod_file = $ENV{'objtree'}."/".$lsmod_file;
 355        } else {
 356                die "$lsmod_file not found";
 357        }
 358    }
 359    if ( -x $lsmod_file) {
 360        # the file is executable, run it
 361        open(LIN, "$lsmod_file|");
 362    } else {
 363        # Just read the contents
 364        open(LIN, "$lsmod_file");
 365    }
 366} else {
 367
 368    # see what modules are loaded on this system
 369    my $lsmod;
 370
 371    foreach my $dir ( ("/sbin", "/bin", "/usr/sbin", "/usr/bin") ) {
 372        if ( -x "$dir/lsmod" ) {
 373            $lsmod = "$dir/lsmod";
 374            last;
 375        }
 376}
 377    if (!defined($lsmod)) {
 378        # try just the path
 379        $lsmod = "lsmod";
 380    }
 381
 382    open(LIN,"$lsmod|") || die "Can not call lsmod with $lsmod";
 383}
 384
 385while (<LIN>) {
 386        next if (/^Module/);  # Skip the first line.
 387        if (/^(\S+)/) {
 388                $modules{$1} = 1;
 389        }
 390}
 391close (LIN);
 392
 393# add to the configs hash all configs that are needed to enable
 394# a loaded module. This is a direct obj-${CONFIG_FOO} += bar.o
 395# where we know we need bar.o so we add FOO to the list.
 396my %configs;
 397foreach my $module (keys(%modules)) {
 398    if (defined($objects{$module})) {
 399        my @arr = @{$objects{$module}};
 400        foreach my $conf (@arr) {
 401            $configs{$conf} = $module;
 402            dprint "$conf added by direct ($module)\n";
 403        }
 404    } else {
 405        # Most likely, someone has a custom (binary?) module loaded.
 406        print STDERR "$module config not found!!\n";
 407    }
 408}
 409
 410# Read the current config, and see what is enabled. We want to
 411# ignore configs that we would not enable anyway.
 412
 413my %orig_configs;
 414my $valid = "A-Za-z_0-9";
 415
 416foreach my $line (@config_file) {
 417    $_ = $line;
 418
 419    if (/(CONFIG_[$valid]*)=(m|y)/) {
 420        $orig_configs{$1} = $2;
 421    }
 422}
 423
 424my $repeat = 1;
 425
 426my $depconfig;
 427
 428#
 429# Note, we do not care about operands (like: &&, ||, !) we want to add any
 430# config that is in the depend list of another config. This script does
 431# not enable configs that are not already enabled. If we come across a
 432# config A that depends on !B, we can still add B to the list of depends
 433# to keep on. If A was on in the original config, B would not have been
 434# and B would not be turned on by this script.
 435#
 436sub parse_config_depends
 437{
 438    my ($p) = @_;
 439
 440    while ($p =~ /[$valid]/) {
 441
 442        if ($p =~ /^[^$valid]*([$valid]+)/) {
 443            my $conf = "CONFIG_" . $1;
 444
 445            $p =~ s/^[^$valid]*[$valid]+//;
 446
 447            # We only need to process if the depend config is a module
 448            if (!defined($orig_configs{$conf}) || !$orig_configs{conf} eq "m") {
 449                next;
 450            }
 451
 452            if (!defined($configs{$conf})) {
 453                # We must make sure that this config has its
 454                # dependencies met.
 455                $repeat = 1; # do again
 456                dprint "$conf selected by depend $depconfig\n";
 457                $configs{$conf} = 1;
 458            }
 459        } else {
 460            die "this should never happen";
 461        }
 462    }
 463}
 464
 465# Select is treated a bit differently than depends. We call this
 466# when a config has no prompt and requires another config to be
 467# selected. We use to just select all configs that selected this
 468# config, but found that that can balloon into enabling hundreds
 469# of configs that we do not care about.
 470#
 471# The idea is we look at all the configs that select it. If one
 472# is already in our list of configs to enable, then there's nothing
 473# else to do. If there isn't, we pick the first config that was
 474# enabled in the orignal config and use that.
 475sub parse_config_selects
 476{
 477    my ($config, $p) = @_;
 478
 479    my $next_config;
 480
 481    while ($p =~ /[$valid]/) {
 482
 483        if ($p =~ /^[^$valid]*([$valid]+)/) {
 484            my $conf = "CONFIG_" . $1;
 485
 486            $p =~ s/^[^$valid]*[$valid]+//;
 487
 488            # Make sure that this config exists in the current .config file
 489            if (!defined($orig_configs{$conf})) {
 490                dprint "$conf not set for $config select\n";
 491                next;
 492            }
 493
 494            # Check if something other than a module selects this config
 495            if (defined($orig_configs{$conf}) && $orig_configs{$conf} ne "m") {
 496                dprint "$conf (non module) selects config, we are good\n";
 497                # we are good with this
 498                return;
 499            }
 500            if (defined($configs{$conf})) {
 501                dprint "$conf selects $config so we are good\n";
 502                # A set config selects this config, we are good
 503                return;
 504            }
 505            # Set this config to be selected
 506            if (!defined($next_config)) {
 507                $next_config = $conf;
 508            }
 509        } else {
 510            die "this should never happen";
 511        }
 512    }
 513
 514    # If no possible config selected this, then something happened.
 515    if (!defined($next_config)) {
 516        print STDERR "WARNING: $config is required, but nothing in the\n";
 517        print STDERR "  current config selects it.\n";
 518        return;
 519    }
 520
 521    # If we are here, then we found no config that is set and
 522    # selects this config. Repeat.
 523    $repeat = 1;
 524    # Make this config need to be selected
 525    $configs{$next_config} = 1;
 526    dprint "$next_config selected by select $config\n";
 527}
 528
 529my %process_selects;
 530
 531# loop through all configs, select their dependencies.
 532sub loop_depend {
 533    $repeat = 1;
 534
 535    while ($repeat) {
 536        $repeat = 0;
 537
 538      forloop:
 539        foreach my $config (keys %configs) {
 540
 541            # If this config is not a module, we do not need to process it
 542            if (defined($orig_configs{$config}) && $orig_configs{$config} ne "m") {
 543                next forloop;
 544            }
 545
 546            $config =~ s/^CONFIG_//;
 547            $depconfig = $config;
 548
 549            if (defined($depends{$config})) {
 550                # This config has dependencies. Make sure they are also included
 551                parse_config_depends $depends{$config};
 552            }
 553
 554            # If the config has no prompt, then we need to check if a config
 555            # that is enabled selected it. Or if we need to enable one.
 556            if (!defined($prompts{$config}) && defined($selects{$config})) {
 557                $process_selects{$config} = 1;
 558            }
 559        }
 560    }
 561}
 562
 563sub loop_select {
 564
 565    foreach my $config (keys %process_selects) {
 566        $config =~ s/^CONFIG_//;
 567
 568        dprint "Process select $config\n";
 569
 570        # config has no prompt and must be selected.
 571        parse_config_selects $config, $selects{$config};
 572    }
 573}
 574
 575while ($repeat) {
 576    # Get the first set of configs and their dependencies.
 577    loop_depend;
 578
 579    $repeat = 0;
 580
 581    # Now we need to see if we have to check selects;
 582    loop_select;
 583}           
 584
 585my %setconfigs;
 586
 587# Finally, read the .config file and turn off any module enabled that
 588# we could not find a reason to keep enabled.
 589foreach my $line (@config_file) {
 590    $_ = $line;
 591
 592    if (/CONFIG_IKCONFIG/) {
 593        if (/# CONFIG_IKCONFIG is not set/) {
 594            # enable IKCONFIG at least as a module
 595            print "CONFIG_IKCONFIG=m\n";
 596            # don't ask about PROC
 597            print "# CONFIG_IKCONFIG_PROC is not set\n";
 598        } else {
 599            print;
 600        }
 601        next;
 602    }
 603
 604    if (/^(CONFIG.*)=(m|y)/) {
 605        if (defined($configs{$1})) {
 606            if ($localyesconfig) {
 607                $setconfigs{$1} = 'y';
 608                print "$1=y\n";
 609                next;
 610            } else {
 611                $setconfigs{$1} = $2;
 612            }
 613        } elsif ($2 eq "m") {
 614            print "# $1 is not set\n";
 615            next;
 616        }
 617    }
 618    print;
 619}
 620
 621# Integrity check, make sure all modules that we want enabled do
 622# indeed have their configs set.
 623loop:
 624foreach my $module (keys(%modules)) {
 625    if (defined($objects{$module})) {
 626        my @arr = @{$objects{$module}};
 627        foreach my $conf (@arr) {
 628            if (defined($setconfigs{$conf})) {
 629                next loop;
 630            }
 631        }
 632        print STDERR "module $module did not have configs";
 633        foreach my $conf (@arr) {
 634            print STDERR " " , $conf;
 635        }
 636        print STDERR "\n";
 637    }
 638}
 639
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.