10f0db065SSteven Rostedt (Red Hat)#!/usr/bin/perl -w
24f19048fSThomas Gleixner# SPDX-License-Identifier: GPL-2.0-only
30f0db065SSteven Rostedt (Red Hat)#
40f0db065SSteven Rostedt (Red Hat)# Copyright 2015 - Steven Rostedt, Red Hat Inc.
50f0db065SSteven Rostedt (Red Hat)# Copyright 2017 - Steven Rostedt, VMware, Inc.
60f0db065SSteven Rostedt (Red Hat)#
70f0db065SSteven Rostedt (Red Hat)
80f0db065SSteven Rostedt (Red Hat)# usage:
90f0db065SSteven Rostedt (Red Hat)#  config-bisect.pl [options] good-config bad-config [good|bad]
100f0db065SSteven Rostedt (Red Hat)#
110f0db065SSteven Rostedt (Red Hat)
120f0db065SSteven Rostedt (Red Hat)# Compares a good config to a bad config, then takes half of the diffs
130f0db065SSteven Rostedt (Red Hat)# and produces a config that is somewhere between the good config and
140f0db065SSteven Rostedt (Red Hat)# the bad config. That is, the resulting config will start with the
150f0db065SSteven Rostedt (Red Hat)# good config and will try to make half of the differences of between
160f0db065SSteven Rostedt (Red Hat)# the good and bad configs match the bad config. It tries because of
170f0db065SSteven Rostedt (Red Hat)# dependencies between the two configs it may not be able to change
180f0db065SSteven Rostedt (Red Hat)# exactly half of the configs that are different between the two config
190f0db065SSteven Rostedt (Red Hat)# files.
200f0db065SSteven Rostedt (Red Hat)
210f0db065SSteven Rostedt (Red Hat)# Here's a normal way to use it:
220f0db065SSteven Rostedt (Red Hat)#
230f0db065SSteven Rostedt (Red Hat)#  $ cd /path/to/linux/kernel
240f0db065SSteven Rostedt (Red Hat)#  $ config-bisect.pl /path/to/good/config /path/to/bad/config
250f0db065SSteven Rostedt (Red Hat)
260f0db065SSteven Rostedt (Red Hat)# This will now pull in good config (blowing away .config in that directory
270f0db065SSteven Rostedt (Red Hat)# so do not make that be one of the good or bad configs), and then
280f0db065SSteven Rostedt (Red Hat)# build the config with "make oldconfig" to make sure it matches the
290f0db065SSteven Rostedt (Red Hat)# current kernel. It will then store the configs in that result for
300f0db065SSteven Rostedt (Red Hat)# the good config. It does the same for the bad config as well.
310f0db065SSteven Rostedt (Red Hat)# The algorithm will run, merging half of the differences between
320f0db065SSteven Rostedt (Red Hat)# the two configs and building them with "make oldconfig" to make sure
330f0db065SSteven Rostedt (Red Hat)# the result changes (dependencies may reset changes the tool had made).
340f0db065SSteven Rostedt (Red Hat)# It then copies the result of its good config to /path/to/good/config.tmp
350f0db065SSteven Rostedt (Red Hat)# and the bad config to /path/to/bad/config.tmp (just appends ".tmp" to the
360f0db065SSteven Rostedt (Red Hat)# files passed in). And the ".config" that you should test will be in
370f0db065SSteven Rostedt (Red Hat)# directory
380f0db065SSteven Rostedt (Red Hat)
390f0db065SSteven Rostedt (Red Hat)# After the first run, determine if the result is good or bad then
400f0db065SSteven Rostedt (Red Hat)# run the same command appending the result
410f0db065SSteven Rostedt (Red Hat)
420f0db065SSteven Rostedt (Red Hat)# For good results:
430f0db065SSteven Rostedt (Red Hat)#  $ config-bisect.pl /path/to/good/config /path/to/bad/config good
440f0db065SSteven Rostedt (Red Hat)
450f0db065SSteven Rostedt (Red Hat)# For bad results:
460f0db065SSteven Rostedt (Red Hat)#  $ config-bisect.pl /path/to/good/config /path/to/bad/config bad
470f0db065SSteven Rostedt (Red Hat)
480f0db065SSteven Rostedt (Red Hat)# Do not change the good-config or bad-config, config-bisect.pl will
490f0db065SSteven Rostedt (Red Hat)# copy the good-config to a temp file with the same name as good-config
500f0db065SSteven Rostedt (Red Hat)# but with a ".tmp" after it. It will do the same with the bad-config.
510f0db065SSteven Rostedt (Red Hat)
520f0db065SSteven Rostedt (Red Hat)# If "good" or "bad" is not stated at the end, it will copy the good and
530f0db065SSteven Rostedt (Red Hat)# bad configs to the .tmp versions. If a .tmp version already exists, it will
54133087f0SSteven Rostedt (VMware)# warn before writing over them (-r will not warn, and just write over them).
55133087f0SSteven Rostedt (VMware)# If the last config is labeled "good", then it will copy it to the good .tmp
56133087f0SSteven Rostedt (VMware)# version. If the last config is labeled "bad", it will copy it to the bad
57133087f0SSteven Rostedt (VMware)# .tmp version. It will continue this until it can not merge the two any more
58133087f0SSteven Rostedt (VMware)# without the result being equal to either the good or bad .tmp configs.
590f0db065SSteven Rostedt (Red Hat)
600f0db065SSteven Rostedt (Red Hat)my $start = 0;
610f0db065SSteven Rostedt (Red Hat)my $val = "";
620f0db065SSteven Rostedt (Red Hat)
630f0db065SSteven Rostedt (Red Hat)my $pwd = `pwd`;
640f0db065SSteven Rostedt (Red Hat)chomp $pwd;
650f0db065SSteven Rostedt (Red Hat)my $tree = $pwd;
660f0db065SSteven Rostedt (Red Hat)my $build;
670f0db065SSteven Rostedt (Red Hat)
680f0db065SSteven Rostedt (Red Hat)my $output_config;
69133087f0SSteven Rostedt (VMware)my $reset_bisect;
700f0db065SSteven Rostedt (Red Hat)
710f0db065SSteven Rostedt (Red Hat)sub usage {
720f0db065SSteven Rostedt (Red Hat)    print << "EOF"
730f0db065SSteven Rostedt (Red Hat)
740f0db065SSteven Rostedt (Red Hat)usage: config-bisect.pl [-l linux-tree][-b build-dir] good-config bad-config [good|bad]
750f0db065SSteven Rostedt (Red Hat)  -l [optional] define location of linux-tree (default is current directory)
760f0db065SSteven Rostedt (Red Hat)  -b [optional] define location to build (O=build-dir) (default is linux-tree)
770f0db065SSteven Rostedt (Red Hat)  good-config the config that is considered good
780f0db065SSteven Rostedt (Red Hat)  bad-config the config that does not work
790f0db065SSteven Rostedt (Red Hat)  "good" add this if the last run produced a good config
800f0db065SSteven Rostedt (Red Hat)  "bad" add this if the last run produced a bad config
810f0db065SSteven Rostedt (Red Hat)  If "good" or "bad" is not specified, then it is the start of a new bisect
820f0db065SSteven Rostedt (Red Hat)
830f0db065SSteven Rostedt (Red Hat)  Note, each run will create copy of good and bad configs with ".tmp" appended.
840f0db065SSteven Rostedt (Red Hat)
850f0db065SSteven Rostedt (Red Hat)EOF
860f0db065SSteven Rostedt (Red Hat);
870f0db065SSteven Rostedt (Red Hat)
880f0db065SSteven Rostedt (Red Hat)    exit(-1);
890f0db065SSteven Rostedt (Red Hat)}
900f0db065SSteven Rostedt (Red Hat)
910f0db065SSteven Rostedt (Red Hat)sub doprint {
920f0db065SSteven Rostedt (Red Hat)    print @_;
930f0db065SSteven Rostedt (Red Hat)}
940f0db065SSteven Rostedt (Red Hat)
950f0db065SSteven Rostedt (Red Hat)sub dodie {
960f0db065SSteven Rostedt (Red Hat)    doprint "CRITICAL FAILURE... ", @_, "\n";
970f0db065SSteven Rostedt (Red Hat)
980f0db065SSteven Rostedt (Red Hat)    die @_, "\n";
990f0db065SSteven Rostedt (Red Hat)}
1000f0db065SSteven Rostedt (Red Hat)
1010f0db065SSteven Rostedt (Red Hat)sub expand_path {
1020f0db065SSteven Rostedt (Red Hat)    my ($file) = @_;
1030f0db065SSteven Rostedt (Red Hat)
1040f0db065SSteven Rostedt (Red Hat)    if ($file =~ m,^/,) {
1050f0db065SSteven Rostedt (Red Hat)	return $file;
1060f0db065SSteven Rostedt (Red Hat)    }
1070f0db065SSteven Rostedt (Red Hat)    return "$pwd/$file";
1080f0db065SSteven Rostedt (Red Hat)}
1090f0db065SSteven Rostedt (Red Hat)
1100f0db065SSteven Rostedt (Red Hat)sub read_prompt {
1110f0db065SSteven Rostedt (Red Hat)    my ($cancel, $prompt) = @_;
1120f0db065SSteven Rostedt (Red Hat)
1130f0db065SSteven Rostedt (Red Hat)    my $ans;
1140f0db065SSteven Rostedt (Red Hat)
1150f0db065SSteven Rostedt (Red Hat)    for (;;) {
1160f0db065SSteven Rostedt (Red Hat)	if ($cancel) {
1170f0db065SSteven Rostedt (Red Hat)	    print "$prompt [y/n/C] ";
1180f0db065SSteven Rostedt (Red Hat)	} else {
1190f0db065SSteven Rostedt (Red Hat)	    print "$prompt [y/N] ";
1200f0db065SSteven Rostedt (Red Hat)	}
1210f0db065SSteven Rostedt (Red Hat)	$ans = <STDIN>;
1220f0db065SSteven Rostedt (Red Hat)	chomp $ans;
1230f0db065SSteven Rostedt (Red Hat)	if ($ans =~ /^\s*$/) {
1240f0db065SSteven Rostedt (Red Hat)	    if ($cancel) {
1250f0db065SSteven Rostedt (Red Hat)		$ans = "c";
1260f0db065SSteven Rostedt (Red Hat)	    } else {
1270f0db065SSteven Rostedt (Red Hat)		$ans = "n";
1280f0db065SSteven Rostedt (Red Hat)	    }
1290f0db065SSteven Rostedt (Red Hat)	}
1300f0db065SSteven Rostedt (Red Hat)	last if ($ans =~ /^y$/i || $ans =~ /^n$/i);
1310f0db065SSteven Rostedt (Red Hat)	if ($cancel) {
1320f0db065SSteven Rostedt (Red Hat)	    last if ($ans =~ /^c$/i);
1330f0db065SSteven Rostedt (Red Hat)	    print "Please answer either 'y', 'n' or 'c'.\n";
1340f0db065SSteven Rostedt (Red Hat)	} else {
1350f0db065SSteven Rostedt (Red Hat)	    print "Please answer either 'y' or 'n'.\n";
1360f0db065SSteven Rostedt (Red Hat)	}
1370f0db065SSteven Rostedt (Red Hat)    }
1380f0db065SSteven Rostedt (Red Hat)    if ($ans =~ /^c/i) {
1390f0db065SSteven Rostedt (Red Hat)	exit;
1400f0db065SSteven Rostedt (Red Hat)    }
1410f0db065SSteven Rostedt (Red Hat)    if ($ans !~ /^y$/i) {
1420f0db065SSteven Rostedt (Red Hat)	return 0;
1430f0db065SSteven Rostedt (Red Hat)    }
1440f0db065SSteven Rostedt (Red Hat)    return 1;
1450f0db065SSteven Rostedt (Red Hat)}
1460f0db065SSteven Rostedt (Red Hat)
1470f0db065SSteven Rostedt (Red Hat)sub read_yn {
1480f0db065SSteven Rostedt (Red Hat)    my ($prompt) = @_;
1490f0db065SSteven Rostedt (Red Hat)
1500f0db065SSteven Rostedt (Red Hat)    return read_prompt 0, $prompt;
1510f0db065SSteven Rostedt (Red Hat)}
1520f0db065SSteven Rostedt (Red Hat)
1530f0db065SSteven Rostedt (Red Hat)sub read_ync {
1540f0db065SSteven Rostedt (Red Hat)    my ($prompt) = @_;
1550f0db065SSteven Rostedt (Red Hat)
1560f0db065SSteven Rostedt (Red Hat)    return read_prompt 1, $prompt;
1570f0db065SSteven Rostedt (Red Hat)}
1580f0db065SSteven Rostedt (Red Hat)
1590f0db065SSteven Rostedt (Red Hat)sub run_command {
1600f0db065SSteven Rostedt (Red Hat)    my ($command, $redirect) = @_;
1610f0db065SSteven Rostedt (Red Hat)    my $start_time;
1620f0db065SSteven Rostedt (Red Hat)    my $end_time;
1630f0db065SSteven Rostedt (Red Hat)    my $dord = 0;
1640f0db065SSteven Rostedt (Red Hat)    my $pid;
1650f0db065SSteven Rostedt (Red Hat)
1660f0db065SSteven Rostedt (Red Hat)    $start_time = time;
1670f0db065SSteven Rostedt (Red Hat)
1680f0db065SSteven Rostedt (Red Hat)    doprint("$command ... ");
1690f0db065SSteven Rostedt (Red Hat)
1700f0db065SSteven Rostedt (Red Hat)    $pid = open(CMD, "$command 2>&1 |") or
1710f0db065SSteven Rostedt (Red Hat)	dodie "unable to exec $command";
1720f0db065SSteven Rostedt (Red Hat)
1730f0db065SSteven Rostedt (Red Hat)    if (defined($redirect)) {
1740f0db065SSteven Rostedt (Red Hat)	open (RD, ">$redirect") or
1750f0db065SSteven Rostedt (Red Hat)	    dodie "failed to write to redirect $redirect";
1760f0db065SSteven Rostedt (Red Hat)	$dord = 1;
1770f0db065SSteven Rostedt (Red Hat)    }
1780f0db065SSteven Rostedt (Red Hat)
1790f0db065SSteven Rostedt (Red Hat)    while (<CMD>) {
1800f0db065SSteven Rostedt (Red Hat)	print RD  if ($dord);
1810f0db065SSteven Rostedt (Red Hat)    }
1820f0db065SSteven Rostedt (Red Hat)
1830f0db065SSteven Rostedt (Red Hat)    waitpid($pid, 0);
1840f0db065SSteven Rostedt (Red Hat)    my $failed = $?;
1850f0db065SSteven Rostedt (Red Hat)
1860f0db065SSteven Rostedt (Red Hat)    close(CMD);
1870f0db065SSteven Rostedt (Red Hat)    close(RD)  if ($dord);
1880f0db065SSteven Rostedt (Red Hat)
1890f0db065SSteven Rostedt (Red Hat)    $end_time = time;
1900f0db065SSteven Rostedt (Red Hat)    my $delta = $end_time - $start_time;
1910f0db065SSteven Rostedt (Red Hat)
1920f0db065SSteven Rostedt (Red Hat)    if ($delta == 1) {
1930f0db065SSteven Rostedt (Red Hat)	doprint "[1 second] ";
1940f0db065SSteven Rostedt (Red Hat)    } else {
1950f0db065SSteven Rostedt (Red Hat)	doprint "[$delta seconds] ";
1960f0db065SSteven Rostedt (Red Hat)    }
1970f0db065SSteven Rostedt (Red Hat)
1980f0db065SSteven Rostedt (Red Hat)    if ($failed) {
1990f0db065SSteven Rostedt (Red Hat)	doprint "FAILED!\n";
2000f0db065SSteven Rostedt (Red Hat)    } else {
2010f0db065SSteven Rostedt (Red Hat)	doprint "SUCCESS\n";
2020f0db065SSteven Rostedt (Red Hat)    }
2030f0db065SSteven Rostedt (Red Hat)
2040f0db065SSteven Rostedt (Red Hat)    return !$failed;
2050f0db065SSteven Rostedt (Red Hat)}
2060f0db065SSteven Rostedt (Red Hat)
2070f0db065SSteven Rostedt (Red Hat)###### CONFIG BISECT ######
2080f0db065SSteven Rostedt (Red Hat)
2090f0db065SSteven Rostedt (Red Hat)# config_ignore holds the configs that were set (or unset) for
2100f0db065SSteven Rostedt (Red Hat)# a good config and we will ignore these configs for the rest
2110f0db065SSteven Rostedt (Red Hat)# of a config bisect. These configs stay as they were.
2120f0db065SSteven Rostedt (Red Hat)my %config_ignore;
2130f0db065SSteven Rostedt (Red Hat)
2140f0db065SSteven Rostedt (Red Hat)# config_set holds what all configs were set as.
2150f0db065SSteven Rostedt (Red Hat)my %config_set;
2160f0db065SSteven Rostedt (Red Hat)
2170f0db065SSteven Rostedt (Red Hat)# config_off holds the set of configs that the bad config had disabled.
2180f0db065SSteven Rostedt (Red Hat)# We need to record them and set them in the .config when running
2190f0db065SSteven Rostedt (Red Hat)# olddefconfig, because olddefconfig keeps the defaults.
2200f0db065SSteven Rostedt (Red Hat)my %config_off;
2210f0db065SSteven Rostedt (Red Hat)
2220f0db065SSteven Rostedt (Red Hat)# config_off_tmp holds a set of configs to turn off for now
2230f0db065SSteven Rostedt (Red Hat)my @config_off_tmp;
2240f0db065SSteven Rostedt (Red Hat)
2250f0db065SSteven Rostedt (Red Hat)# config_list is the set of configs that are being tested
2260f0db065SSteven Rostedt (Red Hat)my %config_list;
2270f0db065SSteven Rostedt (Red Hat)my %null_config;
2280f0db065SSteven Rostedt (Red Hat)
2290f0db065SSteven Rostedt (Red Hat)my %dependency;
2300f0db065SSteven Rostedt (Red Hat)
2310f0db065SSteven Rostedt (Red Hat)my $make;
2320f0db065SSteven Rostedt (Red Hat)
2330f0db065SSteven Rostedt (Red Hat)sub make_oldconfig {
2340f0db065SSteven Rostedt (Red Hat)
2350f0db065SSteven Rostedt (Red Hat)    if (!run_command "$make olddefconfig") {
2360f0db065SSteven Rostedt (Red Hat)	# Perhaps olddefconfig doesn't exist in this version of the kernel
2370f0db065SSteven Rostedt (Red Hat)	# try oldnoconfig
2380f0db065SSteven Rostedt (Red Hat)	doprint "olddefconfig failed, trying make oldnoconfig\n";
2390f0db065SSteven Rostedt (Red Hat)	if (!run_command "$make oldnoconfig") {
2400f0db065SSteven Rostedt (Red Hat)	    doprint "oldnoconfig failed, trying yes '' | make oldconfig\n";
2410f0db065SSteven Rostedt (Red Hat)	    # try a yes '' | oldconfig
2420f0db065SSteven Rostedt (Red Hat)	    run_command "yes '' | $make oldconfig" or
2430f0db065SSteven Rostedt (Red Hat)		dodie "failed make config oldconfig";
2440f0db065SSteven Rostedt (Red Hat)	}
2450f0db065SSteven Rostedt (Red Hat)    }
2460f0db065SSteven Rostedt (Red Hat)}
2470f0db065SSteven Rostedt (Red Hat)
2480f0db065SSteven Rostedt (Red Hat)sub assign_configs {
2490f0db065SSteven Rostedt (Red Hat)    my ($hash, $config) = @_;
2500f0db065SSteven Rostedt (Red Hat)
2510f0db065SSteven Rostedt (Red Hat)    doprint "Reading configs from $config\n";
2520f0db065SSteven Rostedt (Red Hat)
2530f0db065SSteven Rostedt (Red Hat)    open (IN, $config)
2540f0db065SSteven Rostedt (Red Hat)	or dodie "Failed to read $config";
2550f0db065SSteven Rostedt (Red Hat)
2560f0db065SSteven Rostedt (Red Hat)    while (<IN>) {
2570f0db065SSteven Rostedt (Red Hat)	chomp;
2580f0db065SSteven Rostedt (Red Hat)	if (/^((CONFIG\S*)=.*)/) {
2590f0db065SSteven Rostedt (Red Hat)	    ${$hash}{$2} = $1;
2600f0db065SSteven Rostedt (Red Hat)	} elsif (/^(# (CONFIG\S*) is not set)/) {
2610f0db065SSteven Rostedt (Red Hat)	    ${$hash}{$2} = $1;
2620f0db065SSteven Rostedt (Red Hat)	}
2630f0db065SSteven Rostedt (Red Hat)    }
2640f0db065SSteven Rostedt (Red Hat)
2650f0db065SSteven Rostedt (Red Hat)    close(IN);
2660f0db065SSteven Rostedt (Red Hat)}
2670f0db065SSteven Rostedt (Red Hat)
2680f0db065SSteven Rostedt (Red Hat)sub process_config_ignore {
2690f0db065SSteven Rostedt (Red Hat)    my ($config) = @_;
2700f0db065SSteven Rostedt (Red Hat)
2710f0db065SSteven Rostedt (Red Hat)    assign_configs \%config_ignore, $config;
2720f0db065SSteven Rostedt (Red Hat)}
2730f0db065SSteven Rostedt (Red Hat)
2740f0db065SSteven Rostedt (Red Hat)sub get_dependencies {
2750f0db065SSteven Rostedt (Red Hat)    my ($config) = @_;
2760f0db065SSteven Rostedt (Red Hat)
2770f0db065SSteven Rostedt (Red Hat)    my $arr = $dependency{$config};
2780f0db065SSteven Rostedt (Red Hat)    if (!defined($arr)) {
2790f0db065SSteven Rostedt (Red Hat)	return ();
2800f0db065SSteven Rostedt (Red Hat)    }
2810f0db065SSteven Rostedt (Red Hat)
2820f0db065SSteven Rostedt (Red Hat)    my @deps = @{$arr};
2830f0db065SSteven Rostedt (Red Hat)
2840f0db065SSteven Rostedt (Red Hat)    foreach my $dep (@{$arr}) {
2850f0db065SSteven Rostedt (Red Hat)	print "ADD DEP $dep\n";
2860f0db065SSteven Rostedt (Red Hat)	@deps = (@deps, get_dependencies $dep);
2870f0db065SSteven Rostedt (Red Hat)    }
2880f0db065SSteven Rostedt (Red Hat)
2890f0db065SSteven Rostedt (Red Hat)    return @deps;
2900f0db065SSteven Rostedt (Red Hat)}
2910f0db065SSteven Rostedt (Red Hat)
2920f0db065SSteven Rostedt (Red Hat)sub save_config {
2930f0db065SSteven Rostedt (Red Hat)    my ($pc, $file) = @_;
2940f0db065SSteven Rostedt (Red Hat)
2950f0db065SSteven Rostedt (Red Hat)    my %configs = %{$pc};
2960f0db065SSteven Rostedt (Red Hat)
2970f0db065SSteven Rostedt (Red Hat)    doprint "Saving configs into $file\n";
2980f0db065SSteven Rostedt (Red Hat)
2990f0db065SSteven Rostedt (Red Hat)    open(OUT, ">$file") or dodie "Can not write to $file";
3000f0db065SSteven Rostedt (Red Hat)
3010f0db065SSteven Rostedt (Red Hat)    foreach my $config (keys %configs) {
3020f0db065SSteven Rostedt (Red Hat)	print OUT "$configs{$config}\n";
3030f0db065SSteven Rostedt (Red Hat)    }
3040f0db065SSteven Rostedt (Red Hat)    close(OUT);
3050f0db065SSteven Rostedt (Red Hat)}
3060f0db065SSteven Rostedt (Red Hat)
3070f0db065SSteven Rostedt (Red Hat)sub create_config {
3080f0db065SSteven Rostedt (Red Hat)    my ($name, $pc) = @_;
3090f0db065SSteven Rostedt (Red Hat)
3100f0db065SSteven Rostedt (Red Hat)    doprint "Creating old config from $name configs\n";
3110f0db065SSteven Rostedt (Red Hat)
3120f0db065SSteven Rostedt (Red Hat)    save_config $pc, $output_config;
3130f0db065SSteven Rostedt (Red Hat)
3140f0db065SSteven Rostedt (Red Hat)    make_oldconfig;
3150f0db065SSteven Rostedt (Red Hat)}
3160f0db065SSteven Rostedt (Red Hat)
3170f0db065SSteven Rostedt (Red Hat)# compare two config hashes, and return configs with different vals.
3180f0db065SSteven Rostedt (Red Hat)# It returns B's config values, but you can use A to see what A was.
3190f0db065SSteven Rostedt (Red Hat)sub diff_config_vals {
3200f0db065SSteven Rostedt (Red Hat)    my ($pa, $pb) = @_;
3210f0db065SSteven Rostedt (Red Hat)
3220f0db065SSteven Rostedt (Red Hat)    # crappy Perl way to pass in hashes.
3230f0db065SSteven Rostedt (Red Hat)    my %a = %{$pa};
3240f0db065SSteven Rostedt (Red Hat)    my %b = %{$pb};
3250f0db065SSteven Rostedt (Red Hat)
3260f0db065SSteven Rostedt (Red Hat)    my %ret;
3270f0db065SSteven Rostedt (Red Hat)
3280f0db065SSteven Rostedt (Red Hat)    foreach my $item (keys %a) {
3290f0db065SSteven Rostedt (Red Hat)	if (defined($b{$item}) && $b{$item} ne $a{$item}) {
3300f0db065SSteven Rostedt (Red Hat)	    $ret{$item} = $b{$item};
3310f0db065SSteven Rostedt (Red Hat)	}
3320f0db065SSteven Rostedt (Red Hat)    }
3330f0db065SSteven Rostedt (Red Hat)
3340f0db065SSteven Rostedt (Red Hat)    return %ret;
3350f0db065SSteven Rostedt (Red Hat)}
3360f0db065SSteven Rostedt (Red Hat)
3370f0db065SSteven Rostedt (Red Hat)# compare two config hashes and return the configs in B but not A
3380f0db065SSteven Rostedt (Red Hat)sub diff_configs {
3390f0db065SSteven Rostedt (Red Hat)    my ($pa, $pb) = @_;
3400f0db065SSteven Rostedt (Red Hat)
3410f0db065SSteven Rostedt (Red Hat)    my %ret;
3420f0db065SSteven Rostedt (Red Hat)
3430f0db065SSteven Rostedt (Red Hat)    # crappy Perl way to pass in hashes.
3440f0db065SSteven Rostedt (Red Hat)    my %a = %{$pa};
3450f0db065SSteven Rostedt (Red Hat)    my %b = %{$pb};
3460f0db065SSteven Rostedt (Red Hat)
3470f0db065SSteven Rostedt (Red Hat)    foreach my $item (keys %b) {
3480f0db065SSteven Rostedt (Red Hat)	if (!defined($a{$item})) {
3490f0db065SSteven Rostedt (Red Hat)	    $ret{$item} = $b{$item};
3500f0db065SSteven Rostedt (Red Hat)	}
3510f0db065SSteven Rostedt (Red Hat)    }
3520f0db065SSteven Rostedt (Red Hat)
3530f0db065SSteven Rostedt (Red Hat)    return %ret;
3540f0db065SSteven Rostedt (Red Hat)}
3550f0db065SSteven Rostedt (Red Hat)
3560f0db065SSteven Rostedt (Red Hat)# return if two configs are equal or not
3570f0db065SSteven Rostedt (Red Hat)# 0 is equal +1 b has something a does not
3580f0db065SSteven Rostedt (Red Hat)# +1 if a and b have a different item.
3590f0db065SSteven Rostedt (Red Hat)# -1 if a has something b does not
3600f0db065SSteven Rostedt (Red Hat)sub compare_configs {
3610f0db065SSteven Rostedt (Red Hat)    my ($pa, $pb) = @_;
3620f0db065SSteven Rostedt (Red Hat)
3630f0db065SSteven Rostedt (Red Hat)    my %ret;
3640f0db065SSteven Rostedt (Red Hat)
3650f0db065SSteven Rostedt (Red Hat)    # crappy Perl way to pass in hashes.
3660f0db065SSteven Rostedt (Red Hat)    my %a = %{$pa};
3670f0db065SSteven Rostedt (Red Hat)    my %b = %{$pb};
3680f0db065SSteven Rostedt (Red Hat)
3690f0db065SSteven Rostedt (Red Hat)    foreach my $item (keys %b) {
3700f0db065SSteven Rostedt (Red Hat)	if (!defined($a{$item})) {
3710f0db065SSteven Rostedt (Red Hat)	    return 1;
3720f0db065SSteven Rostedt (Red Hat)	}
3730f0db065SSteven Rostedt (Red Hat)	if ($a{$item} ne $b{$item}) {
3740f0db065SSteven Rostedt (Red Hat)	    return 1;
3750f0db065SSteven Rostedt (Red Hat)	}
3760f0db065SSteven Rostedt (Red Hat)    }
3770f0db065SSteven Rostedt (Red Hat)
3780f0db065SSteven Rostedt (Red Hat)    foreach my $item (keys %a) {
3790f0db065SSteven Rostedt (Red Hat)	if (!defined($b{$item})) {
3800f0db065SSteven Rostedt (Red Hat)	    return -1;
3810f0db065SSteven Rostedt (Red Hat)	}
3820f0db065SSteven Rostedt (Red Hat)    }
3830f0db065SSteven Rostedt (Red Hat)
3840f0db065SSteven Rostedt (Red Hat)    return 0;
3850f0db065SSteven Rostedt (Red Hat)}
3860f0db065SSteven Rostedt (Red Hat)
3870f0db065SSteven Rostedt (Red Hat)sub process_failed {
3880f0db065SSteven Rostedt (Red Hat)    my ($config) = @_;
3890f0db065SSteven Rostedt (Red Hat)
3900f0db065SSteven Rostedt (Red Hat)    doprint "\n\n***************************************\n";
3910f0db065SSteven Rostedt (Red Hat)    doprint "Found bad config: $config\n";
3920f0db065SSteven Rostedt (Red Hat)    doprint "***************************************\n\n";
3930f0db065SSteven Rostedt (Red Hat)}
3940f0db065SSteven Rostedt (Red Hat)
3950f0db065SSteven Rostedt (Red Hat)sub process_new_config {
3960f0db065SSteven Rostedt (Red Hat)    my ($tc, $nc, $gc, $bc) = @_;
3970f0db065SSteven Rostedt (Red Hat)
3980f0db065SSteven Rostedt (Red Hat)    my %tmp_config = %{$tc};
3990f0db065SSteven Rostedt (Red Hat)    my %good_configs = %{$gc};
4000f0db065SSteven Rostedt (Red Hat)    my %bad_configs = %{$bc};
4010f0db065SSteven Rostedt (Red Hat)
4020f0db065SSteven Rostedt (Red Hat)    my %new_configs;
4030f0db065SSteven Rostedt (Red Hat)
4040f0db065SSteven Rostedt (Red Hat)    my $runtest = 1;
4050f0db065SSteven Rostedt (Red Hat)    my $ret;
4060f0db065SSteven Rostedt (Red Hat)
4070f0db065SSteven Rostedt (Red Hat)    create_config "tmp_configs", \%tmp_config;
4080f0db065SSteven Rostedt (Red Hat)    assign_configs \%new_configs, $output_config;
4090f0db065SSteven Rostedt (Red Hat)
4100f0db065SSteven Rostedt (Red Hat)    $ret = compare_configs \%new_configs, \%bad_configs;
4110f0db065SSteven Rostedt (Red Hat)    if (!$ret) {
4120f0db065SSteven Rostedt (Red Hat)	doprint "New config equals bad config, try next test\n";
4130f0db065SSteven Rostedt (Red Hat)	$runtest = 0;
4140f0db065SSteven Rostedt (Red Hat)    }
4150f0db065SSteven Rostedt (Red Hat)
4160f0db065SSteven Rostedt (Red Hat)    if ($runtest) {
4170f0db065SSteven Rostedt (Red Hat)	$ret = compare_configs \%new_configs, \%good_configs;
4180f0db065SSteven Rostedt (Red Hat)	if (!$ret) {
4190f0db065SSteven Rostedt (Red Hat)	    doprint "New config equals good config, try next test\n";
4200f0db065SSteven Rostedt (Red Hat)	    $runtest = 0;
4210f0db065SSteven Rostedt (Red Hat)	}
4220f0db065SSteven Rostedt (Red Hat)    }
4230f0db065SSteven Rostedt (Red Hat)
4240f0db065SSteven Rostedt (Red Hat)    %{$nc} = %new_configs;
4250f0db065SSteven Rostedt (Red Hat)
4260f0db065SSteven Rostedt (Red Hat)    return $runtest;
4270f0db065SSteven Rostedt (Red Hat)}
4280f0db065SSteven Rostedt (Red Hat)
4290f0db065SSteven Rostedt (Red Hat)sub convert_config {
4300f0db065SSteven Rostedt (Red Hat)    my ($config) = @_;
4310f0db065SSteven Rostedt (Red Hat)
4320f0db065SSteven Rostedt (Red Hat)    if ($config =~ /^# (.*) is not set/) {
4330f0db065SSteven Rostedt (Red Hat)	$config = "$1=n";
4340f0db065SSteven Rostedt (Red Hat)    }
4350f0db065SSteven Rostedt (Red Hat)
4360f0db065SSteven Rostedt (Red Hat)    $config =~ s/^CONFIG_//;
4370f0db065SSteven Rostedt (Red Hat)    return $config;
4380f0db065SSteven Rostedt (Red Hat)}
4390f0db065SSteven Rostedt (Red Hat)
4400f0db065SSteven Rostedt (Red Hat)sub print_config {
4410f0db065SSteven Rostedt (Red Hat)    my ($sym, $config) = @_;
4420f0db065SSteven Rostedt (Red Hat)
4430f0db065SSteven Rostedt (Red Hat)    $config = convert_config $config;
4440f0db065SSteven Rostedt (Red Hat)    doprint "$sym$config\n";
4450f0db065SSteven Rostedt (Red Hat)}
4460f0db065SSteven Rostedt (Red Hat)
4470f0db065SSteven Rostedt (Red Hat)sub print_config_compare {
4480f0db065SSteven Rostedt (Red Hat)    my ($good_config, $bad_config) = @_;
4490f0db065SSteven Rostedt (Red Hat)
4500f0db065SSteven Rostedt (Red Hat)    $good_config = convert_config $good_config;
4510f0db065SSteven Rostedt (Red Hat)    $bad_config = convert_config $bad_config;
4520f0db065SSteven Rostedt (Red Hat)
4530f0db065SSteven Rostedt (Red Hat)    my $good_value = $good_config;
4540f0db065SSteven Rostedt (Red Hat)    my $bad_value = $bad_config;
4550f0db065SSteven Rostedt (Red Hat)    $good_value =~ s/(.*)=//;
4560f0db065SSteven Rostedt (Red Hat)    my $config = $1;
4570f0db065SSteven Rostedt (Red Hat)
4580f0db065SSteven Rostedt (Red Hat)    $bad_value =~ s/.*=//;
4590f0db065SSteven Rostedt (Red Hat)
4600f0db065SSteven Rostedt (Red Hat)    doprint " $config $good_value -> $bad_value\n";
4610f0db065SSteven Rostedt (Red Hat)}
4620f0db065SSteven Rostedt (Red Hat)
4630f0db065SSteven Rostedt (Red Hat)# Pass in:
4640f0db065SSteven Rostedt (Red Hat)# $phalf: half of the configs names you want to add
4650f0db065SSteven Rostedt (Red Hat)# $oconfigs: The orginial configs to start with
4660f0db065SSteven Rostedt (Red Hat)# $sconfigs: The source to update $oconfigs with (from $phalf)
4670f0db065SSteven Rostedt (Red Hat)# $which: The name of which half that is updating (top / bottom)
4680f0db065SSteven Rostedt (Red Hat)# $type: The name of the source type (good / bad)
4690f0db065SSteven Rostedt (Red Hat)sub make_half {
4700f0db065SSteven Rostedt (Red Hat)    my ($phalf, $oconfigs, $sconfigs, $which, $type) = @_;
4710f0db065SSteven Rostedt (Red Hat)
4720f0db065SSteven Rostedt (Red Hat)    my @half = @{$phalf};
4730f0db065SSteven Rostedt (Red Hat)    my %orig_configs = %{$oconfigs};
4740f0db065SSteven Rostedt (Red Hat)    my %source_configs = %{$sconfigs};
4750f0db065SSteven Rostedt (Red Hat)
4760f0db065SSteven Rostedt (Red Hat)    my %tmp_config = %orig_configs;
4770f0db065SSteven Rostedt (Red Hat)
4780f0db065SSteven Rostedt (Red Hat)    doprint "Settings bisect with $which half of $type configs:\n";
4790f0db065SSteven Rostedt (Red Hat)    foreach my $item (@half) {
4800f0db065SSteven Rostedt (Red Hat)	doprint "Updating $item to $source_configs{$item}\n";
4810f0db065SSteven Rostedt (Red Hat)	$tmp_config{$item} = $source_configs{$item};
4820f0db065SSteven Rostedt (Red Hat)    }
4830f0db065SSteven Rostedt (Red Hat)
4840f0db065SSteven Rostedt (Red Hat)    return %tmp_config;
4850f0db065SSteven Rostedt (Red Hat)}
4860f0db065SSteven Rostedt (Red Hat)
4870f0db065SSteven Rostedt (Red Hat)sub run_config_bisect {
4880f0db065SSteven Rostedt (Red Hat)    my ($pgood, $pbad) = @_;
4890f0db065SSteven Rostedt (Red Hat)
4900f0db065SSteven Rostedt (Red Hat)    my %good_configs = %{$pgood};
4910f0db065SSteven Rostedt (Red Hat)    my %bad_configs = %{$pbad};
4920f0db065SSteven Rostedt (Red Hat)
4930f0db065SSteven Rostedt (Red Hat)    my %diff_configs = diff_config_vals \%good_configs, \%bad_configs;
4940f0db065SSteven Rostedt (Red Hat)    my %b_configs = diff_configs \%good_configs, \%bad_configs;
4950f0db065SSteven Rostedt (Red Hat)    my %g_configs = diff_configs \%bad_configs, \%good_configs;
4960f0db065SSteven Rostedt (Red Hat)
4970f0db065SSteven Rostedt (Red Hat)    # diff_arr is what is in both good and bad but are different (y->n)
4980f0db065SSteven Rostedt (Red Hat)    my @diff_arr = keys %diff_configs;
4990f0db065SSteven Rostedt (Red Hat)    my $len_diff = $#diff_arr + 1;
5000f0db065SSteven Rostedt (Red Hat)
5010f0db065SSteven Rostedt (Red Hat)    # b_arr is what is in bad but not in good (has depends)
5020f0db065SSteven Rostedt (Red Hat)    my @b_arr = keys %b_configs;
5030f0db065SSteven Rostedt (Red Hat)    my $len_b = $#b_arr + 1;
5040f0db065SSteven Rostedt (Red Hat)
5050f0db065SSteven Rostedt (Red Hat)    # g_arr is what is in good but not in bad
5060f0db065SSteven Rostedt (Red Hat)    my @g_arr = keys %g_configs;
5070f0db065SSteven Rostedt (Red Hat)    my $len_g = $#g_arr + 1;
5080f0db065SSteven Rostedt (Red Hat)
5090f0db065SSteven Rostedt (Red Hat)    my $runtest = 0;
5100f0db065SSteven Rostedt (Red Hat)    my %new_configs;
5110f0db065SSteven Rostedt (Red Hat)    my $ret;
5120f0db065SSteven Rostedt (Red Hat)
5130f0db065SSteven Rostedt (Red Hat)    # Look at the configs that are different between good and bad.
5140f0db065SSteven Rostedt (Red Hat)    # This does not include those that depend on other configs
5150f0db065SSteven Rostedt (Red Hat)    #  (configs depending on other configs that are not set would
5160f0db065SSteven Rostedt (Red Hat)    #   not show up even as a "# CONFIG_FOO is not set"
5170f0db065SSteven Rostedt (Red Hat)
5180f0db065SSteven Rostedt (Red Hat)
5190f0db065SSteven Rostedt (Red Hat)    doprint "# of configs to check:             $len_diff\n";
5200f0db065SSteven Rostedt (Red Hat)    doprint "# of configs showing only in good: $len_g\n";
5210f0db065SSteven Rostedt (Red Hat)    doprint "# of configs showing only in bad:  $len_b\n";
5220f0db065SSteven Rostedt (Red Hat)
5230f0db065SSteven Rostedt (Red Hat)    if ($len_diff > 0) {
5240f0db065SSteven Rostedt (Red Hat)	# Now test for different values
5250f0db065SSteven Rostedt (Red Hat)
5260f0db065SSteven Rostedt (Red Hat)	doprint "Configs left to check:\n";
5270f0db065SSteven Rostedt (Red Hat)	doprint "  Good Config\t\t\tBad Config\n";
5280f0db065SSteven Rostedt (Red Hat)	doprint "  -----------\t\t\t----------\n";
5290f0db065SSteven Rostedt (Red Hat)	foreach my $item (@diff_arr) {
5300f0db065SSteven Rostedt (Red Hat)	    doprint "  $good_configs{$item}\t$bad_configs{$item}\n";
5310f0db065SSteven Rostedt (Red Hat)	}
5320f0db065SSteven Rostedt (Red Hat)
5330f0db065SSteven Rostedt (Red Hat)	my $half = int($#diff_arr / 2);
5340f0db065SSteven Rostedt (Red Hat)	my @tophalf = @diff_arr[0 .. $half];
5350f0db065SSteven Rostedt (Red Hat)
5360f0db065SSteven Rostedt (Red Hat)	doprint "Set tmp config to be good config with some bad config values\n";
5370f0db065SSteven Rostedt (Red Hat)
5380f0db065SSteven Rostedt (Red Hat)	my %tmp_config = make_half \@tophalf, \%good_configs,
5390f0db065SSteven Rostedt (Red Hat)	    \%bad_configs, "top", "bad";
5400f0db065SSteven Rostedt (Red Hat)
5410f0db065SSteven Rostedt (Red Hat)	$runtest = process_new_config \%tmp_config, \%new_configs,
5420f0db065SSteven Rostedt (Red Hat)			    \%good_configs, \%bad_configs;
5430f0db065SSteven Rostedt (Red Hat)
5440f0db065SSteven Rostedt (Red Hat)	if (!$runtest) {
5450f0db065SSteven Rostedt (Red Hat)	    doprint "Set tmp config to be bad config with some good config values\n";
5460f0db065SSteven Rostedt (Red Hat)
5470f0db065SSteven Rostedt (Red Hat)	    my %tmp_config = make_half \@tophalf, \%bad_configs,
5480f0db065SSteven Rostedt (Red Hat)		\%good_configs, "top", "good";
5490f0db065SSteven Rostedt (Red Hat)
5500f0db065SSteven Rostedt (Red Hat)	    $runtest = process_new_config \%tmp_config, \%new_configs,
5510f0db065SSteven Rostedt (Red Hat)		\%good_configs, \%bad_configs;
5520f0db065SSteven Rostedt (Red Hat)	}
5530f0db065SSteven Rostedt (Red Hat)    }
5540f0db065SSteven Rostedt (Red Hat)
5550f0db065SSteven Rostedt (Red Hat)    if (!$runtest && $len_diff > 0) {
5560f0db065SSteven Rostedt (Red Hat)	# do the same thing, but this time with bottom half
5570f0db065SSteven Rostedt (Red Hat)
5580f0db065SSteven Rostedt (Red Hat)	my $half = int($#diff_arr / 2);
5590f0db065SSteven Rostedt (Red Hat)	my @bottomhalf = @diff_arr[$half+1 .. $#diff_arr];
5600f0db065SSteven Rostedt (Red Hat)
5610f0db065SSteven Rostedt (Red Hat)	doprint "Set tmp config to be good config with some bad config values\n";
5620f0db065SSteven Rostedt (Red Hat)
5630f0db065SSteven Rostedt (Red Hat)	my %tmp_config = make_half \@bottomhalf, \%good_configs,
5640f0db065SSteven Rostedt (Red Hat)	    \%bad_configs, "bottom", "bad";
5650f0db065SSteven Rostedt (Red Hat)
5660f0db065SSteven Rostedt (Red Hat)	$runtest = process_new_config \%tmp_config, \%new_configs,
5670f0db065SSteven Rostedt (Red Hat)			    \%good_configs, \%bad_configs;
5680f0db065SSteven Rostedt (Red Hat)
5690f0db065SSteven Rostedt (Red Hat)	if (!$runtest) {
5700f0db065SSteven Rostedt (Red Hat)	    doprint "Set tmp config to be bad config with some good config values\n";
5710f0db065SSteven Rostedt (Red Hat)
5720f0db065SSteven Rostedt (Red Hat)	    my %tmp_config = make_half \@bottomhalf, \%bad_configs,
5730f0db065SSteven Rostedt (Red Hat)		\%good_configs, "bottom", "good";
5740f0db065SSteven Rostedt (Red Hat)
5750f0db065SSteven Rostedt (Red Hat)	    $runtest = process_new_config \%tmp_config, \%new_configs,
5760f0db065SSteven Rostedt (Red Hat)		\%good_configs, \%bad_configs;
5770f0db065SSteven Rostedt (Red Hat)	}
5780f0db065SSteven Rostedt (Red Hat)    }
5790f0db065SSteven Rostedt (Red Hat)
5800f0db065SSteven Rostedt (Red Hat)    if ($runtest) {
5810f0db065SSteven Rostedt (Red Hat)	make_oldconfig;
5820f0db065SSteven Rostedt (Red Hat)	doprint "READY TO TEST .config IN $build\n";
5830f0db065SSteven Rostedt (Red Hat)	return 0;
5840f0db065SSteven Rostedt (Red Hat)    }
5850f0db065SSteven Rostedt (Red Hat)
5860f0db065SSteven Rostedt (Red Hat)    doprint "\n%%%%%%%% FAILED TO FIND SINGLE BAD CONFIG %%%%%%%%\n";
5870f0db065SSteven Rostedt (Red Hat)    doprint "Hmm, can't make any more changes without making good == bad?\n";
5880f0db065SSteven Rostedt (Red Hat)    doprint "Difference between good (+) and bad (-)\n";
5890f0db065SSteven Rostedt (Red Hat)
5900f0db065SSteven Rostedt (Red Hat)    foreach my $item (keys %bad_configs) {
5910f0db065SSteven Rostedt (Red Hat)	if (!defined($good_configs{$item})) {
5920f0db065SSteven Rostedt (Red Hat)	    print_config "-", $bad_configs{$item};
5930f0db065SSteven Rostedt (Red Hat)	}
5940f0db065SSteven Rostedt (Red Hat)    }
5950f0db065SSteven Rostedt (Red Hat)
5960f0db065SSteven Rostedt (Red Hat)    foreach my $item (keys %good_configs) {
5970f0db065SSteven Rostedt (Red Hat)	next if (!defined($bad_configs{$item}));
5980f0db065SSteven Rostedt (Red Hat)	if ($good_configs{$item} ne $bad_configs{$item}) {
5990f0db065SSteven Rostedt (Red Hat)	    print_config_compare $good_configs{$item}, $bad_configs{$item};
6000f0db065SSteven Rostedt (Red Hat)	}
6010f0db065SSteven Rostedt (Red Hat)    }
6020f0db065SSteven Rostedt (Red Hat)
6030f0db065SSteven Rostedt (Red Hat)    foreach my $item (keys %good_configs) {
6040f0db065SSteven Rostedt (Red Hat)	if (!defined($bad_configs{$item})) {
6050f0db065SSteven Rostedt (Red Hat)	    print_config "+", $good_configs{$item};
6060f0db065SSteven Rostedt (Red Hat)	}
6070f0db065SSteven Rostedt (Red Hat)    }
6080f0db065SSteven Rostedt (Red Hat)    return -1;
6090f0db065SSteven Rostedt (Red Hat)}
6100f0db065SSteven Rostedt (Red Hat)
6110f0db065SSteven Rostedt (Red Hat)sub config_bisect {
6120f0db065SSteven Rostedt (Red Hat)    my ($good_config, $bad_config) = @_;
6130f0db065SSteven Rostedt (Red Hat)    my $ret;
6140f0db065SSteven Rostedt (Red Hat)
6150f0db065SSteven Rostedt (Red Hat)    my %good_configs;
6160f0db065SSteven Rostedt (Red Hat)    my %bad_configs;
6170f0db065SSteven Rostedt (Red Hat)    my %tmp_configs;
6180f0db065SSteven Rostedt (Red Hat)
6190f0db065SSteven Rostedt (Red Hat)    doprint "Run good configs through make oldconfig\n";
6200f0db065SSteven Rostedt (Red Hat)    assign_configs \%tmp_configs, $good_config;
6210f0db065SSteven Rostedt (Red Hat)    create_config "$good_config", \%tmp_configs;
6220f0db065SSteven Rostedt (Red Hat)    assign_configs \%good_configs, $output_config;
6230f0db065SSteven Rostedt (Red Hat)
6240f0db065SSteven Rostedt (Red Hat)    doprint "Run bad configs through make oldconfig\n";
6250f0db065SSteven Rostedt (Red Hat)    assign_configs \%tmp_configs, $bad_config;
6260f0db065SSteven Rostedt (Red Hat)    create_config "$bad_config", \%tmp_configs;
6270f0db065SSteven Rostedt (Red Hat)    assign_configs \%bad_configs, $output_config;
6280f0db065SSteven Rostedt (Red Hat)
6290f0db065SSteven Rostedt (Red Hat)    save_config \%good_configs, $good_config;
6300f0db065SSteven Rostedt (Red Hat)    save_config \%bad_configs, $bad_config;
6310f0db065SSteven Rostedt (Red Hat)
6320f0db065SSteven Rostedt (Red Hat)    return run_config_bisect \%good_configs, \%bad_configs;
6330f0db065SSteven Rostedt (Red Hat)}
6340f0db065SSteven Rostedt (Red Hat)
6350f0db065SSteven Rostedt (Red Hat)while ($#ARGV >= 0) {
6360f0db065SSteven Rostedt (Red Hat)    if ($ARGV[0] !~ m/^-/) {
6370f0db065SSteven Rostedt (Red Hat)	last;
6380f0db065SSteven Rostedt (Red Hat)    }
6390f0db065SSteven Rostedt (Red Hat)    my $opt = shift @ARGV;
6400f0db065SSteven Rostedt (Red Hat)
6410f0db065SSteven Rostedt (Red Hat)    if ($opt eq "-b") {
6420f0db065SSteven Rostedt (Red Hat)	$val = shift @ARGV;
6430f0db065SSteven Rostedt (Red Hat)	if (!defined($val)) {
6440f0db065SSteven Rostedt (Red Hat)	    die "-b requires value\n";
6450f0db065SSteven Rostedt (Red Hat)	}
6460f0db065SSteven Rostedt (Red Hat)	$build = $val;
6470f0db065SSteven Rostedt (Red Hat)    }
6480f0db065SSteven Rostedt (Red Hat)
6490f0db065SSteven Rostedt (Red Hat)    elsif ($opt eq "-l") {
6500f0db065SSteven Rostedt (Red Hat)	$val = shift @ARGV;
6510f0db065SSteven Rostedt (Red Hat)	if (!defined($val)) {
6520f0db065SSteven Rostedt (Red Hat)	    die "-l requires value\n";
6530f0db065SSteven Rostedt (Red Hat)	}
6540f0db065SSteven Rostedt (Red Hat)	$tree = $val;
6550f0db065SSteven Rostedt (Red Hat)    }
6560f0db065SSteven Rostedt (Red Hat)
657133087f0SSteven Rostedt (VMware)    elsif ($opt eq "-r") {
658133087f0SSteven Rostedt (VMware)	$reset_bisect = 1;
659133087f0SSteven Rostedt (VMware)    }
660133087f0SSteven Rostedt (VMware)
6610f0db065SSteven Rostedt (Red Hat)    elsif ($opt eq "-h") {
6620f0db065SSteven Rostedt (Red Hat)	usage;
6630f0db065SSteven Rostedt (Red Hat)    }
6640f0db065SSteven Rostedt (Red Hat)
6650f0db065SSteven Rostedt (Red Hat)    else {
666aecea57fSMasanari Iida	die "Unknown option $opt\n";
6670f0db065SSteven Rostedt (Red Hat)    }
6680f0db065SSteven Rostedt (Red Hat)}
6690f0db065SSteven Rostedt (Red Hat)
6700f0db065SSteven Rostedt (Red Hat)$build = $tree if (!defined($build));
6710f0db065SSteven Rostedt (Red Hat)
6720f0db065SSteven Rostedt (Red Hat)$tree = expand_path $tree;
6730f0db065SSteven Rostedt (Red Hat)$build = expand_path $build;
6740f0db065SSteven Rostedt (Red Hat)
6750f0db065SSteven Rostedt (Red Hat)if ( ! -d $tree ) {
6760f0db065SSteven Rostedt (Red Hat)    die "$tree not a directory\n";
6770f0db065SSteven Rostedt (Red Hat)}
6780f0db065SSteven Rostedt (Red Hat)
6790f0db065SSteven Rostedt (Red Hat)if ( ! -d $build ) {
6800f0db065SSteven Rostedt (Red Hat)    die "$build not a directory\n";
6810f0db065SSteven Rostedt (Red Hat)}
6820f0db065SSteven Rostedt (Red Hat)
6830f0db065SSteven Rostedt (Red Hat)usage if $#ARGV < 1;
6840f0db065SSteven Rostedt (Red Hat)
6850f0db065SSteven Rostedt (Red Hat)if ($#ARGV == 1) {
6860f0db065SSteven Rostedt (Red Hat)    $start = 1;
6870f0db065SSteven Rostedt (Red Hat)} elsif ($#ARGV == 2) {
6880f0db065SSteven Rostedt (Red Hat)    $val = $ARGV[2];
6890f0db065SSteven Rostedt (Red Hat)    if ($val ne "good" && $val ne "bad") {
6900f0db065SSteven Rostedt (Red Hat)	die "Unknown command '$val', bust be either \"good\" or \"bad\"\n";
6910f0db065SSteven Rostedt (Red Hat)    }
6920f0db065SSteven Rostedt (Red Hat)} else {
6930f0db065SSteven Rostedt (Red Hat)    usage;
6940f0db065SSteven Rostedt (Red Hat)}
6950f0db065SSteven Rostedt (Red Hat)
6960f0db065SSteven Rostedt (Red Hat)my $good_start = expand_path $ARGV[0];
6970f0db065SSteven Rostedt (Red Hat)my $bad_start = expand_path $ARGV[1];
6980f0db065SSteven Rostedt (Red Hat)
6990f0db065SSteven Rostedt (Red Hat)my $good = "$good_start.tmp";
7000f0db065SSteven Rostedt (Red Hat)my $bad = "$bad_start.tmp";
7010f0db065SSteven Rostedt (Red Hat)
7020f0db065SSteven Rostedt (Red Hat)$make = "make";
7030f0db065SSteven Rostedt (Red Hat)
7040f0db065SSteven Rostedt (Red Hat)if ($build ne $tree) {
7050f0db065SSteven Rostedt (Red Hat)    $make = "make O=$build"
7060f0db065SSteven Rostedt (Red Hat)}
7070f0db065SSteven Rostedt (Red Hat)
7080f0db065SSteven Rostedt (Red Hat)$output_config = "$build/.config";
7090f0db065SSteven Rostedt (Red Hat)
7100f0db065SSteven Rostedt (Red Hat)if ($start) {
7110f0db065SSteven Rostedt (Red Hat)    if ( ! -f $good_start ) {
7120f0db065SSteven Rostedt (Red Hat)	die "$good_start not found\n";
7130f0db065SSteven Rostedt (Red Hat)    }
7140f0db065SSteven Rostedt (Red Hat)    if ( ! -f $bad_start ) {
7150f0db065SSteven Rostedt (Red Hat)	die "$bad_start not found\n";
7160f0db065SSteven Rostedt (Red Hat)    }
7170f0db065SSteven Rostedt (Red Hat)    if ( -f $good || -f $bad ) {
7180f0db065SSteven Rostedt (Red Hat)	my $p = "";
7190f0db065SSteven Rostedt (Red Hat)
7200f0db065SSteven Rostedt (Red Hat)	if ( -f $good ) {
7210f0db065SSteven Rostedt (Red Hat)	    $p = "$good exists\n";
7220f0db065SSteven Rostedt (Red Hat)	}
7230f0db065SSteven Rostedt (Red Hat)
7240f0db065SSteven Rostedt (Red Hat)	if ( -f $bad ) {
7250f0db065SSteven Rostedt (Red Hat)	    $p = "$p$bad exists\n";
7260f0db065SSteven Rostedt (Red Hat)	}
7270f0db065SSteven Rostedt (Red Hat)
728133087f0SSteven Rostedt (VMware)	if (!defined($reset_bisect)) {
7290f0db065SSteven Rostedt (Red Hat)	    if (!read_yn "${p}Overwrite and start new bisect anyway?") {
7300f0db065SSteven Rostedt (Red Hat)		exit (-1);
7310f0db065SSteven Rostedt (Red Hat)	    }
7320f0db065SSteven Rostedt (Red Hat)	}
733133087f0SSteven Rostedt (VMware)    }
7340f0db065SSteven Rostedt (Red Hat)    run_command "cp $good_start $good" or die "failed to copy to $good\n";
735aecea57fSMasanari Iida    run_command "cp $bad_start $bad" or die "failed to copy to $bad\n";
7360f0db065SSteven Rostedt (Red Hat)} else {
7370f0db065SSteven Rostedt (Red Hat)    if ( ! -f $good ) {
7380f0db065SSteven Rostedt (Red Hat)	die "Can not find file $good\n";
7390f0db065SSteven Rostedt (Red Hat)    }
7400f0db065SSteven Rostedt (Red Hat)    if ( ! -f $bad ) {
7410f0db065SSteven Rostedt (Red Hat)	die "Can not find file $bad\n";
7420f0db065SSteven Rostedt (Red Hat)    }
7430f0db065SSteven Rostedt (Red Hat)    if ($val eq "good") {
7440f0db065SSteven Rostedt (Red Hat)	run_command "cp $output_config $good" or die "failed to copy $config to $good\n";
7450f0db065SSteven Rostedt (Red Hat)    } elsif ($val eq "bad") {
7460f0db065SSteven Rostedt (Red Hat)	run_command "cp $output_config $bad" or die "failed to copy $config to $bad\n";
7470f0db065SSteven Rostedt (Red Hat)    }
7480f0db065SSteven Rostedt (Red Hat)}
7490f0db065SSteven Rostedt (Red Hat)
7500f0db065SSteven Rostedt (Red Hat)chdir $tree || die "can't change directory to $tree";
7510f0db065SSteven Rostedt (Red Hat)
7520f0db065SSteven Rostedt (Red Hat)my $ret = config_bisect $good, $bad;
7530f0db065SSteven Rostedt (Red Hat)
7540f0db065SSteven Rostedt (Red Hat)if (!$ret) {
7550f0db065SSteven Rostedt (Red Hat)    exit(0);
7560f0db065SSteven Rostedt (Red Hat)}
7570f0db065SSteven Rostedt (Red Hat)
7580f0db065SSteven Rostedt (Red Hat)if ($ret > 0) {
7590f0db065SSteven Rostedt (Red Hat)    doprint "Cleaning temp files\n";
7600f0db065SSteven Rostedt (Red Hat)    run_command "rm $good";
7610f0db065SSteven Rostedt (Red Hat)    run_command "rm $bad";
7620f0db065SSteven Rostedt (Red Hat)    exit(1);
7630f0db065SSteven Rostedt (Red Hat)} else {
7640f0db065SSteven Rostedt (Red Hat)    doprint "See good and bad configs for details:\n";
7650f0db065SSteven Rostedt (Red Hat)    doprint "good: $good\n";
7660f0db065SSteven Rostedt (Red Hat)    doprint "bad:  $bad\n";
7670f0db065SSteven Rostedt (Red Hat)    doprint "%%%%%%%% FAILED TO FIND SINGLE BAD CONFIG %%%%%%%%\n";
7680f0db065SSteven Rostedt (Red Hat)}
7690f0db065SSteven Rostedt (Red Hat)exit(2);
770