xref: /openbmc/linux/tools/testing/ktest/ktest.pl (revision 4ab1cce5bdd87948b75ed4fe4a8629c0f76267ae)
12545eb61SSteven Rostedt#!/usr/bin/perl -w
2d6ce2a0bSSteven Rostedt#
3cce1dac8SUwe Kleine-König# Copyright 2010 - Steven Rostedt <srostedt@redhat.com>, Red Hat Inc.
4d6ce2a0bSSteven Rostedt# Licensed under the terms of the GNU GPL License version 2
5d6ce2a0bSSteven Rostedt#
62545eb61SSteven Rostedt
72545eb61SSteven Rostedtuse strict;
82545eb61SSteven Rostedtuse IPC::Open2;
92545eb61SSteven Rostedtuse Fcntl qw(F_GETFL F_SETFL O_NONBLOCK);
107faafbd6SSteven Rostedtuse File::Path qw(mkpath);
117faafbd6SSteven Rostedtuse File::Copy qw(cp);
122545eb61SSteven Rostedtuse FileHandle;
132545eb61SSteven Rostedt
14e48c5293SSteven Rostedtmy $VERSION = "0.2";
15e48c5293SSteven Rostedt
162545eb61SSteven Rostedt$| = 1;
172545eb61SSteven Rostedt
182545eb61SSteven Rostedtmy %opt;
19a57419b3SSteven Rostedtmy %repeat_tests;
20a57419b3SSteven Rostedtmy %repeats;
21a75fececSSteven Rostedtmy %default;
222545eb61SSteven Rostedt
232545eb61SSteven Rostedt#default opts
24a57419b3SSteven Rostedt$default{"NUM_TESTS"}		= 1;
25a75fececSSteven Rostedt$default{"REBOOT_TYPE"}		= "grub";
26a75fececSSteven Rostedt$default{"TEST_TYPE"}		= "test";
27a75fececSSteven Rostedt$default{"BUILD_TYPE"}		= "randconfig";
28a75fececSSteven Rostedt$default{"MAKE_CMD"}		= "make";
29a75fececSSteven Rostedt$default{"TIMEOUT"}		= 120;
3048920630SSteven Rostedt$default{"TMP_DIR"}		= "/tmp/ktest/\${MACHINE}";
31a75fececSSteven Rostedt$default{"SLEEP_TIME"}		= 60;	# sleep time between tests
32a75fececSSteven Rostedt$default{"BUILD_NOCLEAN"}	= 0;
33a75fececSSteven Rostedt$default{"REBOOT_ON_ERROR"}	= 0;
34a75fececSSteven Rostedt$default{"POWEROFF_ON_ERROR"}	= 0;
35a75fececSSteven Rostedt$default{"REBOOT_ON_SUCCESS"}	= 1;
36a75fececSSteven Rostedt$default{"POWEROFF_ON_SUCCESS"}	= 0;
37a75fececSSteven Rostedt$default{"BUILD_OPTIONS"}	= "";
38a75fececSSteven Rostedt$default{"BISECT_SLEEP_TIME"}	= 60;   # sleep time between bisects
3927d934b2SSteven Rostedt$default{"PATCHCHECK_SLEEP_TIME"} = 60; # sleep time between patch checks
40a75fececSSteven Rostedt$default{"CLEAR_LOG"}		= 0;
41c960bb9fSSteven Rostedt$default{"BISECT_MANUAL"}	= 0;
42c23dca7cSSteven Rostedt$default{"BISECT_SKIP"}		= 1;
43a75fececSSteven Rostedt$default{"SUCCESS_LINE"}	= "login:";
44f1a5b962SSteven Rostedt$default{"DETECT_TRIPLE_FAULT"} = 1;
45e0a8742eSSteven Rostedt$default{"NO_INSTALL"}		= 0;
46a75fececSSteven Rostedt$default{"BOOTED_TIMEOUT"}	= 1;
47a75fececSSteven Rostedt$default{"DIE_ON_FAILURE"}	= 1;
48e48c5293SSteven Rostedt$default{"SSH_EXEC"}		= "ssh \$SSH_USER\@\$MACHINE \$SSH_COMMAND";
49e48c5293SSteven Rostedt$default{"SCP_TO_TARGET"}	= "scp \$SRC_FILE \$SSH_USER\@\$MACHINE:\$DST_FILE";
50e48c5293SSteven Rostedt$default{"REBOOT"}		= "ssh \$SSH_USER\@\$MACHINE reboot";
511c8a617aSSteven Rostedt$default{"STOP_AFTER_SUCCESS"}	= 10;
521c8a617aSSteven Rostedt$default{"STOP_AFTER_FAILURE"}	= 60;
532d01b26aSSteven Rostedt$default{"STOP_TEST_AFTER"}	= 600;
548d1491baSSteven Rostedt$default{"LOCALVERSION"}	= "-test";
552545eb61SSteven Rostedt
568d1491baSSteven Rostedtmy $ktest_config;
572545eb61SSteven Rostedtmy $version;
58a75fececSSteven Rostedtmy $machine;
59e48c5293SSteven Rostedtmy $ssh_user;
60a75fececSSteven Rostedtmy $tmpdir;
61a75fececSSteven Rostedtmy $builddir;
62a75fececSSteven Rostedtmy $outputdir;
6351ad1dd1SSteven Rostedtmy $output_config;
64a75fececSSteven Rostedtmy $test_type;
657faafbd6SSteven Rostedtmy $build_type;
66a75fececSSteven Rostedtmy $build_options;
670bd6c1a3SSteven Rostedtmy $pre_build;
680bd6c1a3SSteven Rostedtmy $post_build;
690bd6c1a3SSteven Rostedtmy $pre_build_die;
700bd6c1a3SSteven Rostedtmy $post_build_die;
71a75fececSSteven Rostedtmy $reboot_type;
72a75fececSSteven Rostedtmy $reboot_script;
73a75fececSSteven Rostedtmy $power_cycle;
74e48c5293SSteven Rostedtmy $reboot;
75a75fececSSteven Rostedtmy $reboot_on_error;
76a75fececSSteven Rostedtmy $poweroff_on_error;
77a75fececSSteven Rostedtmy $die_on_failure;
78576f627cSSteven Rostedtmy $powercycle_after_reboot;
79576f627cSSteven Rostedtmy $poweroff_after_halt;
80e48c5293SSteven Rostedtmy $ssh_exec;
81e48c5293SSteven Rostedtmy $scp_to_target;
82a75fececSSteven Rostedtmy $power_off;
83a75fececSSteven Rostedtmy $grub_menu;
842545eb61SSteven Rostedtmy $grub_number;
852545eb61SSteven Rostedtmy $target;
862545eb61SSteven Rostedtmy $make;
878b37ca8cSSteven Rostedtmy $post_install;
88e0a8742eSSteven Rostedtmy $no_install;
895c42fc5bSSteven Rostedtmy $noclean;
905f9b6cedSSteven Rostedtmy $minconfig;
914c4ab120SSteven Rostedtmy $start_minconfig;
9235ce5952SSteven Rostedtmy $start_minconfig_defined;
934c4ab120SSteven Rostedtmy $output_minconfig;
944c4ab120SSteven Rostedtmy $ignore_config;
952b7d9b21SSteven Rostedtmy $addconfig;
965f9b6cedSSteven Rostedtmy $in_bisect = 0;
975f9b6cedSSteven Rostedtmy $bisect_bad = "";
98d6ce2a0bSSteven Rostedtmy $reverse_bisect;
99c960bb9fSSteven Rostedtmy $bisect_manual;
100c23dca7cSSteven Rostedtmy $bisect_skip;
10130f75da5SSteven Rostedtmy $config_bisect_good;
1026c5ee0beSSteven Rostedtmy $in_patchcheck = 0;
1035a391fbfSSteven Rostedtmy $run_test;
1046c5ee0beSSteven Rostedtmy $redirect;
1057faafbd6SSteven Rostedtmy $buildlog;
1067faafbd6SSteven Rostedtmy $dmesg;
1077faafbd6SSteven Rostedtmy $monitor_fp;
1087faafbd6SSteven Rostedtmy $monitor_pid;
1097faafbd6SSteven Rostedtmy $monitor_cnt = 0;
110a75fececSSteven Rostedtmy $sleep_time;
111a75fececSSteven Rostedtmy $bisect_sleep_time;
11227d934b2SSteven Rostedtmy $patchcheck_sleep_time;
1131990207dSSteven Rostedtmy $ignore_warnings;
114a75fececSSteven Rostedtmy $store_failures;
1159064af52SSteven Rostedtmy $test_name;
116a75fececSSteven Rostedtmy $timeout;
117a75fececSSteven Rostedtmy $booted_timeout;
118f1a5b962SSteven Rostedtmy $detect_triplefault;
119a75fececSSteven Rostedtmy $console;
1202b803365SSteven Rostedtmy $reboot_success_line;
121a75fececSSteven Rostedtmy $success_line;
1221c8a617aSSteven Rostedtmy $stop_after_success;
1231c8a617aSSteven Rostedtmy $stop_after_failure;
1242d01b26aSSteven Rostedtmy $stop_test_after;
125a75fececSSteven Rostedtmy $build_target;
126a75fececSSteven Rostedtmy $target_image;
127a75fececSSteven Rostedtmy $localversion;
128576f627cSSteven Rostedtmy $iteration = 0;
129e48c5293SSteven Rostedtmy $successes = 0;
1302545eb61SSteven Rostedt
1318d1491baSSteven Rostedtmy %entered_configs;
1328d1491baSSteven Rostedtmy %config_help;
13377d942ceSSteven Rostedtmy %variable;
134fcb3f16aSSteven Rostedtmy %force_config;
1358d1491baSSteven Rostedt
136*4ab1cce5SSteven Rostedt# do not force reboots on config problems
137*4ab1cce5SSteven Rostedtmy $no_reboot = 1;
138*4ab1cce5SSteven Rostedt
1398d1491baSSteven Rostedt$config_help{"MACHINE"} = << "EOF"
1408d1491baSSteven Rostedt The machine hostname that you will test.
1418d1491baSSteven RostedtEOF
1428d1491baSSteven Rostedt    ;
1438d1491baSSteven Rostedt$config_help{"SSH_USER"} = << "EOF"
1448d1491baSSteven Rostedt The box is expected to have ssh on normal bootup, provide the user
1458d1491baSSteven Rostedt  (most likely root, since you need privileged operations)
1468d1491baSSteven RostedtEOF
1478d1491baSSteven Rostedt    ;
1488d1491baSSteven Rostedt$config_help{"BUILD_DIR"} = << "EOF"
1498d1491baSSteven Rostedt The directory that contains the Linux source code (full path).
1508d1491baSSteven RostedtEOF
1518d1491baSSteven Rostedt    ;
1528d1491baSSteven Rostedt$config_help{"OUTPUT_DIR"} = << "EOF"
1538d1491baSSteven Rostedt The directory that the objects will be built (full path).
1548d1491baSSteven Rostedt (can not be same as BUILD_DIR)
1558d1491baSSteven RostedtEOF
1568d1491baSSteven Rostedt    ;
1578d1491baSSteven Rostedt$config_help{"BUILD_TARGET"} = << "EOF"
1588d1491baSSteven Rostedt The location of the compiled file to copy to the target.
1598d1491baSSteven Rostedt (relative to OUTPUT_DIR)
1608d1491baSSteven RostedtEOF
1618d1491baSSteven Rostedt    ;
1628d1491baSSteven Rostedt$config_help{"TARGET_IMAGE"} = << "EOF"
1638d1491baSSteven Rostedt The place to put your image on the test machine.
1648d1491baSSteven RostedtEOF
1658d1491baSSteven Rostedt    ;
1668d1491baSSteven Rostedt$config_help{"POWER_CYCLE"} = << "EOF"
1678d1491baSSteven Rostedt A script or command to reboot the box.
1688d1491baSSteven Rostedt
1698d1491baSSteven Rostedt Here is a digital loggers power switch example
1708d1491baSSteven Rostedt POWER_CYCLE = wget --no-proxy -O /dev/null -q  --auth-no-challenge 'http://admin:admin\@power/outlet?5=CCL'
1718d1491baSSteven Rostedt
1728d1491baSSteven Rostedt Here is an example to reboot a virtual box on the current host
1738d1491baSSteven Rostedt with the name "Guest".
1748d1491baSSteven Rostedt POWER_CYCLE = virsh destroy Guest; sleep 5; virsh start Guest
1758d1491baSSteven RostedtEOF
1768d1491baSSteven Rostedt    ;
1778d1491baSSteven Rostedt$config_help{"CONSOLE"} = << "EOF"
1788d1491baSSteven Rostedt The script or command that reads the console
1798d1491baSSteven Rostedt
1808d1491baSSteven Rostedt  If you use ttywatch server, something like the following would work.
1818d1491baSSteven RostedtCONSOLE = nc -d localhost 3001
1828d1491baSSteven Rostedt
1838d1491baSSteven Rostedt For a virtual machine with guest name "Guest".
1848d1491baSSteven RostedtCONSOLE =  virsh console Guest
1858d1491baSSteven RostedtEOF
1868d1491baSSteven Rostedt    ;
1878d1491baSSteven Rostedt$config_help{"LOCALVERSION"} = << "EOF"
1888d1491baSSteven Rostedt Required version ending to differentiate the test
1898d1491baSSteven Rostedt from other linux builds on the system.
1908d1491baSSteven RostedtEOF
1918d1491baSSteven Rostedt    ;
1928d1491baSSteven Rostedt$config_help{"REBOOT_TYPE"} = << "EOF"
1938d1491baSSteven Rostedt Way to reboot the box to the test kernel.
1948d1491baSSteven Rostedt Only valid options so far are "grub" and "script".
1958d1491baSSteven Rostedt
1968d1491baSSteven Rostedt If you specify grub, it will assume grub version 1
1978d1491baSSteven Rostedt and will search in /boot/grub/menu.lst for the title \$GRUB_MENU
1988d1491baSSteven Rostedt and select that target to reboot to the kernel. If this is not
1998d1491baSSteven Rostedt your setup, then specify "script" and have a command or script
2008d1491baSSteven Rostedt specified in REBOOT_SCRIPT to boot to the target.
2018d1491baSSteven Rostedt
2028d1491baSSteven Rostedt The entry in /boot/grub/menu.lst must be entered in manually.
2038d1491baSSteven Rostedt The test will not modify that file.
2048d1491baSSteven RostedtEOF
2058d1491baSSteven Rostedt    ;
2068d1491baSSteven Rostedt$config_help{"GRUB_MENU"} = << "EOF"
2078d1491baSSteven Rostedt The grub title name for the test kernel to boot
2088d1491baSSteven Rostedt (Only mandatory if REBOOT_TYPE = grub)
2098d1491baSSteven Rostedt
2108d1491baSSteven Rostedt Note, ktest.pl will not update the grub menu.lst, you need to
2118d1491baSSteven Rostedt manually add an option for the test. ktest.pl will search
2128d1491baSSteven Rostedt the grub menu.lst for this option to find what kernel to
2138d1491baSSteven Rostedt reboot into.
2148d1491baSSteven Rostedt
2158d1491baSSteven Rostedt For example, if in the /boot/grub/menu.lst the test kernel title has:
2168d1491baSSteven Rostedt title Test Kernel
2178d1491baSSteven Rostedt kernel vmlinuz-test
2188d1491baSSteven Rostedt GRUB_MENU = Test Kernel
2198d1491baSSteven RostedtEOF
2208d1491baSSteven Rostedt    ;
2218d1491baSSteven Rostedt$config_help{"REBOOT_SCRIPT"} = << "EOF"
2228d1491baSSteven Rostedt A script to reboot the target into the test kernel
2238d1491baSSteven Rostedt (Only mandatory if REBOOT_TYPE = script)
2248d1491baSSteven RostedtEOF
2258d1491baSSteven Rostedt    ;
2268d1491baSSteven Rostedt
22735ce5952SSteven Rostedtsub read_yn {
22835ce5952SSteven Rostedt    my ($prompt) = @_;
22935ce5952SSteven Rostedt
23035ce5952SSteven Rostedt    my $ans;
23135ce5952SSteven Rostedt
23235ce5952SSteven Rostedt    for (;;) {
23335ce5952SSteven Rostedt	print "$prompt [Y/n] ";
23435ce5952SSteven Rostedt	$ans = <STDIN>;
23535ce5952SSteven Rostedt	chomp $ans;
23635ce5952SSteven Rostedt	if ($ans =~ /^\s*$/) {
23735ce5952SSteven Rostedt	    $ans = "y";
23835ce5952SSteven Rostedt	}
23935ce5952SSteven Rostedt	last if ($ans =~ /^y$/i || $ans =~ /^n$/i);
24035ce5952SSteven Rostedt	print "Please answer either 'y' or 'n'.\n";
24135ce5952SSteven Rostedt    }
24235ce5952SSteven Rostedt    if ($ans !~ /^y$/i) {
24335ce5952SSteven Rostedt	return 0;
24435ce5952SSteven Rostedt    }
24535ce5952SSteven Rostedt    return 1;
24635ce5952SSteven Rostedt}
2478d1491baSSteven Rostedt
2488d1491baSSteven Rostedtsub get_ktest_config {
2498d1491baSSteven Rostedt    my ($config) = @_;
2508d1491baSSteven Rostedt
2518d1491baSSteven Rostedt    return if (defined($opt{$config}));
2528d1491baSSteven Rostedt
2538d1491baSSteven Rostedt    if (defined($config_help{$config})) {
2548d1491baSSteven Rostedt	print "\n";
2558d1491baSSteven Rostedt	print $config_help{$config};
2568d1491baSSteven Rostedt    }
2578d1491baSSteven Rostedt
2588d1491baSSteven Rostedt    for (;;) {
2598d1491baSSteven Rostedt	print "$config = ";
2608d1491baSSteven Rostedt	if (defined($default{$config})) {
2618d1491baSSteven Rostedt	    print "\[$default{$config}\] ";
2628d1491baSSteven Rostedt	}
2638d1491baSSteven Rostedt	$entered_configs{$config} = <STDIN>;
2648d1491baSSteven Rostedt	$entered_configs{$config} =~ s/^\s*(.*\S)\s*$/$1/;
2658d1491baSSteven Rostedt	if ($entered_configs{$config} =~ /^\s*$/) {
2668d1491baSSteven Rostedt	    if ($default{$config}) {
2678d1491baSSteven Rostedt		$entered_configs{$config} = $default{$config};
2688d1491baSSteven Rostedt	    } else {
2698d1491baSSteven Rostedt		print "Your answer can not be blank\n";
2708d1491baSSteven Rostedt		next;
2718d1491baSSteven Rostedt	    }
2728d1491baSSteven Rostedt	}
2738d1491baSSteven Rostedt	last;
2748d1491baSSteven Rostedt    }
2758d1491baSSteven Rostedt}
2768d1491baSSteven Rostedt
2778d1491baSSteven Rostedtsub get_ktest_configs {
2788d1491baSSteven Rostedt    get_ktest_config("MACHINE");
2798d1491baSSteven Rostedt    get_ktest_config("SSH_USER");
2808d1491baSSteven Rostedt    get_ktest_config("BUILD_DIR");
2818d1491baSSteven Rostedt    get_ktest_config("OUTPUT_DIR");
2828d1491baSSteven Rostedt    get_ktest_config("BUILD_TARGET");
2838d1491baSSteven Rostedt    get_ktest_config("TARGET_IMAGE");
2848d1491baSSteven Rostedt    get_ktest_config("POWER_CYCLE");
2858d1491baSSteven Rostedt    get_ktest_config("CONSOLE");
2868d1491baSSteven Rostedt    get_ktest_config("LOCALVERSION");
2878d1491baSSteven Rostedt
2888d1491baSSteven Rostedt    my $rtype = $opt{"REBOOT_TYPE"};
2898d1491baSSteven Rostedt
2908d1491baSSteven Rostedt    if (!defined($rtype)) {
2918d1491baSSteven Rostedt	if (!defined($opt{"GRUB_MENU"})) {
2928d1491baSSteven Rostedt	    get_ktest_config("REBOOT_TYPE");
2938d1491baSSteven Rostedt	    $rtype = $entered_configs{"REBOOT_TYPE"};
2948d1491baSSteven Rostedt	} else {
2958d1491baSSteven Rostedt	    $rtype = "grub";
2968d1491baSSteven Rostedt	}
2978d1491baSSteven Rostedt    }
2988d1491baSSteven Rostedt
2998d1491baSSteven Rostedt    if ($rtype eq "grub") {
3008d1491baSSteven Rostedt	get_ktest_config("GRUB_MENU");
3018d1491baSSteven Rostedt    } else {
3028d1491baSSteven Rostedt	get_ktest_config("REBOOT_SCRIPT");
3038d1491baSSteven Rostedt    }
3048d1491baSSteven Rostedt}
3058d1491baSSteven Rostedt
30677d942ceSSteven Rostedtsub process_variables {
30777d942ceSSteven Rostedt    my ($value) = @_;
30877d942ceSSteven Rostedt    my $retval = "";
30977d942ceSSteven Rostedt
31077d942ceSSteven Rostedt    # We want to check for '\', and it is just easier
31177d942ceSSteven Rostedt    # to check the previous characet of '$' and not need
31277d942ceSSteven Rostedt    # to worry if '$' is the first character. By adding
31377d942ceSSteven Rostedt    # a space to $value, we can just check [^\\]\$ and
31477d942ceSSteven Rostedt    # it will still work.
31577d942ceSSteven Rostedt    $value = " $value";
31677d942ceSSteven Rostedt
31777d942ceSSteven Rostedt    while ($value =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) {
31877d942ceSSteven Rostedt	my $begin = $1;
31977d942ceSSteven Rostedt	my $var = $2;
32077d942ceSSteven Rostedt	my $end = $3;
32177d942ceSSteven Rostedt	# append beginning of value to retval
32277d942ceSSteven Rostedt	$retval = "$retval$begin";
32377d942ceSSteven Rostedt	if (defined($variable{$var})) {
32477d942ceSSteven Rostedt	    $retval = "$retval$variable{$var}";
32577d942ceSSteven Rostedt	} else {
32677d942ceSSteven Rostedt	    # put back the origin piece.
32777d942ceSSteven Rostedt	    $retval = "$retval\$\{$var\}";
32877d942ceSSteven Rostedt	}
32977d942ceSSteven Rostedt	$value = $end;
33077d942ceSSteven Rostedt    }
33177d942ceSSteven Rostedt    $retval = "$retval$value";
33277d942ceSSteven Rostedt
33377d942ceSSteven Rostedt    # remove the space added in the beginning
33477d942ceSSteven Rostedt    $retval =~ s/ //;
33577d942ceSSteven Rostedt
33677d942ceSSteven Rostedt    return "$retval"
33777d942ceSSteven Rostedt}
33877d942ceSSteven Rostedt
339a57419b3SSteven Rostedtsub set_value {
340a57419b3SSteven Rostedt    my ($lvalue, $rvalue) = @_;
3412545eb61SSteven Rostedt
342a75fececSSteven Rostedt    if (defined($opt{$lvalue})) {
343a75fececSSteven Rostedt	die "Error: Option $lvalue defined more than once!\n";
344a75fececSSteven Rostedt    }
34521a9679fSSteven Rostedt    if ($rvalue =~ /^\s*$/) {
34621a9679fSSteven Rostedt	delete $opt{$lvalue};
34721a9679fSSteven Rostedt    } else {
34877d942ceSSteven Rostedt	$rvalue = process_variables($rvalue);
34921a9679fSSteven Rostedt	$opt{$lvalue} = $rvalue;
35021a9679fSSteven Rostedt    }
3512545eb61SSteven Rostedt}
352a57419b3SSteven Rostedt
35377d942ceSSteven Rostedtsub set_variable {
35477d942ceSSteven Rostedt    my ($lvalue, $rvalue) = @_;
35577d942ceSSteven Rostedt
35677d942ceSSteven Rostedt    if ($rvalue =~ /^\s*$/) {
35777d942ceSSteven Rostedt	delete $variable{$lvalue};
35877d942ceSSteven Rostedt    } else {
35977d942ceSSteven Rostedt	$rvalue = process_variables($rvalue);
36077d942ceSSteven Rostedt	$variable{$lvalue} = $rvalue;
36177d942ceSSteven Rostedt    }
36277d942ceSSteven Rostedt}
36377d942ceSSteven Rostedt
364a57419b3SSteven Rostedtsub read_config {
365a57419b3SSteven Rostedt    my ($config) = @_;
366a57419b3SSteven Rostedt
367a57419b3SSteven Rostedt    open(IN, $config) || die "can't read file $config";
368a57419b3SSteven Rostedt
369a57419b3SSteven Rostedt    my $name = $config;
370a57419b3SSteven Rostedt    $name =~ s,.*/(.*),$1,;
371a57419b3SSteven Rostedt
372a57419b3SSteven Rostedt    my $test_num = 0;
373a57419b3SSteven Rostedt    my $default = 1;
374a57419b3SSteven Rostedt    my $repeat = 1;
375a57419b3SSteven Rostedt    my $num_tests_set = 0;
376a57419b3SSteven Rostedt    my $skip = 0;
377a57419b3SSteven Rostedt    my $rest;
3780df213caSSteven Rostedt    my $test_case = 0;
379a57419b3SSteven Rostedt
380a57419b3SSteven Rostedt    while (<IN>) {
381a57419b3SSteven Rostedt
382a57419b3SSteven Rostedt	# ignore blank lines and comments
383a57419b3SSteven Rostedt	next if (/^\s*$/ || /\s*\#/);
384a57419b3SSteven Rostedt
385a57419b3SSteven Rostedt	if (/^\s*TEST_START(.*)/) {
386a57419b3SSteven Rostedt
387a57419b3SSteven Rostedt	    $rest = $1;
388a57419b3SSteven Rostedt
389a57419b3SSteven Rostedt	    if ($num_tests_set) {
390a57419b3SSteven Rostedt		die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
391a57419b3SSteven Rostedt	    }
392a57419b3SSteven Rostedt
393a57419b3SSteven Rostedt	    my $old_test_num = $test_num;
394e48c5293SSteven Rostedt	    my $old_repeat = $repeat;
395a57419b3SSteven Rostedt
396a57419b3SSteven Rostedt	    $test_num += $repeat;
397a57419b3SSteven Rostedt	    $default = 0;
398a57419b3SSteven Rostedt	    $repeat = 1;
399a57419b3SSteven Rostedt
400a57419b3SSteven Rostedt	    if ($rest =~ /\s+SKIP(.*)/) {
401a57419b3SSteven Rostedt		$rest = $1;
402a57419b3SSteven Rostedt		$skip = 1;
403a57419b3SSteven Rostedt	    } else {
4040df213caSSteven Rostedt		$test_case = 1;
405a57419b3SSteven Rostedt		$skip = 0;
406a57419b3SSteven Rostedt	    }
407a57419b3SSteven Rostedt
408a57419b3SSteven Rostedt	    if ($rest =~ /\s+ITERATE\s+(\d+)(.*)$/) {
409a57419b3SSteven Rostedt		$repeat = $1;
410a57419b3SSteven Rostedt		$rest = $2;
411a57419b3SSteven Rostedt		$repeat_tests{"$test_num"} = $repeat;
412a57419b3SSteven Rostedt	    }
413a57419b3SSteven Rostedt
414a57419b3SSteven Rostedt	    if ($rest =~ /\s+SKIP(.*)/) {
415a57419b3SSteven Rostedt		$rest = $1;
416a57419b3SSteven Rostedt		$skip = 1;
417a57419b3SSteven Rostedt	    }
418a57419b3SSteven Rostedt
419a57419b3SSteven Rostedt	    if ($rest !~ /^\s*$/) {
420a57419b3SSteven Rostedt		die "$name: $.: Gargbage found after TEST_START\n$_";
421a57419b3SSteven Rostedt	    }
422a57419b3SSteven Rostedt
423a57419b3SSteven Rostedt	    if ($skip) {
424a57419b3SSteven Rostedt		$test_num = $old_test_num;
425e48c5293SSteven Rostedt		$repeat = $old_repeat;
426a57419b3SSteven Rostedt	    }
427a57419b3SSteven Rostedt
428a57419b3SSteven Rostedt	} elsif (/^\s*DEFAULTS(.*)$/) {
429a57419b3SSteven Rostedt	    $default = 1;
430a57419b3SSteven Rostedt
431a57419b3SSteven Rostedt	    $rest = $1;
432a57419b3SSteven Rostedt
433a57419b3SSteven Rostedt	    if ($rest =~ /\s+SKIP(.*)/) {
434a57419b3SSteven Rostedt		$rest = $1;
435a57419b3SSteven Rostedt		$skip = 1;
436a57419b3SSteven Rostedt	    } else {
437a57419b3SSteven Rostedt		$skip = 0;
438a57419b3SSteven Rostedt	    }
439a57419b3SSteven Rostedt
440a57419b3SSteven Rostedt	    if ($rest !~ /^\s*$/) {
441a57419b3SSteven Rostedt		die "$name: $.: Gargbage found after DEFAULTS\n$_";
442a57419b3SSteven Rostedt	    }
443a57419b3SSteven Rostedt
444a57419b3SSteven Rostedt	} elsif (/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) {
445a57419b3SSteven Rostedt
446a57419b3SSteven Rostedt	    next if ($skip);
447a57419b3SSteven Rostedt
448a57419b3SSteven Rostedt	    my $lvalue = $1;
449a57419b3SSteven Rostedt	    my $rvalue = $2;
450a57419b3SSteven Rostedt
451a57419b3SSteven Rostedt	    if (!$default &&
452a57419b3SSteven Rostedt		($lvalue eq "NUM_TESTS" ||
453a57419b3SSteven Rostedt		 $lvalue eq "LOG_FILE" ||
454a57419b3SSteven Rostedt		 $lvalue eq "CLEAR_LOG")) {
455a57419b3SSteven Rostedt		die "$name: $.: $lvalue must be set in DEFAULTS section\n";
456a57419b3SSteven Rostedt	    }
457a57419b3SSteven Rostedt
458a57419b3SSteven Rostedt	    if ($lvalue eq "NUM_TESTS") {
459a57419b3SSteven Rostedt		if ($test_num) {
460a57419b3SSteven Rostedt		    die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
461a57419b3SSteven Rostedt		}
462a57419b3SSteven Rostedt		if (!$default) {
463a57419b3SSteven Rostedt		    die "$name: $.: NUM_TESTS must be set in default section\n";
464a57419b3SSteven Rostedt		}
465a57419b3SSteven Rostedt		$num_tests_set = 1;
466a57419b3SSteven Rostedt	    }
467a57419b3SSteven Rostedt
468a57419b3SSteven Rostedt	    if ($default || $lvalue =~ /\[\d+\]$/) {
469a57419b3SSteven Rostedt		set_value($lvalue, $rvalue);
470a57419b3SSteven Rostedt	    } else {
471a57419b3SSteven Rostedt		my $val = "$lvalue\[$test_num\]";
472a57419b3SSteven Rostedt		set_value($val, $rvalue);
473a57419b3SSteven Rostedt
474a57419b3SSteven Rostedt		if ($repeat > 1) {
475a57419b3SSteven Rostedt		    $repeats{$val} = $repeat;
476a57419b3SSteven Rostedt		}
477a57419b3SSteven Rostedt	    }
47877d942ceSSteven Rostedt	} elsif (/^\s*([A-Z_\[\]\d]+)\s*:=\s*(.*?)\s*$/) {
47977d942ceSSteven Rostedt	    next if ($skip);
48077d942ceSSteven Rostedt
48177d942ceSSteven Rostedt	    my $lvalue = $1;
48277d942ceSSteven Rostedt	    my $rvalue = $2;
48377d942ceSSteven Rostedt
48477d942ceSSteven Rostedt	    # process config variables.
48577d942ceSSteven Rostedt	    # Config variables are only active while reading the
48677d942ceSSteven Rostedt	    # config and can be defined anywhere. They also ignore
48777d942ceSSteven Rostedt	    # TEST_START and DEFAULTS, but are skipped if they are in
48877d942ceSSteven Rostedt	    # on of these sections that have SKIP defined.
48977d942ceSSteven Rostedt	    # The save variable can be
49077d942ceSSteven Rostedt	    # defined multiple times and the new one simply overrides
49177d942ceSSteven Rostedt	    # the prevous one.
49277d942ceSSteven Rostedt	    set_variable($lvalue, $rvalue);
49377d942ceSSteven Rostedt
494a57419b3SSteven Rostedt	} else {
495a57419b3SSteven Rostedt	    die "$name: $.: Garbage found in config\n$_";
496a57419b3SSteven Rostedt	}
4972545eb61SSteven Rostedt    }
4982545eb61SSteven Rostedt
4992545eb61SSteven Rostedt    close(IN);
500a75fececSSteven Rostedt
501a57419b3SSteven Rostedt    if ($test_num) {
502a57419b3SSteven Rostedt	$test_num += $repeat - 1;
503a57419b3SSteven Rostedt	$opt{"NUM_TESTS"} = $test_num;
504a57419b3SSteven Rostedt    }
505a57419b3SSteven Rostedt
5068d1491baSSteven Rostedt    # make sure we have all mandatory configs
5078d1491baSSteven Rostedt    get_ktest_configs;
5088d1491baSSteven Rostedt
5090df213caSSteven Rostedt    # was a test specified?
5100df213caSSteven Rostedt    if (!$test_case) {
5110df213caSSteven Rostedt	print "No test case specified.\n";
5120df213caSSteven Rostedt	print "What test case would you like to run?\n";
5130df213caSSteven Rostedt	my $ans = <STDIN>;
5140df213caSSteven Rostedt	chomp $ans;
5150df213caSSteven Rostedt	$default{"TEST_TYPE"} = $ans;
5160df213caSSteven Rostedt    }
5170df213caSSteven Rostedt
518a75fececSSteven Rostedt    # set any defaults
519a75fececSSteven Rostedt
520a75fececSSteven Rostedt    foreach my $default (keys %default) {
521a75fececSSteven Rostedt	if (!defined($opt{$default})) {
522a75fececSSteven Rostedt	    $opt{$default} = $default{$default};
523a75fececSSteven Rostedt	}
524a75fececSSteven Rostedt    }
5252545eb61SSteven Rostedt}
5262545eb61SSteven Rostedt
52723715c3cSSteven Rostedtsub __eval_option {
52823715c3cSSteven Rostedt    my ($option, $i) = @_;
52923715c3cSSteven Rostedt
53023715c3cSSteven Rostedt    # Add space to evaluate the character before $
53123715c3cSSteven Rostedt    $option = " $option";
53223715c3cSSteven Rostedt    my $retval = "";
53323715c3cSSteven Rostedt
53423715c3cSSteven Rostedt    while ($option =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) {
53523715c3cSSteven Rostedt	my $start = $1;
53623715c3cSSteven Rostedt	my $var = $2;
53723715c3cSSteven Rostedt	my $end = $3;
53823715c3cSSteven Rostedt
53923715c3cSSteven Rostedt	# Append beginning of line
54023715c3cSSteven Rostedt	$retval = "$retval$start";
54123715c3cSSteven Rostedt
54223715c3cSSteven Rostedt	# If the iteration option OPT[$i] exists, then use that.
54323715c3cSSteven Rostedt	# otherwise see if the default OPT (without [$i]) exists.
54423715c3cSSteven Rostedt
54523715c3cSSteven Rostedt	my $o = "$var\[$i\]";
54623715c3cSSteven Rostedt
54723715c3cSSteven Rostedt	if (defined($opt{$o})) {
54823715c3cSSteven Rostedt	    $o = $opt{$o};
54923715c3cSSteven Rostedt	    $retval = "$retval$o";
55023715c3cSSteven Rostedt	} elsif (defined($opt{$var})) {
55123715c3cSSteven Rostedt	    $o = $opt{$var};
55223715c3cSSteven Rostedt	    $retval = "$retval$o";
55323715c3cSSteven Rostedt	} else {
55423715c3cSSteven Rostedt	    $retval = "$retval\$\{$var\}";
55523715c3cSSteven Rostedt	}
55623715c3cSSteven Rostedt
55723715c3cSSteven Rostedt	$option = $end;
55823715c3cSSteven Rostedt    }
55923715c3cSSteven Rostedt
56023715c3cSSteven Rostedt    $retval = "$retval$option";
56123715c3cSSteven Rostedt
56223715c3cSSteven Rostedt    $retval =~ s/^ //;
56323715c3cSSteven Rostedt
56423715c3cSSteven Rostedt    return $retval;
56523715c3cSSteven Rostedt}
56623715c3cSSteven Rostedt
56723715c3cSSteven Rostedtsub eval_option {
56823715c3cSSteven Rostedt    my ($option, $i) = @_;
56923715c3cSSteven Rostedt
57023715c3cSSteven Rostedt    my $prev = "";
57123715c3cSSteven Rostedt
57223715c3cSSteven Rostedt    # Since an option can evaluate to another option,
57323715c3cSSteven Rostedt    # keep iterating until we do not evaluate any more
57423715c3cSSteven Rostedt    # options.
57523715c3cSSteven Rostedt    my $r = 0;
57623715c3cSSteven Rostedt    while ($prev ne $option) {
57723715c3cSSteven Rostedt	# Check for recursive evaluations.
57823715c3cSSteven Rostedt	# 100 deep should be more than enough.
57923715c3cSSteven Rostedt	if ($r++ > 100) {
58023715c3cSSteven Rostedt	    die "Over 100 evaluations accurred with $option\n" .
58123715c3cSSteven Rostedt		"Check for recursive variables\n";
58223715c3cSSteven Rostedt	}
58323715c3cSSteven Rostedt	$prev = $option;
58423715c3cSSteven Rostedt	$option = __eval_option($option, $i);
58523715c3cSSteven Rostedt    }
58623715c3cSSteven Rostedt
58723715c3cSSteven Rostedt    return $option;
58823715c3cSSteven Rostedt}
58923715c3cSSteven Rostedt
590d1e2f22aSSteven Rostedtsub _logit {
5912545eb61SSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
5922545eb61SSteven Rostedt	open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}";
5932545eb61SSteven Rostedt	print OUT @_;
5942545eb61SSteven Rostedt	close(OUT);
5952545eb61SSteven Rostedt    }
5962545eb61SSteven Rostedt}
5972545eb61SSteven Rostedt
598d1e2f22aSSteven Rostedtsub logit {
599d1e2f22aSSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
600d1e2f22aSSteven Rostedt	_logit @_;
601d1e2f22aSSteven Rostedt    } else {
602d1e2f22aSSteven Rostedt	print @_;
603d1e2f22aSSteven Rostedt    }
604d1e2f22aSSteven Rostedt}
605d1e2f22aSSteven Rostedt
6065f9b6cedSSteven Rostedtsub doprint {
6075f9b6cedSSteven Rostedt    print @_;
608d1e2f22aSSteven Rostedt    _logit @_;
6095f9b6cedSSteven Rostedt}
6105f9b6cedSSteven Rostedt
6117faafbd6SSteven Rostedtsub run_command;
6122728be41SAndrew Jonessub start_monitor;
6132728be41SAndrew Jonessub end_monitor;
6142728be41SAndrew Jonessub wait_for_monitor;
6157faafbd6SSteven Rostedt
6167faafbd6SSteven Rostedtsub reboot {
6172728be41SAndrew Jones    my ($time) = @_;
6182728be41SAndrew Jones
6192b803365SSteven Rostedt    if (defined($time)) {
6202b803365SSteven Rostedt	start_monitor;
6212b803365SSteven Rostedt	# flush out current monitor
6222b803365SSteven Rostedt	# May contain the reboot success line
6232b803365SSteven Rostedt	wait_for_monitor 1;
6242b803365SSteven Rostedt    }
6252b803365SSteven Rostedt
6267faafbd6SSteven Rostedt    # try to reboot normally
627e48c5293SSteven Rostedt    if (run_command $reboot) {
628576f627cSSteven Rostedt	if (defined($powercycle_after_reboot)) {
629576f627cSSteven Rostedt	    sleep $powercycle_after_reboot;
630576f627cSSteven Rostedt	    run_command "$power_cycle";
631576f627cSSteven Rostedt	}
632576f627cSSteven Rostedt    } else {
6337faafbd6SSteven Rostedt	# nope? power cycle it.
634a75fececSSteven Rostedt	run_command "$power_cycle";
6357faafbd6SSteven Rostedt    }
6362728be41SAndrew Jones
6372728be41SAndrew Jones    if (defined($time)) {
6382b803365SSteven Rostedt	wait_for_monitor($time, $reboot_success_line);
6392728be41SAndrew Jones	end_monitor;
6402728be41SAndrew Jones    }
6417faafbd6SSteven Rostedt}
6427faafbd6SSteven Rostedt
643576f627cSSteven Rostedtsub do_not_reboot {
644576f627cSSteven Rostedt    my $i = $iteration;
645576f627cSSteven Rostedt
646*4ab1cce5SSteven Rostedt    return $test_type eq "build" || $no_reboot ||
647576f627cSSteven Rostedt	($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") ||
648576f627cSSteven Rostedt	($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build");
649576f627cSSteven Rostedt}
650576f627cSSteven Rostedt
6515c42fc5bSSteven Rostedtsub dodie {
6525a391fbfSSteven Rostedt    doprint "CRITICAL FAILURE... ", @_, "\n";
6535c42fc5bSSteven Rostedt
654576f627cSSteven Rostedt    my $i = $iteration;
655576f627cSSteven Rostedt
656576f627cSSteven Rostedt    if ($reboot_on_error && !do_not_reboot) {
657576f627cSSteven Rostedt
65875c3fda7SSteven Rostedt	doprint "REBOOTING\n";
6597faafbd6SSteven Rostedt	reboot;
66075c3fda7SSteven Rostedt
661a75fececSSteven Rostedt    } elsif ($poweroff_on_error && defined($power_off)) {
6625c42fc5bSSteven Rostedt	doprint "POWERING OFF\n";
663a75fececSSteven Rostedt	`$power_off`;
6645c42fc5bSSteven Rostedt    }
66575c3fda7SSteven Rostedt
666f80802cbSSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
667f80802cbSSteven Rostedt	print " See $opt{LOG_FILE} for more info.\n";
668f80802cbSSteven Rostedt    }
669f80802cbSSteven Rostedt
670576f627cSSteven Rostedt    die @_, "\n";
6715c42fc5bSSteven Rostedt}
6725c42fc5bSSteven Rostedt
6737faafbd6SSteven Rostedtsub open_console {
6747faafbd6SSteven Rostedt    my ($fp) = @_;
6757faafbd6SSteven Rostedt
6767faafbd6SSteven Rostedt    my $flags;
6777faafbd6SSteven Rostedt
678a75fececSSteven Rostedt    my $pid = open($fp, "$console|") or
679a75fececSSteven Rostedt	dodie "Can't open console $console";
6807faafbd6SSteven Rostedt
6817faafbd6SSteven Rostedt    $flags = fcntl($fp, F_GETFL, 0) or
682576f627cSSteven Rostedt	dodie "Can't get flags for the socket: $!";
6837faafbd6SSteven Rostedt    $flags = fcntl($fp, F_SETFL, $flags | O_NONBLOCK) or
684576f627cSSteven Rostedt	dodie "Can't set flags for the socket: $!";
6857faafbd6SSteven Rostedt
6867faafbd6SSteven Rostedt    return $pid;
6877faafbd6SSteven Rostedt}
6887faafbd6SSteven Rostedt
6897faafbd6SSteven Rostedtsub close_console {
6907faafbd6SSteven Rostedt    my ($fp, $pid) = @_;
6917faafbd6SSteven Rostedt
6927faafbd6SSteven Rostedt    doprint "kill child process $pid\n";
6937faafbd6SSteven Rostedt    kill 2, $pid;
6947faafbd6SSteven Rostedt
6957faafbd6SSteven Rostedt    print "closing!\n";
6967faafbd6SSteven Rostedt    close($fp);
6977faafbd6SSteven Rostedt}
6987faafbd6SSteven Rostedt
6997faafbd6SSteven Rostedtsub start_monitor {
7007faafbd6SSteven Rostedt    if ($monitor_cnt++) {
7017faafbd6SSteven Rostedt	return;
7027faafbd6SSteven Rostedt    }
7037faafbd6SSteven Rostedt    $monitor_fp = \*MONFD;
7047faafbd6SSteven Rostedt    $monitor_pid = open_console $monitor_fp;
705a75fececSSteven Rostedt
706a75fececSSteven Rostedt    return;
707a75fececSSteven Rostedt
708a75fececSSteven Rostedt    open(MONFD, "Stop perl from warning about single use of MONFD");
7097faafbd6SSteven Rostedt}
7107faafbd6SSteven Rostedt
7117faafbd6SSteven Rostedtsub end_monitor {
7127faafbd6SSteven Rostedt    if (--$monitor_cnt) {
7137faafbd6SSteven Rostedt	return;
7147faafbd6SSteven Rostedt    }
7157faafbd6SSteven Rostedt    close_console($monitor_fp, $monitor_pid);
7167faafbd6SSteven Rostedt}
7177faafbd6SSteven Rostedt
7187faafbd6SSteven Rostedtsub wait_for_monitor {
7192b803365SSteven Rostedt    my ($time, $stop) = @_;
7202b803365SSteven Rostedt    my $full_line = "";
7217faafbd6SSteven Rostedt    my $line;
7222b803365SSteven Rostedt    my $booted = 0;
7237faafbd6SSteven Rostedt
724a75fececSSteven Rostedt    doprint "** Wait for monitor to settle down **\n";
7257faafbd6SSteven Rostedt
7267faafbd6SSteven Rostedt    # read the monitor and wait for the system to calm down
7272b803365SSteven Rostedt    while (!$booted) {
7287faafbd6SSteven Rostedt	$line = wait_for_input($monitor_fp, $time);
7292b803365SSteven Rostedt	last if (!defined($line));
7302b803365SSteven Rostedt	print "$line";
7312b803365SSteven Rostedt	$full_line .= $line;
7322b803365SSteven Rostedt
7332b803365SSteven Rostedt	if (defined($stop) && $full_line =~ /$stop/) {
7342b803365SSteven Rostedt	    doprint "wait for monitor detected $stop\n";
7352b803365SSteven Rostedt	    $booted = 1;
7362b803365SSteven Rostedt	}
7372b803365SSteven Rostedt
7382b803365SSteven Rostedt	if ($line =~ /\n/) {
7392b803365SSteven Rostedt	    $full_line = "";
7402b803365SSteven Rostedt	}
7412b803365SSteven Rostedt    }
742a75fececSSteven Rostedt    print "** Monitor flushed **\n";
7437faafbd6SSteven Rostedt}
7447faafbd6SSteven Rostedt
7452b7d9b21SSteven Rostedtsub fail {
7462b7d9b21SSteven Rostedt
747a75fececSSteven Rostedt	if ($die_on_failure) {
7482b7d9b21SSteven Rostedt		dodie @_;
7492b7d9b21SSteven Rostedt	}
7502b7d9b21SSteven Rostedt
751a75fececSSteven Rostedt	doprint "FAILED\n";
7527faafbd6SSteven Rostedt
753576f627cSSteven Rostedt	my $i = $iteration;
754576f627cSSteven Rostedt
755a75fececSSteven Rostedt	# no need to reboot for just building.
756576f627cSSteven Rostedt	if (!do_not_reboot) {
7577faafbd6SSteven Rostedt	    doprint "REBOOTING\n";
7582728be41SAndrew Jones	    reboot $sleep_time;
759a75fececSSteven Rostedt	}
7607faafbd6SSteven Rostedt
7619064af52SSteven Rostedt	my $name = "";
7629064af52SSteven Rostedt
7639064af52SSteven Rostedt	if (defined($test_name)) {
7649064af52SSteven Rostedt	    $name = " ($test_name)";
7659064af52SSteven Rostedt	}
7669064af52SSteven Rostedt
767576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
768576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
7699064af52SSteven Rostedt	doprint "KTEST RESULT: TEST $i$name Failed: ", @_, "\n";
770576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
771576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
772a75fececSSteven Rostedt
773a75fececSSteven Rostedt	return 1 if (!defined($store_failures));
7747faafbd6SSteven Rostedt
7757faafbd6SSteven Rostedt	my @t = localtime;
7767faafbd6SSteven Rostedt	my $date = sprintf "%04d%02d%02d%02d%02d%02d",
7777faafbd6SSteven Rostedt		1900+$t[5],$t[4],$t[3],$t[2],$t[1],$t[0];
7787faafbd6SSteven Rostedt
779cccae1a6SSteven Rostedt	my $type = $build_type;
780cccae1a6SSteven Rostedt	if ($type =~ /useconfig/) {
781cccae1a6SSteven Rostedt	    $type = "useconfig";
782cccae1a6SSteven Rostedt	}
783cccae1a6SSteven Rostedt
784cccae1a6SSteven Rostedt	my $dir = "$machine-$test_type-$type-fail-$date";
785a75fececSSteven Rostedt	my $faildir = "$store_failures/$dir";
7867faafbd6SSteven Rostedt
7877faafbd6SSteven Rostedt	if (!-d $faildir) {
7887faafbd6SSteven Rostedt	    mkpath($faildir) or
789a75fececSSteven Rostedt		die "can't create $faildir";
7907faafbd6SSteven Rostedt	}
79151ad1dd1SSteven Rostedt	if (-f "$output_config") {
79251ad1dd1SSteven Rostedt	    cp "$output_config", "$faildir/config" or
7937faafbd6SSteven Rostedt		die "failed to copy .config";
7947faafbd6SSteven Rostedt	}
7957faafbd6SSteven Rostedt	if (-f $buildlog) {
7967faafbd6SSteven Rostedt	    cp $buildlog, "$faildir/buildlog" or
7977faafbd6SSteven Rostedt		die "failed to move $buildlog";
7987faafbd6SSteven Rostedt	}
7997faafbd6SSteven Rostedt	if (-f $dmesg) {
8007faafbd6SSteven Rostedt	    cp $dmesg, "$faildir/dmesg" or
8017faafbd6SSteven Rostedt		die "failed to move $dmesg";
8027faafbd6SSteven Rostedt	}
8037faafbd6SSteven Rostedt
8047faafbd6SSteven Rostedt	doprint "*** Saved info to $faildir ***\n";
8057faafbd6SSteven Rostedt
8062b7d9b21SSteven Rostedt	return 1;
8072b7d9b21SSteven Rostedt}
8082b7d9b21SSteven Rostedt
8092545eb61SSteven Rostedtsub run_command {
8102545eb61SSteven Rostedt    my ($command) = @_;
811d6ce2a0bSSteven Rostedt    my $dolog = 0;
812d6ce2a0bSSteven Rostedt    my $dord = 0;
813d6ce2a0bSSteven Rostedt    my $pid;
814d6ce2a0bSSteven Rostedt
815e48c5293SSteven Rostedt    $command =~ s/\$SSH_USER/$ssh_user/g;
816e48c5293SSteven Rostedt    $command =~ s/\$MACHINE/$machine/g;
817e48c5293SSteven Rostedt
818d6ce2a0bSSteven Rostedt    doprint("$command ... ");
819d6ce2a0bSSteven Rostedt
820d6ce2a0bSSteven Rostedt    $pid = open(CMD, "$command 2>&1 |") or
8212b7d9b21SSteven Rostedt	(fail "unable to exec $command" and return 0);
8222545eb61SSteven Rostedt
8232545eb61SSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
824d6ce2a0bSSteven Rostedt	open(LOG, ">>$opt{LOG_FILE}") or
825d6ce2a0bSSteven Rostedt	    dodie "failed to write to log";
826d6ce2a0bSSteven Rostedt	$dolog = 1;
8276c5ee0beSSteven Rostedt    }
8286c5ee0beSSteven Rostedt
8296c5ee0beSSteven Rostedt    if (defined($redirect)) {
830d6ce2a0bSSteven Rostedt	open (RD, ">$redirect") or
831d6ce2a0bSSteven Rostedt	    dodie "failed to write to redirect $redirect";
832d6ce2a0bSSteven Rostedt	$dord = 1;
8332545eb61SSteven Rostedt    }
8342545eb61SSteven Rostedt
835d6ce2a0bSSteven Rostedt    while (<CMD>) {
836d6ce2a0bSSteven Rostedt	print LOG if ($dolog);
837d6ce2a0bSSteven Rostedt	print RD  if ($dord);
838d6ce2a0bSSteven Rostedt    }
8392545eb61SSteven Rostedt
840d6ce2a0bSSteven Rostedt    waitpid($pid, 0);
8412545eb61SSteven Rostedt    my $failed = $?;
8422545eb61SSteven Rostedt
843d6ce2a0bSSteven Rostedt    close(CMD);
844d6ce2a0bSSteven Rostedt    close(LOG) if ($dolog);
845d6ce2a0bSSteven Rostedt    close(RD)  if ($dord);
846d6ce2a0bSSteven Rostedt
8472545eb61SSteven Rostedt    if ($failed) {
8482545eb61SSteven Rostedt	doprint "FAILED!\n";
8492545eb61SSteven Rostedt    } else {
8502545eb61SSteven Rostedt	doprint "SUCCESS\n";
8512545eb61SSteven Rostedt    }
8522545eb61SSteven Rostedt
8535f9b6cedSSteven Rostedt    return !$failed;
8545f9b6cedSSteven Rostedt}
8555f9b6cedSSteven Rostedt
856e48c5293SSteven Rostedtsub run_ssh {
857e48c5293SSteven Rostedt    my ($cmd) = @_;
858e48c5293SSteven Rostedt    my $cp_exec = $ssh_exec;
859e48c5293SSteven Rostedt
860e48c5293SSteven Rostedt    $cp_exec =~ s/\$SSH_COMMAND/$cmd/g;
861e48c5293SSteven Rostedt    return run_command "$cp_exec";
862e48c5293SSteven Rostedt}
863e48c5293SSteven Rostedt
864e48c5293SSteven Rostedtsub run_scp {
865e48c5293SSteven Rostedt    my ($src, $dst) = @_;
866e48c5293SSteven Rostedt    my $cp_scp = $scp_to_target;
867e48c5293SSteven Rostedt
868e48c5293SSteven Rostedt    $cp_scp =~ s/\$SRC_FILE/$src/g;
869e48c5293SSteven Rostedt    $cp_scp =~ s/\$DST_FILE/$dst/g;
870e48c5293SSteven Rostedt
871e48c5293SSteven Rostedt    return run_command "$cp_scp";
872e48c5293SSteven Rostedt}
873e48c5293SSteven Rostedt
8745f9b6cedSSteven Rostedtsub get_grub_index {
8755f9b6cedSSteven Rostedt
876a75fececSSteven Rostedt    if ($reboot_type ne "grub") {
877a75fececSSteven Rostedt	return;
878a75fececSSteven Rostedt    }
8795a391fbfSSteven Rostedt    return if (defined($grub_number));
8805f9b6cedSSteven Rostedt
8815f9b6cedSSteven Rostedt    doprint "Find grub menu ... ";
8825f9b6cedSSteven Rostedt    $grub_number = -1;
883e48c5293SSteven Rostedt
884e48c5293SSteven Rostedt    my $ssh_grub = $ssh_exec;
885e48c5293SSteven Rostedt    $ssh_grub =~ s,\$SSH_COMMAND,cat /boot/grub/menu.lst,g;
886e48c5293SSteven Rostedt
887e48c5293SSteven Rostedt    open(IN, "$ssh_grub |")
8885f9b6cedSSteven Rostedt	or die "unable to get menu.lst";
889e48c5293SSteven Rostedt
890eaa1fe25SSteven Rostedt    my $found = 0;
891eaa1fe25SSteven Rostedt
8925f9b6cedSSteven Rostedt    while (<IN>) {
893a75fececSSteven Rostedt	if (/^\s*title\s+$grub_menu\s*$/) {
8945f9b6cedSSteven Rostedt	    $grub_number++;
895eaa1fe25SSteven Rostedt	    $found = 1;
8965f9b6cedSSteven Rostedt	    last;
8975f9b6cedSSteven Rostedt	} elsif (/^\s*title\s/) {
8985f9b6cedSSteven Rostedt	    $grub_number++;
8995f9b6cedSSteven Rostedt	}
9005f9b6cedSSteven Rostedt    }
9015f9b6cedSSteven Rostedt    close(IN);
9025f9b6cedSSteven Rostedt
903a75fececSSteven Rostedt    die "Could not find '$grub_menu' in /boot/grub/menu on $machine"
904eaa1fe25SSteven Rostedt	if (!$found);
9055f9b6cedSSteven Rostedt    doprint "$grub_number\n";
9062545eb61SSteven Rostedt}
9072545eb61SSteven Rostedt
9082545eb61SSteven Rostedtsub wait_for_input
9092545eb61SSteven Rostedt{
9102545eb61SSteven Rostedt    my ($fp, $time) = @_;
9112545eb61SSteven Rostedt    my $rin;
9122545eb61SSteven Rostedt    my $ready;
9132545eb61SSteven Rostedt    my $line;
9142545eb61SSteven Rostedt    my $ch;
9152545eb61SSteven Rostedt
9162545eb61SSteven Rostedt    if (!defined($time)) {
9172545eb61SSteven Rostedt	$time = $timeout;
9182545eb61SSteven Rostedt    }
9192545eb61SSteven Rostedt
9202545eb61SSteven Rostedt    $rin = '';
9212545eb61SSteven Rostedt    vec($rin, fileno($fp), 1) = 1;
9222545eb61SSteven Rostedt    $ready = select($rin, undef, undef, $time);
9232545eb61SSteven Rostedt
9242545eb61SSteven Rostedt    $line = "";
9252545eb61SSteven Rostedt
9262545eb61SSteven Rostedt    # try to read one char at a time
9272545eb61SSteven Rostedt    while (sysread $fp, $ch, 1) {
9282545eb61SSteven Rostedt	$line .= $ch;
9292545eb61SSteven Rostedt	last if ($ch eq "\n");
9302545eb61SSteven Rostedt    }
9312545eb61SSteven Rostedt
9322545eb61SSteven Rostedt    if (!length($line)) {
9332545eb61SSteven Rostedt	return undef;
9342545eb61SSteven Rostedt    }
9352545eb61SSteven Rostedt
9362545eb61SSteven Rostedt    return $line;
9372545eb61SSteven Rostedt}
9382545eb61SSteven Rostedt
93975c3fda7SSteven Rostedtsub reboot_to {
940a75fececSSteven Rostedt    if ($reboot_type eq "grub") {
9414da46da2SSteven Rostedt	run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch && reboot)'";
942a75fececSSteven Rostedt	return;
943a75fececSSteven Rostedt    }
944a75fececSSteven Rostedt
945a75fececSSteven Rostedt    run_command "$reboot_script";
9462545eb61SSteven Rostedt}
9472545eb61SSteven Rostedt
948a57419b3SSteven Rostedtsub get_sha1 {
949a57419b3SSteven Rostedt    my ($commit) = @_;
950a57419b3SSteven Rostedt
951a57419b3SSteven Rostedt    doprint "git rev-list --max-count=1 $commit ... ";
952a57419b3SSteven Rostedt    my $sha1 = `git rev-list --max-count=1 $commit`;
953a57419b3SSteven Rostedt    my $ret = $?;
954a57419b3SSteven Rostedt
955a57419b3SSteven Rostedt    logit $sha1;
956a57419b3SSteven Rostedt
957a57419b3SSteven Rostedt    if ($ret) {
958a57419b3SSteven Rostedt	doprint "FAILED\n";
959a57419b3SSteven Rostedt	dodie "Failed to get git $commit";
960a57419b3SSteven Rostedt    }
961a57419b3SSteven Rostedt
962a57419b3SSteven Rostedt    print "SUCCESS\n";
963a57419b3SSteven Rostedt
964a57419b3SSteven Rostedt    chomp $sha1;
965a57419b3SSteven Rostedt
966a57419b3SSteven Rostedt    return $sha1;
967a57419b3SSteven Rostedt}
968a57419b3SSteven Rostedt
9695a391fbfSSteven Rostedtsub monitor {
9702545eb61SSteven Rostedt    my $booted = 0;
9712545eb61SSteven Rostedt    my $bug = 0;
9725c42fc5bSSteven Rostedt    my $skip_call_trace = 0;
9732b7d9b21SSteven Rostedt    my $loops;
9742545eb61SSteven Rostedt
9757faafbd6SSteven Rostedt    wait_for_monitor 5;
9762545eb61SSteven Rostedt
9772545eb61SSteven Rostedt    my $line;
9782545eb61SSteven Rostedt    my $full_line = "";
9792545eb61SSteven Rostedt
9807faafbd6SSteven Rostedt    open(DMESG, "> $dmesg") or
9817faafbd6SSteven Rostedt	die "unable to write to $dmesg";
9822545eb61SSteven Rostedt
98375c3fda7SSteven Rostedt    reboot_to;
9842545eb61SSteven Rostedt
9851c8a617aSSteven Rostedt    my $success_start;
9861c8a617aSSteven Rostedt    my $failure_start;
9872d01b26aSSteven Rostedt    my $monitor_start = time;
9882d01b26aSSteven Rostedt    my $done = 0;
989f1a5b962SSteven Rostedt    my $version_found = 0;
9901c8a617aSSteven Rostedt
9912d01b26aSSteven Rostedt    while (!$done) {
9922545eb61SSteven Rostedt
993ecaf8e52SSteven Rostedt	if ($bug && defined($stop_after_failure) &&
994ecaf8e52SSteven Rostedt	    $stop_after_failure >= 0) {
995ecaf8e52SSteven Rostedt	    my $time = $stop_after_failure - (time - $failure_start);
996ecaf8e52SSteven Rostedt	    $line = wait_for_input($monitor_fp, $time);
997ecaf8e52SSteven Rostedt	    if (!defined($line)) {
998ecaf8e52SSteven Rostedt		doprint "bug timed out after $booted_timeout seconds\n";
999ecaf8e52SSteven Rostedt		doprint "Test forced to stop after $stop_after_failure seconds after failure\n";
1000ecaf8e52SSteven Rostedt		last;
1001ecaf8e52SSteven Rostedt	    }
1002ecaf8e52SSteven Rostedt	} elsif ($booted) {
1003a75fececSSteven Rostedt	    $line = wait_for_input($monitor_fp, $booted_timeout);
1004cd4f1d53SSteven Rostedt	    if (!defined($line)) {
1005cd4f1d53SSteven Rostedt		my $s = $booted_timeout == 1 ? "" : "s";
1006cd4f1d53SSteven Rostedt		doprint "Successful boot found: break after $booted_timeout second$s\n";
1007cd4f1d53SSteven Rostedt		last;
1008cd4f1d53SSteven Rostedt	    }
10092b7d9b21SSteven Rostedt	} else {
10107faafbd6SSteven Rostedt	    $line = wait_for_input($monitor_fp);
1011cd4f1d53SSteven Rostedt	    if (!defined($line)) {
1012cd4f1d53SSteven Rostedt		my $s = $timeout == 1 ? "" : "s";
1013cd4f1d53SSteven Rostedt		doprint "Timed out after $timeout second$s\n";
1014cd4f1d53SSteven Rostedt		last;
10152b7d9b21SSteven Rostedt	    }
1016cd4f1d53SSteven Rostedt	}
10172545eb61SSteven Rostedt
10182545eb61SSteven Rostedt	doprint $line;
10197faafbd6SSteven Rostedt	print DMESG $line;
10202545eb61SSteven Rostedt
10212545eb61SSteven Rostedt	# we are not guaranteed to get a full line
10222545eb61SSteven Rostedt	$full_line .= $line;
10232545eb61SSteven Rostedt
1024a75fececSSteven Rostedt	if ($full_line =~ /$success_line/) {
10252545eb61SSteven Rostedt	    $booted = 1;
10261c8a617aSSteven Rostedt	    $success_start = time;
10271c8a617aSSteven Rostedt	}
10281c8a617aSSteven Rostedt
10291c8a617aSSteven Rostedt	if ($booted && defined($stop_after_success) &&
10301c8a617aSSteven Rostedt	    $stop_after_success >= 0) {
10311c8a617aSSteven Rostedt	    my $now = time;
10321c8a617aSSteven Rostedt	    if ($now - $success_start >= $stop_after_success) {
10331c8a617aSSteven Rostedt		doprint "Test forced to stop after $stop_after_success seconds after success\n";
10341c8a617aSSteven Rostedt		last;
10351c8a617aSSteven Rostedt	    }
10362545eb61SSteven Rostedt	}
10372545eb61SSteven Rostedt
10385c42fc5bSSteven Rostedt	if ($full_line =~ /\[ backtrace testing \]/) {
10395c42fc5bSSteven Rostedt	    $skip_call_trace = 1;
10405c42fc5bSSteven Rostedt	}
10415c42fc5bSSteven Rostedt
10422545eb61SSteven Rostedt	if ($full_line =~ /call trace:/i) {
10434651920eSSteven Rostedt	    if (!$bug && !$skip_call_trace) {
10441c8a617aSSteven Rostedt		$bug = 1;
10451c8a617aSSteven Rostedt		$failure_start = time;
10461c8a617aSSteven Rostedt	    }
10471c8a617aSSteven Rostedt	}
10481c8a617aSSteven Rostedt
10491c8a617aSSteven Rostedt	if ($bug && defined($stop_after_failure) &&
10501c8a617aSSteven Rostedt	    $stop_after_failure >= 0) {
10511c8a617aSSteven Rostedt	    my $now = time;
10521c8a617aSSteven Rostedt	    if ($now - $failure_start >= $stop_after_failure) {
10531c8a617aSSteven Rostedt		doprint "Test forced to stop after $stop_after_failure seconds after failure\n";
10541c8a617aSSteven Rostedt		last;
10551c8a617aSSteven Rostedt	    }
10565c42fc5bSSteven Rostedt	}
10575c42fc5bSSteven Rostedt
10585c42fc5bSSteven Rostedt	if ($full_line =~ /\[ end of backtrace testing \]/) {
10595c42fc5bSSteven Rostedt	    $skip_call_trace = 0;
10605c42fc5bSSteven Rostedt	}
10615c42fc5bSSteven Rostedt
10625c42fc5bSSteven Rostedt	if ($full_line =~ /Kernel panic -/) {
106310abf118SSteven Rostedt	    $failure_start = time;
10642545eb61SSteven Rostedt	    $bug = 1;
10652545eb61SSteven Rostedt	}
10662545eb61SSteven Rostedt
1067f1a5b962SSteven Rostedt	# Detect triple faults by testing the banner
1068f1a5b962SSteven Rostedt	if ($full_line =~ /\bLinux version (\S+).*\n/) {
1069f1a5b962SSteven Rostedt	    if ($1 eq $version) {
1070f1a5b962SSteven Rostedt		$version_found = 1;
1071f1a5b962SSteven Rostedt	    } elsif ($version_found && $detect_triplefault) {
1072f1a5b962SSteven Rostedt		# We already booted into the kernel we are testing,
1073f1a5b962SSteven Rostedt		# but now we booted into another kernel?
1074f1a5b962SSteven Rostedt		# Consider this a triple fault.
1075f1a5b962SSteven Rostedt		doprint "Aleady booted in Linux kernel $version, but now\n";
1076f1a5b962SSteven Rostedt		doprint "we booted into Linux kernel $1.\n";
1077f1a5b962SSteven Rostedt		doprint "Assuming that this is a triple fault.\n";
1078f1a5b962SSteven Rostedt		doprint "To disable this: set DETECT_TRIPLE_FAULT to 0\n";
1079f1a5b962SSteven Rostedt		last;
1080f1a5b962SSteven Rostedt	    }
1081f1a5b962SSteven Rostedt	}
1082f1a5b962SSteven Rostedt
10832545eb61SSteven Rostedt	if ($line =~ /\n/) {
10842545eb61SSteven Rostedt	    $full_line = "";
10852545eb61SSteven Rostedt	}
10862d01b26aSSteven Rostedt
10872d01b26aSSteven Rostedt	if ($stop_test_after > 0 && !$booted && !$bug) {
10882d01b26aSSteven Rostedt	    if (time - $monitor_start > $stop_test_after) {
10894d62bf51SSteven Rostedt		doprint "STOP_TEST_AFTER ($stop_test_after seconds) timed out\n";
10902d01b26aSSteven Rostedt		$done = 1;
10912d01b26aSSteven Rostedt	    }
10922d01b26aSSteven Rostedt	}
10932545eb61SSteven Rostedt    }
10942545eb61SSteven Rostedt
10957faafbd6SSteven Rostedt    close(DMESG);
10962545eb61SSteven Rostedt
10972545eb61SSteven Rostedt    if ($bug) {
10982b7d9b21SSteven Rostedt	return 0 if ($in_bisect);
1099576f627cSSteven Rostedt	fail "failed - got a bug report" and return 0;
11002545eb61SSteven Rostedt    }
11015f9b6cedSSteven Rostedt
1102a75fececSSteven Rostedt    if (!$booted) {
1103a75fececSSteven Rostedt	return 0 if ($in_bisect);
1104576f627cSSteven Rostedt	fail "failed - never got a boot prompt." and return 0;
1105a75fececSSteven Rostedt    }
1106a75fececSSteven Rostedt
11072b7d9b21SSteven Rostedt    return 1;
11082545eb61SSteven Rostedt}
11092545eb61SSteven Rostedt
1110db05cfefSSteven Rostedtsub do_post_install {
1111db05cfefSSteven Rostedt
1112db05cfefSSteven Rostedt    return if (!defined($post_install));
1113db05cfefSSteven Rostedt
1114db05cfefSSteven Rostedt    my $cp_post_install = $post_install;
1115db05cfefSSteven Rostedt    $cp_post_install =~ s/\$KERNEL_VERSION/$version/g;
1116db05cfefSSteven Rostedt    run_command "$cp_post_install" or
1117db05cfefSSteven Rostedt	dodie "Failed to run post install";
1118db05cfefSSteven Rostedt}
1119db05cfefSSteven Rostedt
11202545eb61SSteven Rostedtsub install {
11212545eb61SSteven Rostedt
1122e0a8742eSSteven Rostedt    return if ($no_install);
1123e0a8742eSSteven Rostedt
1124e48c5293SSteven Rostedt    run_scp "$outputdir/$build_target", "$target_image" or
11255c42fc5bSSteven Rostedt	dodie "failed to copy image";
11265f9b6cedSSteven Rostedt
11275f9b6cedSSteven Rostedt    my $install_mods = 0;
11285f9b6cedSSteven Rostedt
11295f9b6cedSSteven Rostedt    # should we process modules?
11305f9b6cedSSteven Rostedt    $install_mods = 0;
113151ad1dd1SSteven Rostedt    open(IN, "$output_config") or dodie("Can't read config file");
11325f9b6cedSSteven Rostedt    while (<IN>) {
11335f9b6cedSSteven Rostedt	if (/CONFIG_MODULES(=y)?/) {
11345f9b6cedSSteven Rostedt	    $install_mods = 1 if (defined($1));
11355f9b6cedSSteven Rostedt	    last;
11365f9b6cedSSteven Rostedt	}
11375f9b6cedSSteven Rostedt    }
11385f9b6cedSSteven Rostedt    close(IN);
11395f9b6cedSSteven Rostedt
11405f9b6cedSSteven Rostedt    if (!$install_mods) {
1141db05cfefSSteven Rostedt	do_post_install;
11425f9b6cedSSteven Rostedt	doprint "No modules needed\n";
11435f9b6cedSSteven Rostedt	return;
11442545eb61SSteven Rostedt    }
11452545eb61SSteven Rostedt
1146a75fececSSteven Rostedt    run_command "$make INSTALL_MOD_PATH=$tmpdir modules_install" or
11475f9b6cedSSteven Rostedt	dodie "Failed to install modules";
11485f9b6cedSSteven Rostedt
11492545eb61SSteven Rostedt    my $modlib = "/lib/modules/$version";
1150a57419b3SSteven Rostedt    my $modtar = "ktest-mods.tar.bz2";
11512545eb61SSteven Rostedt
1152e48c5293SSteven Rostedt    run_ssh "rm -rf $modlib" or
11535c42fc5bSSteven Rostedt	dodie "failed to remove old mods: $modlib";
11542545eb61SSteven Rostedt
11555c42fc5bSSteven Rostedt    # would be nice if scp -r did not follow symbolic links
1156a75fececSSteven Rostedt    run_command "cd $tmpdir && tar -cjf $modtar lib/modules/$version" or
11575c42fc5bSSteven Rostedt	dodie "making tarball";
11585c42fc5bSSteven Rostedt
1159e48c5293SSteven Rostedt    run_scp "$tmpdir/$modtar", "/tmp" or
11605c42fc5bSSteven Rostedt	dodie "failed to copy modules";
11615c42fc5bSSteven Rostedt
1162a75fececSSteven Rostedt    unlink "$tmpdir/$modtar";
11635c42fc5bSSteven Rostedt
1164e7b13441SSteven Rostedt    run_ssh "'(cd / && tar xjf /tmp/$modtar)'" or
11655c42fc5bSSteven Rostedt	dodie "failed to tar modules";
11665c42fc5bSSteven Rostedt
1167e48c5293SSteven Rostedt    run_ssh "rm -f /tmp/$modtar";
11688b37ca8cSSteven Rostedt
1169db05cfefSSteven Rostedt    do_post_install;
11702545eb61SSteven Rostedt}
11712545eb61SSteven Rostedt
1172ddf607e5SSteven Rostedtsub get_version {
1173ddf607e5SSteven Rostedt    # get the release name
1174ddf607e5SSteven Rostedt    doprint "$make kernelrelease ... ";
1175ddf607e5SSteven Rostedt    $version = `$make kernelrelease | tail -1`;
1176ddf607e5SSteven Rostedt    chomp($version);
1177ddf607e5SSteven Rostedt    doprint "$version\n";
1178ddf607e5SSteven Rostedt}
1179ddf607e5SSteven Rostedt
1180ddf607e5SSteven Rostedtsub start_monitor_and_boot {
1181ddf607e5SSteven Rostedt    get_grub_index;
1182ddf607e5SSteven Rostedt    get_version;
1183ddf607e5SSteven Rostedt    install;
1184ddf607e5SSteven Rostedt
1185ddf607e5SSteven Rostedt    start_monitor;
1186ddf607e5SSteven Rostedt    return monitor;
1187ddf607e5SSteven Rostedt}
1188ddf607e5SSteven Rostedt
11896c5ee0beSSteven Rostedtsub check_buildlog {
11906c5ee0beSSteven Rostedt    my ($patch) = @_;
11916c5ee0beSSteven Rostedt
11926c5ee0beSSteven Rostedt    my @files = `git show $patch | diffstat -l`;
11936c5ee0beSSteven Rostedt
11946c5ee0beSSteven Rostedt    open(IN, "git show $patch |") or
11956c5ee0beSSteven Rostedt	dodie "failed to show $patch";
11966c5ee0beSSteven Rostedt    while (<IN>) {
11976c5ee0beSSteven Rostedt	if (m,^--- a/(.*),) {
11986c5ee0beSSteven Rostedt	    chomp $1;
11996c5ee0beSSteven Rostedt	    $files[$#files] = $1;
12006c5ee0beSSteven Rostedt	}
12016c5ee0beSSteven Rostedt    }
12026c5ee0beSSteven Rostedt    close(IN);
12036c5ee0beSSteven Rostedt
12046c5ee0beSSteven Rostedt    open(IN, $buildlog) or dodie "Can't open $buildlog";
12056c5ee0beSSteven Rostedt    while (<IN>) {
12066c5ee0beSSteven Rostedt	if (/^\s*(.*?):.*(warning|error)/) {
12076c5ee0beSSteven Rostedt	    my $err = $1;
12086c5ee0beSSteven Rostedt	    foreach my $file (@files) {
1209a75fececSSteven Rostedt		my $fullpath = "$builddir/$file";
12106c5ee0beSSteven Rostedt		if ($file eq $err || $fullpath eq $err) {
12112b7d9b21SSteven Rostedt		    fail "$file built with warnings" and return 0;
12126c5ee0beSSteven Rostedt		}
12136c5ee0beSSteven Rostedt	    }
12146c5ee0beSSteven Rostedt	}
12156c5ee0beSSteven Rostedt    }
12166c5ee0beSSteven Rostedt    close(IN);
12172b7d9b21SSteven Rostedt
12182b7d9b21SSteven Rostedt    return 1;
12196c5ee0beSSteven Rostedt}
12206c5ee0beSSteven Rostedt
1221fcb3f16aSSteven Rostedtsub apply_min_config {
1222fcb3f16aSSteven Rostedt    my $outconfig = "$output_config.new";
1223612b9e9bSSteven Rostedt
1224fcb3f16aSSteven Rostedt    # Read the config file and remove anything that
1225fcb3f16aSSteven Rostedt    # is in the force_config hash (from minconfig and others)
1226fcb3f16aSSteven Rostedt    # then add the force config back.
1227fcb3f16aSSteven Rostedt
1228fcb3f16aSSteven Rostedt    doprint "Applying minimum configurations into $output_config.new\n";
1229fcb3f16aSSteven Rostedt
1230fcb3f16aSSteven Rostedt    open (OUT, ">$outconfig") or
1231fcb3f16aSSteven Rostedt	dodie "Can't create $outconfig";
1232fcb3f16aSSteven Rostedt
1233fcb3f16aSSteven Rostedt    if (-f $output_config) {
1234fcb3f16aSSteven Rostedt	open (IN, $output_config) or
1235fcb3f16aSSteven Rostedt	    dodie "Failed to open $output_config";
1236fcb3f16aSSteven Rostedt	while (<IN>) {
1237fcb3f16aSSteven Rostedt	    if (/^(# )?(CONFIG_[^\s=]*)/) {
1238fcb3f16aSSteven Rostedt		next if (defined($force_config{$2}));
1239fcb3f16aSSteven Rostedt	    }
1240fcb3f16aSSteven Rostedt	    print OUT;
1241fcb3f16aSSteven Rostedt	}
1242fcb3f16aSSteven Rostedt	close IN;
1243fcb3f16aSSteven Rostedt    }
1244fcb3f16aSSteven Rostedt    foreach my $config (keys %force_config) {
1245fcb3f16aSSteven Rostedt	print OUT "$force_config{$config}\n";
1246fcb3f16aSSteven Rostedt    }
1247fcb3f16aSSteven Rostedt    close OUT;
1248fcb3f16aSSteven Rostedt
1249fcb3f16aSSteven Rostedt    run_command "mv $outconfig $output_config";
1250fcb3f16aSSteven Rostedt}
1251fcb3f16aSSteven Rostedt
1252fcb3f16aSSteven Rostedtsub make_oldconfig {
1253fcb3f16aSSteven Rostedt
12544c4ab120SSteven Rostedt    my @force_list = keys %force_config;
12554c4ab120SSteven Rostedt
12564c4ab120SSteven Rostedt    if ($#force_list >= 0) {
1257fcb3f16aSSteven Rostedt	apply_min_config;
12584c4ab120SSteven Rostedt    }
1259fcb3f16aSSteven Rostedt
1260fcb3f16aSSteven Rostedt    if (!run_command "$make oldnoconfig") {
1261612b9e9bSSteven Rostedt	# Perhaps oldnoconfig doesn't exist in this version of the kernel
1262612b9e9bSSteven Rostedt	# try a yes '' | oldconfig
1263612b9e9bSSteven Rostedt	doprint "oldnoconfig failed, trying yes '' | make oldconfig\n";
1264fcb3f16aSSteven Rostedt	run_command "yes '' | $make oldconfig" or
1265612b9e9bSSteven Rostedt	    dodie "failed make config oldconfig";
1266612b9e9bSSteven Rostedt    }
1267612b9e9bSSteven Rostedt}
1268612b9e9bSSteven Rostedt
1269fcb3f16aSSteven Rostedt# read a config file and use this to force new configs.
1270fcb3f16aSSteven Rostedtsub load_force_config {
1271fcb3f16aSSteven Rostedt    my ($config) = @_;
1272fcb3f16aSSteven Rostedt
1273fcb3f16aSSteven Rostedt    open(IN, $config) or
1274fcb3f16aSSteven Rostedt	dodie "failed to read $config";
1275fcb3f16aSSteven Rostedt    while (<IN>) {
1276fcb3f16aSSteven Rostedt	chomp;
1277fcb3f16aSSteven Rostedt	if (/^(CONFIG[^\s=]*)(\s*=.*)/) {
1278fcb3f16aSSteven Rostedt	    $force_config{$1} = $_;
1279fcb3f16aSSteven Rostedt	} elsif (/^# (CONFIG_\S*) is not set/) {
1280fcb3f16aSSteven Rostedt	    $force_config{$1} = $_;
1281fcb3f16aSSteven Rostedt	}
1282fcb3f16aSSteven Rostedt    }
1283fcb3f16aSSteven Rostedt    close IN;
1284fcb3f16aSSteven Rostedt}
1285fcb3f16aSSteven Rostedt
12862545eb61SSteven Rostedtsub build {
12872545eb61SSteven Rostedt    my ($type) = @_;
12882545eb61SSteven Rostedt
12897faafbd6SSteven Rostedt    unlink $buildlog;
12907faafbd6SSteven Rostedt
1291*4ab1cce5SSteven Rostedt    # Failed builds should not reboot the target
1292*4ab1cce5SSteven Rostedt    my $save_no_reboot = $no_reboot;
1293*4ab1cce5SSteven Rostedt    $no_reboot = 1;
1294*4ab1cce5SSteven Rostedt
12950bd6c1a3SSteven Rostedt    if (defined($pre_build)) {
12960bd6c1a3SSteven Rostedt	my $ret = run_command $pre_build;
12970bd6c1a3SSteven Rostedt	if (!$ret && defined($pre_build_die) &&
12980bd6c1a3SSteven Rostedt	    $pre_build_die) {
12990bd6c1a3SSteven Rostedt	    dodie "failed to pre_build\n";
13000bd6c1a3SSteven Rostedt	}
13010bd6c1a3SSteven Rostedt    }
13020bd6c1a3SSteven Rostedt
130375c3fda7SSteven Rostedt    if ($type =~ /^useconfig:(.*)/) {
130451ad1dd1SSteven Rostedt	run_command "cp $1 $output_config" or
130575c3fda7SSteven Rostedt	    dodie "could not copy $1 to .config";
13065f9b6cedSSteven Rostedt
130775c3fda7SSteven Rostedt	$type = "oldconfig";
130875c3fda7SSteven Rostedt    }
130975c3fda7SSteven Rostedt
13105c42fc5bSSteven Rostedt    # old config can ask questions
13115c42fc5bSSteven Rostedt    if ($type eq "oldconfig") {
13129386c6abSSteven Rostedt	$type = "oldnoconfig";
131375c3fda7SSteven Rostedt
131475c3fda7SSteven Rostedt	# allow for empty configs
131551ad1dd1SSteven Rostedt	run_command "touch $output_config";
131675c3fda7SSteven Rostedt
131713488231SAndrew Jones	if (!$noclean) {
131851ad1dd1SSteven Rostedt	    run_command "mv $output_config $outputdir/config_temp" or
13195c42fc5bSSteven Rostedt		dodie "moving .config";
13205c42fc5bSSteven Rostedt
132113488231SAndrew Jones	    run_command "$make mrproper" or dodie "make mrproper";
13225c42fc5bSSteven Rostedt
132351ad1dd1SSteven Rostedt	    run_command "mv $outputdir/config_temp $output_config" or
13245c42fc5bSSteven Rostedt		dodie "moving config_temp";
132513488231SAndrew Jones	}
13265c42fc5bSSteven Rostedt
13275c42fc5bSSteven Rostedt    } elsif (!$noclean) {
132851ad1dd1SSteven Rostedt	unlink "$output_config";
13295f9b6cedSSteven Rostedt	run_command "$make mrproper" or
13305c42fc5bSSteven Rostedt	    dodie "make mrproper";
13315c42fc5bSSteven Rostedt    }
13322545eb61SSteven Rostedt
13332545eb61SSteven Rostedt    # add something to distinguish this build
1334a75fececSSteven Rostedt    open(OUT, "> $outputdir/localversion") or dodie("Can't make localversion file");
1335a75fececSSteven Rostedt    print OUT "$localversion\n";
13362545eb61SSteven Rostedt    close(OUT);
13372545eb61SSteven Rostedt
13385f9b6cedSSteven Rostedt    if (defined($minconfig)) {
1339fcb3f16aSSteven Rostedt	load_force_config($minconfig);
13402545eb61SSteven Rostedt    }
13412545eb61SSteven Rostedt
1342fcb3f16aSSteven Rostedt    if ($type ne "oldnoconfig") {
1343fcb3f16aSSteven Rostedt	run_command "$make $type" or
13445c42fc5bSSteven Rostedt	    dodie "failed make config";
1345612b9e9bSSteven Rostedt    }
1346fcb3f16aSSteven Rostedt    # Run old config regardless, to enforce min configurations
1347fcb3f16aSSteven Rostedt    make_oldconfig;
13482545eb61SSteven Rostedt
1349a75fececSSteven Rostedt    $redirect = "$buildlog";
13500bd6c1a3SSteven Rostedt    my $build_ret = run_command "$make $build_options";
13516c5ee0beSSteven Rostedt    undef $redirect;
13520bd6c1a3SSteven Rostedt
13530bd6c1a3SSteven Rostedt    if (defined($post_build)) {
13540bd6c1a3SSteven Rostedt	my $ret = run_command $post_build;
13550bd6c1a3SSteven Rostedt	if (!$ret && defined($post_build_die) &&
13560bd6c1a3SSteven Rostedt	    $post_build_die) {
13570bd6c1a3SSteven Rostedt	    dodie "failed to post_build\n";
13580bd6c1a3SSteven Rostedt	}
13590bd6c1a3SSteven Rostedt    }
13600bd6c1a3SSteven Rostedt
13610bd6c1a3SSteven Rostedt    if (!$build_ret) {
13625f9b6cedSSteven Rostedt	# bisect may need this to pass
1363*4ab1cce5SSteven Rostedt	if ($in_bisect) {
1364*4ab1cce5SSteven Rostedt	    $no_reboot = $save_no_reboot;
1365*4ab1cce5SSteven Rostedt	    return 0;
1366*4ab1cce5SSteven Rostedt	}
13672b7d9b21SSteven Rostedt	fail "failed build" and return 0;
13682545eb61SSteven Rostedt    }
13695f9b6cedSSteven Rostedt
1370*4ab1cce5SSteven Rostedt    $no_reboot = $save_no_reboot;
1371*4ab1cce5SSteven Rostedt
13722b7d9b21SSteven Rostedt    return 1;
13732545eb61SSteven Rostedt}
13742545eb61SSteven Rostedt
137575c3fda7SSteven Rostedtsub halt {
1376e48c5293SSteven Rostedt    if (!run_ssh "halt" or defined($power_off)) {
1377576f627cSSteven Rostedt	if (defined($poweroff_after_halt)) {
1378576f627cSSteven Rostedt	    sleep $poweroff_after_halt;
1379576f627cSSteven Rostedt	    run_command "$power_off";
1380576f627cSSteven Rostedt	}
1381576f627cSSteven Rostedt    } else {
138275c3fda7SSteven Rostedt	# nope? the zap it!
1383a75fececSSteven Rostedt	run_command "$power_off";
138475c3fda7SSteven Rostedt    }
138575c3fda7SSteven Rostedt}
138675c3fda7SSteven Rostedt
13875f9b6cedSSteven Rostedtsub success {
13885f9b6cedSSteven Rostedt    my ($i) = @_;
13895f9b6cedSSteven Rostedt
1390e48c5293SSteven Rostedt    $successes++;
1391e48c5293SSteven Rostedt
13929064af52SSteven Rostedt    my $name = "";
13939064af52SSteven Rostedt
13949064af52SSteven Rostedt    if (defined($test_name)) {
13959064af52SSteven Rostedt	$name = " ($test_name)";
13969064af52SSteven Rostedt    }
13979064af52SSteven Rostedt
13985f9b6cedSSteven Rostedt    doprint "\n\n*******************************************\n";
13995f9b6cedSSteven Rostedt    doprint     "*******************************************\n";
14009064af52SSteven Rostedt    doprint     "KTEST RESULT: TEST $i$name SUCCESS!!!!         **\n";
14015f9b6cedSSteven Rostedt    doprint     "*******************************************\n";
14025f9b6cedSSteven Rostedt    doprint     "*******************************************\n";
14035f9b6cedSSteven Rostedt
1404576f627cSSteven Rostedt    if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) {
1405a75fececSSteven Rostedt	doprint "Reboot and wait $sleep_time seconds\n";
14062728be41SAndrew Jones	reboot $sleep_time;
14075f9b6cedSSteven Rostedt    }
14085f9b6cedSSteven Rostedt}
14095f9b6cedSSteven Rostedt
1410c960bb9fSSteven Rostedtsub answer_bisect {
1411c960bb9fSSteven Rostedt    for (;;) {
1412c960bb9fSSteven Rostedt	doprint "Pass or fail? [p/f]";
1413c960bb9fSSteven Rostedt	my $ans = <STDIN>;
1414c960bb9fSSteven Rostedt	chomp $ans;
1415c960bb9fSSteven Rostedt	if ($ans eq "p" || $ans eq "P") {
1416c960bb9fSSteven Rostedt	    return 1;
1417c960bb9fSSteven Rostedt	} elsif ($ans eq "f" || $ans eq "F") {
1418c960bb9fSSteven Rostedt	    return 0;
1419c960bb9fSSteven Rostedt	} else {
1420c960bb9fSSteven Rostedt	    print "Please answer 'P' or 'F'\n";
1421c960bb9fSSteven Rostedt	}
1422c960bb9fSSteven Rostedt    }
1423c960bb9fSSteven Rostedt}
1424c960bb9fSSteven Rostedt
14255a391fbfSSteven Rostedtsub child_run_test {
14267faafbd6SSteven Rostedt    my $failed = 0;
14275a391fbfSSteven Rostedt
14287faafbd6SSteven Rostedt    # child should have no power
1429a75fececSSteven Rostedt    $reboot_on_error = 0;
1430a75fececSSteven Rostedt    $poweroff_on_error = 0;
1431a75fececSSteven Rostedt    $die_on_failure = 1;
14327faafbd6SSteven Rostedt
14337faafbd6SSteven Rostedt    run_command $run_test or $failed = 1;
14345a391fbfSSteven Rostedt    exit $failed;
14355a391fbfSSteven Rostedt}
14365a391fbfSSteven Rostedt
14375a391fbfSSteven Rostedtmy $child_done;
14385a391fbfSSteven Rostedt
14395a391fbfSSteven Rostedtsub child_finished {
14405a391fbfSSteven Rostedt    $child_done = 1;
14415a391fbfSSteven Rostedt}
14425a391fbfSSteven Rostedt
14435a391fbfSSteven Rostedtsub do_run_test {
14445a391fbfSSteven Rostedt    my $child_pid;
14455a391fbfSSteven Rostedt    my $child_exit;
14465a391fbfSSteven Rostedt    my $line;
14475a391fbfSSteven Rostedt    my $full_line;
14485a391fbfSSteven Rostedt    my $bug = 0;
14495a391fbfSSteven Rostedt
14507faafbd6SSteven Rostedt    wait_for_monitor 1;
14515a391fbfSSteven Rostedt
14527faafbd6SSteven Rostedt    doprint "run test $run_test\n";
14535a391fbfSSteven Rostedt
14545a391fbfSSteven Rostedt    $child_done = 0;
14555a391fbfSSteven Rostedt
14565a391fbfSSteven Rostedt    $SIG{CHLD} = qw(child_finished);
14575a391fbfSSteven Rostedt
14585a391fbfSSteven Rostedt    $child_pid = fork;
14595a391fbfSSteven Rostedt
14605a391fbfSSteven Rostedt    child_run_test if (!$child_pid);
14615a391fbfSSteven Rostedt
14625a391fbfSSteven Rostedt    $full_line = "";
14635a391fbfSSteven Rostedt
14645a391fbfSSteven Rostedt    do {
14657faafbd6SSteven Rostedt	$line = wait_for_input($monitor_fp, 1);
14665a391fbfSSteven Rostedt	if (defined($line)) {
14675a391fbfSSteven Rostedt
14685a391fbfSSteven Rostedt	    # we are not guaranteed to get a full line
14695a391fbfSSteven Rostedt	    $full_line .= $line;
14708ea0e063SSteven Rostedt	    doprint $line;
14715a391fbfSSteven Rostedt
14725a391fbfSSteven Rostedt	    if ($full_line =~ /call trace:/i) {
14735a391fbfSSteven Rostedt		$bug = 1;
14745a391fbfSSteven Rostedt	    }
14755a391fbfSSteven Rostedt
14765a391fbfSSteven Rostedt	    if ($full_line =~ /Kernel panic -/) {
14775a391fbfSSteven Rostedt		$bug = 1;
14785a391fbfSSteven Rostedt	    }
14795a391fbfSSteven Rostedt
14805a391fbfSSteven Rostedt	    if ($line =~ /\n/) {
14815a391fbfSSteven Rostedt		$full_line = "";
14825a391fbfSSteven Rostedt	    }
14835a391fbfSSteven Rostedt	}
14845a391fbfSSteven Rostedt    } while (!$child_done && !$bug);
14855a391fbfSSteven Rostedt
14865a391fbfSSteven Rostedt    if ($bug) {
14878ea0e063SSteven Rostedt	my $failure_start = time;
14888ea0e063SSteven Rostedt	my $now;
14898ea0e063SSteven Rostedt	do {
14908ea0e063SSteven Rostedt	    $line = wait_for_input($monitor_fp, 1);
14918ea0e063SSteven Rostedt	    if (defined($line)) {
14928ea0e063SSteven Rostedt		doprint $line;
14938ea0e063SSteven Rostedt	    }
14948ea0e063SSteven Rostedt	    $now = time;
14958ea0e063SSteven Rostedt	    if ($now - $failure_start >= $stop_after_failure) {
14968ea0e063SSteven Rostedt		last;
14978ea0e063SSteven Rostedt	    }
14988ea0e063SSteven Rostedt	} while (defined($line));
14998ea0e063SSteven Rostedt
15005a391fbfSSteven Rostedt	doprint "Detected kernel crash!\n";
15015a391fbfSSteven Rostedt	# kill the child with extreme prejudice
15025a391fbfSSteven Rostedt	kill 9, $child_pid;
15035a391fbfSSteven Rostedt    }
15045a391fbfSSteven Rostedt
15055a391fbfSSteven Rostedt    waitpid $child_pid, 0;
15065a391fbfSSteven Rostedt    $child_exit = $?;
15075a391fbfSSteven Rostedt
15085a391fbfSSteven Rostedt    if ($bug || $child_exit) {
15092b7d9b21SSteven Rostedt	return 0 if $in_bisect;
15102b7d9b21SSteven Rostedt	fail "test failed" and return 0;
15115a391fbfSSteven Rostedt    }
15122b7d9b21SSteven Rostedt    return 1;
15135a391fbfSSteven Rostedt}
15145a391fbfSSteven Rostedt
1515a75fececSSteven Rostedtsub run_git_bisect {
1516a75fececSSteven Rostedt    my ($command) = @_;
1517a75fececSSteven Rostedt
1518a75fececSSteven Rostedt    doprint "$command ... ";
1519a75fececSSteven Rostedt
1520a75fececSSteven Rostedt    my $output = `$command 2>&1`;
1521a75fececSSteven Rostedt    my $ret = $?;
1522a75fececSSteven Rostedt
1523a75fececSSteven Rostedt    logit $output;
1524a75fececSSteven Rostedt
1525a75fececSSteven Rostedt    if ($ret) {
1526a75fececSSteven Rostedt	doprint "FAILED\n";
1527a75fececSSteven Rostedt	dodie "Failed to git bisect";
1528a75fececSSteven Rostedt    }
1529a75fececSSteven Rostedt
1530a75fececSSteven Rostedt    doprint "SUCCESS\n";
1531a75fececSSteven Rostedt    if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) {
1532a75fececSSteven Rostedt	doprint "$1 [$2]\n";
1533a75fececSSteven Rostedt    } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) {
1534a75fececSSteven Rostedt	$bisect_bad = $1;
1535a75fececSSteven Rostedt	doprint "Found bad commit... $1\n";
1536a75fececSSteven Rostedt	return 0;
1537a75fececSSteven Rostedt    } else {
1538a75fececSSteven Rostedt	# we already logged it, just print it now.
1539a75fececSSteven Rostedt	print $output;
1540a75fececSSteven Rostedt    }
1541a75fececSSteven Rostedt
1542a75fececSSteven Rostedt    return 1;
1543a75fececSSteven Rostedt}
1544a75fececSSteven Rostedt
1545c23dca7cSSteven Rostedtsub bisect_reboot {
1546c23dca7cSSteven Rostedt    doprint "Reboot and sleep $bisect_sleep_time seconds\n";
15472728be41SAndrew Jones    reboot $bisect_sleep_time;
1548c23dca7cSSteven Rostedt}
1549c23dca7cSSteven Rostedt
1550c23dca7cSSteven Rostedt# returns 1 on success, 0 on failure, -1 on skip
15510a05c769SSteven Rostedtsub run_bisect_test {
15520a05c769SSteven Rostedt    my ($type, $buildtype) = @_;
15535f9b6cedSSteven Rostedt
15542b7d9b21SSteven Rostedt    my $failed = 0;
15555f9b6cedSSteven Rostedt    my $result;
15565f9b6cedSSteven Rostedt    my $output;
15575f9b6cedSSteven Rostedt    my $ret;
15585f9b6cedSSteven Rostedt
15590a05c769SSteven Rostedt    $in_bisect = 1;
15600a05c769SSteven Rostedt
15610a05c769SSteven Rostedt    build $buildtype or $failed = 1;
15625f9b6cedSSteven Rostedt
15635f9b6cedSSteven Rostedt    if ($type ne "build") {
1564c23dca7cSSteven Rostedt	if ($failed && $bisect_skip) {
1565c23dca7cSSteven Rostedt	    $in_bisect = 0;
1566c23dca7cSSteven Rostedt	    return -1;
1567c23dca7cSSteven Rostedt	}
15687faafbd6SSteven Rostedt	dodie "Failed on build" if $failed;
15695f9b6cedSSteven Rostedt
15705f9b6cedSSteven Rostedt	# Now boot the box
1571ddf607e5SSteven Rostedt	start_monitor_and_boot or $failed = 1;
15725f9b6cedSSteven Rostedt
15735f9b6cedSSteven Rostedt	if ($type ne "boot") {
1574c23dca7cSSteven Rostedt	    if ($failed && $bisect_skip) {
1575c23dca7cSSteven Rostedt		end_monitor;
1576c23dca7cSSteven Rostedt		bisect_reboot;
1577c23dca7cSSteven Rostedt		$in_bisect = 0;
1578c23dca7cSSteven Rostedt		return -1;
1579c23dca7cSSteven Rostedt	    }
15807faafbd6SSteven Rostedt	    dodie "Failed on boot" if $failed;
15815a391fbfSSteven Rostedt
15822b7d9b21SSteven Rostedt	    do_run_test or $failed = 1;
15835f9b6cedSSteven Rostedt	}
15847faafbd6SSteven Rostedt	end_monitor;
15855f9b6cedSSteven Rostedt    }
15865f9b6cedSSteven Rostedt
15875f9b6cedSSteven Rostedt    if ($failed) {
15880a05c769SSteven Rostedt	$result = 0;
15895f9b6cedSSteven Rostedt    } else {
15900a05c769SSteven Rostedt	$result = 1;
15915f9b6cedSSteven Rostedt    }
15924025bc62SSteven Rostedt
15934025bc62SSteven Rostedt    # reboot the box to a kernel we can ssh to
15944025bc62SSteven Rostedt    if ($type ne "build") {
15954025bc62SSteven Rostedt	bisect_reboot;
15964025bc62SSteven Rostedt    }
15970a05c769SSteven Rostedt    $in_bisect = 0;
15980a05c769SSteven Rostedt
15990a05c769SSteven Rostedt    return $result;
16000a05c769SSteven Rostedt}
16010a05c769SSteven Rostedt
16020a05c769SSteven Rostedtsub run_bisect {
16030a05c769SSteven Rostedt    my ($type) = @_;
16040a05c769SSteven Rostedt    my $buildtype = "oldconfig";
16050a05c769SSteven Rostedt
16060a05c769SSteven Rostedt    # We should have a minconfig to use?
16070a05c769SSteven Rostedt    if (defined($minconfig)) {
16080a05c769SSteven Rostedt	$buildtype = "useconfig:$minconfig";
16090a05c769SSteven Rostedt    }
16100a05c769SSteven Rostedt
16110a05c769SSteven Rostedt    my $ret = run_bisect_test $type, $buildtype;
16120a05c769SSteven Rostedt
1613c960bb9fSSteven Rostedt    if ($bisect_manual) {
1614c960bb9fSSteven Rostedt	$ret = answer_bisect;
1615c960bb9fSSteven Rostedt    }
16165f9b6cedSSteven Rostedt
1617d6ce2a0bSSteven Rostedt    # Are we looking for where it worked, not failed?
1618d6ce2a0bSSteven Rostedt    if ($reverse_bisect) {
16190a05c769SSteven Rostedt	$ret = !$ret;
1620d6ce2a0bSSteven Rostedt    }
1621d6ce2a0bSSteven Rostedt
1622c23dca7cSSteven Rostedt    if ($ret > 0) {
16230a05c769SSteven Rostedt	return "good";
1624c23dca7cSSteven Rostedt    } elsif ($ret == 0) {
16250a05c769SSteven Rostedt	return  "bad";
1626c23dca7cSSteven Rostedt    } elsif ($bisect_skip) {
1627c23dca7cSSteven Rostedt	doprint "HIT A BAD COMMIT ... SKIPPING\n";
1628c23dca7cSSteven Rostedt	return "skip";
16290a05c769SSteven Rostedt    }
16305f9b6cedSSteven Rostedt}
16315f9b6cedSSteven Rostedt
16325f9b6cedSSteven Rostedtsub bisect {
16335f9b6cedSSteven Rostedt    my ($i) = @_;
16345f9b6cedSSteven Rostedt
16355f9b6cedSSteven Rostedt    my $result;
16365f9b6cedSSteven Rostedt
16375f9b6cedSSteven Rostedt    die "BISECT_GOOD[$i] not defined\n"	if (!defined($opt{"BISECT_GOOD[$i]"}));
16385f9b6cedSSteven Rostedt    die "BISECT_BAD[$i] not defined\n"	if (!defined($opt{"BISECT_BAD[$i]"}));
16395f9b6cedSSteven Rostedt    die "BISECT_TYPE[$i] not defined\n"	if (!defined($opt{"BISECT_TYPE[$i]"}));
16405f9b6cedSSteven Rostedt
16415f9b6cedSSteven Rostedt    my $good = $opt{"BISECT_GOOD[$i]"};
16425f9b6cedSSteven Rostedt    my $bad = $opt{"BISECT_BAD[$i]"};
16435f9b6cedSSteven Rostedt    my $type = $opt{"BISECT_TYPE[$i]"};
1644a75fececSSteven Rostedt    my $start = $opt{"BISECT_START[$i]"};
1645a75fececSSteven Rostedt    my $replay = $opt{"BISECT_REPLAY[$i]"};
16463410f6fdSSteven Rostedt    my $start_files = $opt{"BISECT_FILES[$i]"};
16473410f6fdSSteven Rostedt
16483410f6fdSSteven Rostedt    if (defined($start_files)) {
16493410f6fdSSteven Rostedt	$start_files = " -- " . $start_files;
16503410f6fdSSteven Rostedt    } else {
16513410f6fdSSteven Rostedt	$start_files = "";
16523410f6fdSSteven Rostedt    }
16535f9b6cedSSteven Rostedt
1654a57419b3SSteven Rostedt    # convert to true sha1's
1655a57419b3SSteven Rostedt    $good = get_sha1($good);
1656a57419b3SSteven Rostedt    $bad = get_sha1($bad);
1657a57419b3SSteven Rostedt
1658d6ce2a0bSSteven Rostedt    if (defined($opt{"BISECT_REVERSE[$i]"}) &&
1659d6ce2a0bSSteven Rostedt	$opt{"BISECT_REVERSE[$i]"} == 1) {
1660d6ce2a0bSSteven Rostedt	doprint "Performing a reverse bisect (bad is good, good is bad!)\n";
1661d6ce2a0bSSteven Rostedt	$reverse_bisect = 1;
1662d6ce2a0bSSteven Rostedt    } else {
1663d6ce2a0bSSteven Rostedt	$reverse_bisect = 0;
1664d6ce2a0bSSteven Rostedt    }
1665d6ce2a0bSSteven Rostedt
16665a391fbfSSteven Rostedt    # Can't have a test without having a test to run
16675a391fbfSSteven Rostedt    if ($type eq "test" && !defined($run_test)) {
16685a391fbfSSteven Rostedt	$type = "boot";
16695a391fbfSSteven Rostedt    }
16705a391fbfSSteven Rostedt
1671a75fececSSteven Rostedt    my $check = $opt{"BISECT_CHECK[$i]"};
1672a75fececSSteven Rostedt    if (defined($check) && $check ne "0") {
1673a75fececSSteven Rostedt
1674a75fececSSteven Rostedt	# get current HEAD
1675a57419b3SSteven Rostedt	my $head = get_sha1("HEAD");
1676a75fececSSteven Rostedt
1677a75fececSSteven Rostedt	if ($check ne "good") {
1678a75fececSSteven Rostedt	    doprint "TESTING BISECT BAD [$bad]\n";
1679a75fececSSteven Rostedt	    run_command "git checkout $bad" or
1680a75fececSSteven Rostedt		die "Failed to checkout $bad";
1681a75fececSSteven Rostedt
1682a75fececSSteven Rostedt	    $result = run_bisect $type;
1683a75fececSSteven Rostedt
1684a75fececSSteven Rostedt	    if ($result ne "bad") {
1685a75fececSSteven Rostedt		fail "Tested BISECT_BAD [$bad] and it succeeded" and return 0;
1686a75fececSSteven Rostedt	    }
1687a75fececSSteven Rostedt	}
1688a75fececSSteven Rostedt
1689a75fececSSteven Rostedt	if ($check ne "bad") {
1690a75fececSSteven Rostedt	    doprint "TESTING BISECT GOOD [$good]\n";
1691a75fececSSteven Rostedt	    run_command "git checkout $good" or
1692a75fececSSteven Rostedt		die "Failed to checkout $good";
1693a75fececSSteven Rostedt
1694a75fececSSteven Rostedt	    $result = run_bisect $type;
1695a75fececSSteven Rostedt
1696a75fececSSteven Rostedt	    if ($result ne "good") {
1697a75fececSSteven Rostedt		fail "Tested BISECT_GOOD [$good] and it failed" and return 0;
1698a75fececSSteven Rostedt	    }
1699a75fececSSteven Rostedt	}
1700a75fececSSteven Rostedt
1701a75fececSSteven Rostedt	# checkout where we started
1702a75fececSSteven Rostedt	run_command "git checkout $head" or
1703a75fececSSteven Rostedt	    die "Failed to checkout $head";
1704a75fececSSteven Rostedt    }
1705a75fececSSteven Rostedt
17063410f6fdSSteven Rostedt    run_command "git bisect start$start_files" or
1707a75fececSSteven Rostedt	dodie "could not start bisect";
1708a75fececSSteven Rostedt
1709a75fececSSteven Rostedt    run_command "git bisect good $good" or
1710a75fececSSteven Rostedt	dodie "could not set bisect good to $good";
1711a75fececSSteven Rostedt
1712a75fececSSteven Rostedt    run_git_bisect "git bisect bad $bad" or
1713a75fececSSteven Rostedt	dodie "could not set bisect bad to $bad";
1714a75fececSSteven Rostedt
1715a75fececSSteven Rostedt    if (defined($replay)) {
1716a75fececSSteven Rostedt	run_command "git bisect replay $replay" or
1717a75fececSSteven Rostedt	    dodie "failed to run replay";
1718a75fececSSteven Rostedt    }
1719a75fececSSteven Rostedt
1720a75fececSSteven Rostedt    if (defined($start)) {
1721a75fececSSteven Rostedt	run_command "git checkout $start" or
1722a75fececSSteven Rostedt	    dodie "failed to checkout $start";
1723a75fececSSteven Rostedt    }
1724a75fececSSteven Rostedt
1725a75fececSSteven Rostedt    my $test;
17265f9b6cedSSteven Rostedt    do {
17275f9b6cedSSteven Rostedt	$result = run_bisect $type;
1728a75fececSSteven Rostedt	$test = run_git_bisect "git bisect $result";
1729a75fececSSteven Rostedt    } while ($test);
17305f9b6cedSSteven Rostedt
17315f9b6cedSSteven Rostedt    run_command "git bisect log" or
17325f9b6cedSSteven Rostedt	dodie "could not capture git bisect log";
17335f9b6cedSSteven Rostedt
17345f9b6cedSSteven Rostedt    run_command "git bisect reset" or
17355f9b6cedSSteven Rostedt	dodie "could not reset git bisect";
17365f9b6cedSSteven Rostedt
17375f9b6cedSSteven Rostedt    doprint "Bad commit was [$bisect_bad]\n";
17385f9b6cedSSteven Rostedt
17390a05c769SSteven Rostedt    success $i;
17400a05c769SSteven Rostedt}
17410a05c769SSteven Rostedt
17420a05c769SSteven Rostedtmy %config_ignore;
17430a05c769SSteven Rostedtmy %config_set;
17440a05c769SSteven Rostedt
17450a05c769SSteven Rostedtmy %config_list;
17460a05c769SSteven Rostedtmy %null_config;
17470a05c769SSteven Rostedt
17480a05c769SSteven Rostedtmy %dependency;
17490a05c769SSteven Rostedt
17504c4ab120SSteven Rostedtsub assign_configs {
17514c4ab120SSteven Rostedt    my ($hash, $config) = @_;
17520a05c769SSteven Rostedt
17530a05c769SSteven Rostedt    open (IN, $config)
17540a05c769SSteven Rostedt	or dodie "Failed to read $config";
17550a05c769SSteven Rostedt
17560a05c769SSteven Rostedt    while (<IN>) {
17579bf71749SSteven Rostedt	if (/^((CONFIG\S*)=.*)/) {
17584c4ab120SSteven Rostedt	    ${$hash}{$2} = $1;
17590a05c769SSteven Rostedt	}
17600a05c769SSteven Rostedt    }
17610a05c769SSteven Rostedt
17620a05c769SSteven Rostedt    close(IN);
17630a05c769SSteven Rostedt}
17640a05c769SSteven Rostedt
17654c4ab120SSteven Rostedtsub process_config_ignore {
17664c4ab120SSteven Rostedt    my ($config) = @_;
17674c4ab120SSteven Rostedt
17684c4ab120SSteven Rostedt    assign_configs \%config_ignore, $config;
17694c4ab120SSteven Rostedt}
17704c4ab120SSteven Rostedt
17710a05c769SSteven Rostedtsub read_current_config {
17720a05c769SSteven Rostedt    my ($config_ref) = @_;
17730a05c769SSteven Rostedt
17740a05c769SSteven Rostedt    %{$config_ref} = ();
17750a05c769SSteven Rostedt    undef %{$config_ref};
17760a05c769SSteven Rostedt
17770a05c769SSteven Rostedt    my @key = keys %{$config_ref};
17780a05c769SSteven Rostedt    if ($#key >= 0) {
17790a05c769SSteven Rostedt	print "did not delete!\n";
17800a05c769SSteven Rostedt	exit;
17810a05c769SSteven Rostedt    }
17820a05c769SSteven Rostedt    open (IN, "$output_config");
17830a05c769SSteven Rostedt
17840a05c769SSteven Rostedt    while (<IN>) {
17850a05c769SSteven Rostedt	if (/^(CONFIG\S+)=(.*)/) {
17860a05c769SSteven Rostedt	    ${$config_ref}{$1} = $2;
17870a05c769SSteven Rostedt	}
17880a05c769SSteven Rostedt    }
17890a05c769SSteven Rostedt    close(IN);
17900a05c769SSteven Rostedt}
17910a05c769SSteven Rostedt
17920a05c769SSteven Rostedtsub get_dependencies {
17930a05c769SSteven Rostedt    my ($config) = @_;
17940a05c769SSteven Rostedt
17950a05c769SSteven Rostedt    my $arr = $dependency{$config};
17960a05c769SSteven Rostedt    if (!defined($arr)) {
17970a05c769SSteven Rostedt	return ();
17980a05c769SSteven Rostedt    }
17990a05c769SSteven Rostedt
18000a05c769SSteven Rostedt    my @deps = @{$arr};
18010a05c769SSteven Rostedt
18020a05c769SSteven Rostedt    foreach my $dep (@{$arr}) {
18030a05c769SSteven Rostedt	print "ADD DEP $dep\n";
18040a05c769SSteven Rostedt	@deps = (@deps, get_dependencies $dep);
18050a05c769SSteven Rostedt    }
18060a05c769SSteven Rostedt
18070a05c769SSteven Rostedt    return @deps;
18080a05c769SSteven Rostedt}
18090a05c769SSteven Rostedt
18100a05c769SSteven Rostedtsub create_config {
18110a05c769SSteven Rostedt    my @configs = @_;
18120a05c769SSteven Rostedt
18130a05c769SSteven Rostedt    open(OUT, ">$output_config") or dodie "Can not write to $output_config";
18140a05c769SSteven Rostedt
18150a05c769SSteven Rostedt    foreach my $config (@configs) {
18160a05c769SSteven Rostedt	print OUT "$config_set{$config}\n";
18170a05c769SSteven Rostedt	my @deps = get_dependencies $config;
18180a05c769SSteven Rostedt	foreach my $dep (@deps) {
18190a05c769SSteven Rostedt	    print OUT "$config_set{$dep}\n";
18200a05c769SSteven Rostedt	}
18210a05c769SSteven Rostedt    }
18220a05c769SSteven Rostedt
18230a05c769SSteven Rostedt    foreach my $config (keys %config_ignore) {
18240a05c769SSteven Rostedt	print OUT "$config_ignore{$config}\n";
18250a05c769SSteven Rostedt    }
18260a05c769SSteven Rostedt    close(OUT);
18270a05c769SSteven Rostedt
18280a05c769SSteven Rostedt#    exit;
1829fcb3f16aSSteven Rostedt    make_oldconfig;
18300a05c769SSteven Rostedt}
18310a05c769SSteven Rostedt
18320a05c769SSteven Rostedtsub compare_configs {
18330a05c769SSteven Rostedt    my (%a, %b) = @_;
18340a05c769SSteven Rostedt
18350a05c769SSteven Rostedt    foreach my $item (keys %a) {
18360a05c769SSteven Rostedt	if (!defined($b{$item})) {
18370a05c769SSteven Rostedt	    print "diff $item\n";
18380a05c769SSteven Rostedt	    return 1;
18390a05c769SSteven Rostedt	}
18400a05c769SSteven Rostedt	delete $b{$item};
18410a05c769SSteven Rostedt    }
18420a05c769SSteven Rostedt
18430a05c769SSteven Rostedt    my @keys = keys %b;
18440a05c769SSteven Rostedt    if ($#keys) {
18450a05c769SSteven Rostedt	print "diff2 $keys[0]\n";
18460a05c769SSteven Rostedt    }
18470a05c769SSteven Rostedt    return -1 if ($#keys >= 0);
18480a05c769SSteven Rostedt
18490a05c769SSteven Rostedt    return 0;
18500a05c769SSteven Rostedt}
18510a05c769SSteven Rostedt
18520a05c769SSteven Rostedtsub run_config_bisect_test {
18530a05c769SSteven Rostedt    my ($type) = @_;
18540a05c769SSteven Rostedt
18550a05c769SSteven Rostedt    return run_bisect_test $type, "oldconfig";
18560a05c769SSteven Rostedt}
18570a05c769SSteven Rostedt
18580a05c769SSteven Rostedtsub process_passed {
18590a05c769SSteven Rostedt    my (%configs) = @_;
18600a05c769SSteven Rostedt
18610a05c769SSteven Rostedt    doprint "These configs had no failure: (Enabling them for further compiles)\n";
18620a05c769SSteven Rostedt    # Passed! All these configs are part of a good compile.
18630a05c769SSteven Rostedt    # Add them to the min options.
18640a05c769SSteven Rostedt    foreach my $config (keys %configs) {
18650a05c769SSteven Rostedt	if (defined($config_list{$config})) {
18660a05c769SSteven Rostedt	    doprint " removing $config\n";
18670a05c769SSteven Rostedt	    $config_ignore{$config} = $config_list{$config};
18680a05c769SSteven Rostedt	    delete $config_list{$config};
18690a05c769SSteven Rostedt	}
18700a05c769SSteven Rostedt    }
1871f1a27850SSteven Rostedt    doprint "config copied to $outputdir/config_good\n";
1872f1a27850SSteven Rostedt    run_command "cp -f $output_config $outputdir/config_good";
18730a05c769SSteven Rostedt}
18740a05c769SSteven Rostedt
18750a05c769SSteven Rostedtsub process_failed {
18760a05c769SSteven Rostedt    my ($config) = @_;
18770a05c769SSteven Rostedt
18780a05c769SSteven Rostedt    doprint "\n\n***************************************\n";
18790a05c769SSteven Rostedt    doprint "Found bad config: $config\n";
18800a05c769SSteven Rostedt    doprint "***************************************\n\n";
18810a05c769SSteven Rostedt}
18820a05c769SSteven Rostedt
18830a05c769SSteven Rostedtsub run_config_bisect {
18840a05c769SSteven Rostedt
18850a05c769SSteven Rostedt    my @start_list = keys %config_list;
18860a05c769SSteven Rostedt
18870a05c769SSteven Rostedt    if ($#start_list < 0) {
18880a05c769SSteven Rostedt	doprint "No more configs to test!!!\n";
18890a05c769SSteven Rostedt	return -1;
18900a05c769SSteven Rostedt    }
18910a05c769SSteven Rostedt
18920a05c769SSteven Rostedt    doprint "***** RUN TEST ***\n";
18930a05c769SSteven Rostedt    my $type = $opt{"CONFIG_BISECT_TYPE[$iteration]"};
18940a05c769SSteven Rostedt    my $ret;
18950a05c769SSteven Rostedt    my %current_config;
18960a05c769SSteven Rostedt
18970a05c769SSteven Rostedt    my $count = $#start_list + 1;
18980a05c769SSteven Rostedt    doprint "  $count configs to test\n";
18990a05c769SSteven Rostedt
19000a05c769SSteven Rostedt    my $half = int($#start_list / 2);
19010a05c769SSteven Rostedt
19020a05c769SSteven Rostedt    do {
19030a05c769SSteven Rostedt	my @tophalf = @start_list[0 .. $half];
19040a05c769SSteven Rostedt
19050a05c769SSteven Rostedt	create_config @tophalf;
19060a05c769SSteven Rostedt	read_current_config \%current_config;
19070a05c769SSteven Rostedt
19080a05c769SSteven Rostedt	$count = $#tophalf + 1;
19090a05c769SSteven Rostedt	doprint "Testing $count configs\n";
19100a05c769SSteven Rostedt	my $found = 0;
19110a05c769SSteven Rostedt	# make sure we test something
19120a05c769SSteven Rostedt	foreach my $config (@tophalf) {
19130a05c769SSteven Rostedt	    if (defined($current_config{$config})) {
19140a05c769SSteven Rostedt		logit " $config\n";
19150a05c769SSteven Rostedt		$found = 1;
19160a05c769SSteven Rostedt	    }
19170a05c769SSteven Rostedt	}
19180a05c769SSteven Rostedt	if (!$found) {
19190a05c769SSteven Rostedt	    # try the other half
19200a05c769SSteven Rostedt	    doprint "Top half produced no set configs, trying bottom half\n";
19214c8cc55bSSteven Rostedt	    @tophalf = @start_list[$half + 1 .. $#start_list];
19220a05c769SSteven Rostedt	    create_config @tophalf;
19230a05c769SSteven Rostedt	    read_current_config \%current_config;
19240a05c769SSteven Rostedt	    foreach my $config (@tophalf) {
19250a05c769SSteven Rostedt		if (defined($current_config{$config})) {
19260a05c769SSteven Rostedt		    logit " $config\n";
19270a05c769SSteven Rostedt		    $found = 1;
19280a05c769SSteven Rostedt		}
19290a05c769SSteven Rostedt	    }
19300a05c769SSteven Rostedt	    if (!$found) {
19310a05c769SSteven Rostedt		doprint "Failed: Can't make new config with current configs\n";
19320a05c769SSteven Rostedt		foreach my $config (@start_list) {
19330a05c769SSteven Rostedt		    doprint "  CONFIG: $config\n";
19340a05c769SSteven Rostedt		}
19350a05c769SSteven Rostedt		return -1;
19360a05c769SSteven Rostedt	    }
19370a05c769SSteven Rostedt	    $count = $#tophalf + 1;
19380a05c769SSteven Rostedt	    doprint "Testing $count configs\n";
19390a05c769SSteven Rostedt	}
19400a05c769SSteven Rostedt
19410a05c769SSteven Rostedt	$ret = run_config_bisect_test $type;
1942c960bb9fSSteven Rostedt	if ($bisect_manual) {
1943c960bb9fSSteven Rostedt	    $ret = answer_bisect;
1944c960bb9fSSteven Rostedt	}
19450a05c769SSteven Rostedt	if ($ret) {
19460a05c769SSteven Rostedt	    process_passed %current_config;
19470a05c769SSteven Rostedt	    return 0;
19480a05c769SSteven Rostedt	}
19490a05c769SSteven Rostedt
19500a05c769SSteven Rostedt	doprint "This config had a failure.\n";
19510a05c769SSteven Rostedt	doprint "Removing these configs that were not set in this config:\n";
1952f1a27850SSteven Rostedt	doprint "config copied to $outputdir/config_bad\n";
1953f1a27850SSteven Rostedt	run_command "cp -f $output_config $outputdir/config_bad";
19540a05c769SSteven Rostedt
19550a05c769SSteven Rostedt	# A config exists in this group that was bad.
19560a05c769SSteven Rostedt	foreach my $config (keys %config_list) {
19570a05c769SSteven Rostedt	    if (!defined($current_config{$config})) {
19580a05c769SSteven Rostedt		doprint " removing $config\n";
19590a05c769SSteven Rostedt		delete $config_list{$config};
19600a05c769SSteven Rostedt	    }
19610a05c769SSteven Rostedt	}
19620a05c769SSteven Rostedt
19630a05c769SSteven Rostedt	@start_list = @tophalf;
19640a05c769SSteven Rostedt
19650a05c769SSteven Rostedt	if ($#start_list == 0) {
19660a05c769SSteven Rostedt	    process_failed $start_list[0];
19670a05c769SSteven Rostedt	    return 1;
19680a05c769SSteven Rostedt	}
19690a05c769SSteven Rostedt
19700a05c769SSteven Rostedt	# remove half the configs we are looking at and see if
19710a05c769SSteven Rostedt	# they are good.
19720a05c769SSteven Rostedt	$half = int($#start_list / 2);
19734c8cc55bSSteven Rostedt    } while ($#start_list > 0);
19740a05c769SSteven Rostedt
1975c960bb9fSSteven Rostedt    # we found a single config, try it again unless we are running manually
1976c960bb9fSSteven Rostedt
1977c960bb9fSSteven Rostedt    if ($bisect_manual) {
1978c960bb9fSSteven Rostedt	process_failed $start_list[0];
1979c960bb9fSSteven Rostedt	return 1;
1980c960bb9fSSteven Rostedt    }
1981c960bb9fSSteven Rostedt
19820a05c769SSteven Rostedt    my @tophalf = @start_list[0 .. 0];
19830a05c769SSteven Rostedt
19840a05c769SSteven Rostedt    $ret = run_config_bisect_test $type;
19850a05c769SSteven Rostedt    if ($ret) {
19860a05c769SSteven Rostedt	process_passed %current_config;
19870a05c769SSteven Rostedt	return 0;
19880a05c769SSteven Rostedt    }
19890a05c769SSteven Rostedt
19900a05c769SSteven Rostedt    process_failed $start_list[0];
19910a05c769SSteven Rostedt    return 1;
19920a05c769SSteven Rostedt}
19930a05c769SSteven Rostedt
19940a05c769SSteven Rostedtsub config_bisect {
19950a05c769SSteven Rostedt    my ($i) = @_;
19960a05c769SSteven Rostedt
19970a05c769SSteven Rostedt    my $start_config = $opt{"CONFIG_BISECT[$i]"};
19980a05c769SSteven Rostedt
19990a05c769SSteven Rostedt    my $tmpconfig = "$tmpdir/use_config";
20000a05c769SSteven Rostedt
200130f75da5SSteven Rostedt    if (defined($config_bisect_good)) {
200230f75da5SSteven Rostedt	process_config_ignore $config_bisect_good;
200330f75da5SSteven Rostedt    }
200430f75da5SSteven Rostedt
20050a05c769SSteven Rostedt    # Make the file with the bad config and the min config
20060a05c769SSteven Rostedt    if (defined($minconfig)) {
20070a05c769SSteven Rostedt	# read the min config for things to ignore
20080a05c769SSteven Rostedt	run_command "cp $minconfig $tmpconfig" or
20090a05c769SSteven Rostedt	    dodie "failed to copy $minconfig to $tmpconfig";
20100a05c769SSteven Rostedt    } else {
20110a05c769SSteven Rostedt	unlink $tmpconfig;
20120a05c769SSteven Rostedt    }
20130a05c769SSteven Rostedt
20140a05c769SSteven Rostedt    if (-f $tmpconfig) {
2015fcb3f16aSSteven Rostedt	load_force_config($tmpconfig);
20160a05c769SSteven Rostedt	process_config_ignore $tmpconfig;
20170a05c769SSteven Rostedt    }
20180a05c769SSteven Rostedt
20190a05c769SSteven Rostedt    # now process the start config
20200a05c769SSteven Rostedt    run_command "cp $start_config $output_config" or
20210a05c769SSteven Rostedt	dodie "failed to copy $start_config to $output_config";
20220a05c769SSteven Rostedt
20230a05c769SSteven Rostedt    # read directly what we want to check
20240a05c769SSteven Rostedt    my %config_check;
20250a05c769SSteven Rostedt    open (IN, $output_config)
20260a05c769SSteven Rostedt	or dodie "faied to open $output_config";
20270a05c769SSteven Rostedt
20280a05c769SSteven Rostedt    while (<IN>) {
20290a05c769SSteven Rostedt	if (/^((CONFIG\S*)=.*)/) {
20300a05c769SSteven Rostedt	    $config_check{$2} = $1;
20310a05c769SSteven Rostedt	}
20320a05c769SSteven Rostedt    }
20330a05c769SSteven Rostedt    close(IN);
20340a05c769SSteven Rostedt
2035250bae8bSSteven Rostedt    # Now run oldconfig with the minconfig
2036fcb3f16aSSteven Rostedt    make_oldconfig;
20370a05c769SSteven Rostedt
20380a05c769SSteven Rostedt    # check to see what we lost (or gained)
20390a05c769SSteven Rostedt    open (IN, $output_config)
20400a05c769SSteven Rostedt	or dodie "Failed to read $start_config";
20410a05c769SSteven Rostedt
20420a05c769SSteven Rostedt    my %removed_configs;
20430a05c769SSteven Rostedt    my %added_configs;
20440a05c769SSteven Rostedt
20450a05c769SSteven Rostedt    while (<IN>) {
20460a05c769SSteven Rostedt	if (/^((CONFIG\S*)=.*)/) {
20470a05c769SSteven Rostedt	    # save off all options
20480a05c769SSteven Rostedt	    $config_set{$2} = $1;
20490a05c769SSteven Rostedt	    if (defined($config_check{$2})) {
20500a05c769SSteven Rostedt		if (defined($config_ignore{$2})) {
20510a05c769SSteven Rostedt		    $removed_configs{$2} = $1;
20520a05c769SSteven Rostedt		} else {
20530a05c769SSteven Rostedt		    $config_list{$2} = $1;
20540a05c769SSteven Rostedt		}
20550a05c769SSteven Rostedt	    } elsif (!defined($config_ignore{$2})) {
20560a05c769SSteven Rostedt		$added_configs{$2} = $1;
20570a05c769SSteven Rostedt		$config_list{$2} = $1;
20580a05c769SSteven Rostedt	    }
20590a05c769SSteven Rostedt	}
20600a05c769SSteven Rostedt    }
20610a05c769SSteven Rostedt    close(IN);
20620a05c769SSteven Rostedt
20630a05c769SSteven Rostedt    my @confs = keys %removed_configs;
20640a05c769SSteven Rostedt    if ($#confs >= 0) {
20650a05c769SSteven Rostedt	doprint "Configs overridden by default configs and removed from check:\n";
20660a05c769SSteven Rostedt	foreach my $config (@confs) {
20670a05c769SSteven Rostedt	    doprint " $config\n";
20680a05c769SSteven Rostedt	}
20690a05c769SSteven Rostedt    }
20700a05c769SSteven Rostedt    @confs = keys %added_configs;
20710a05c769SSteven Rostedt    if ($#confs >= 0) {
20720a05c769SSteven Rostedt	doprint "Configs appearing in make oldconfig and added:\n";
20730a05c769SSteven Rostedt	foreach my $config (@confs) {
20740a05c769SSteven Rostedt	    doprint " $config\n";
20750a05c769SSteven Rostedt	}
20760a05c769SSteven Rostedt    }
20770a05c769SSteven Rostedt
20780a05c769SSteven Rostedt    my %config_test;
20790a05c769SSteven Rostedt    my $once = 0;
20800a05c769SSteven Rostedt
20810a05c769SSteven Rostedt    # Sometimes kconfig does weird things. We must make sure
20820a05c769SSteven Rostedt    # that the config we autocreate has everything we need
20830a05c769SSteven Rostedt    # to test, otherwise we may miss testing configs, or
20840a05c769SSteven Rostedt    # may not be able to create a new config.
20850a05c769SSteven Rostedt    # Here we create a config with everything set.
20860a05c769SSteven Rostedt    create_config (keys %config_list);
20870a05c769SSteven Rostedt    read_current_config \%config_test;
20880a05c769SSteven Rostedt    foreach my $config (keys %config_list) {
20890a05c769SSteven Rostedt	if (!defined($config_test{$config})) {
20900a05c769SSteven Rostedt	    if (!$once) {
20910a05c769SSteven Rostedt		$once = 1;
20920a05c769SSteven Rostedt		doprint "Configs not produced by kconfig (will not be checked):\n";
20930a05c769SSteven Rostedt	    }
20940a05c769SSteven Rostedt	    doprint "  $config\n";
20950a05c769SSteven Rostedt	    delete $config_list{$config};
20960a05c769SSteven Rostedt	}
20970a05c769SSteven Rostedt    }
20980a05c769SSteven Rostedt    my $ret;
20990a05c769SSteven Rostedt    do {
21000a05c769SSteven Rostedt	$ret = run_config_bisect;
21010a05c769SSteven Rostedt    } while (!$ret);
21020a05c769SSteven Rostedt
21030a05c769SSteven Rostedt    return $ret if ($ret < 0);
21045f9b6cedSSteven Rostedt
21055f9b6cedSSteven Rostedt    success $i;
21065f9b6cedSSteven Rostedt}
21075f9b6cedSSteven Rostedt
210827d934b2SSteven Rostedtsub patchcheck_reboot {
210927d934b2SSteven Rostedt    doprint "Reboot and sleep $patchcheck_sleep_time seconds\n";
21102728be41SAndrew Jones    reboot $patchcheck_sleep_time;
211127d934b2SSteven Rostedt}
211227d934b2SSteven Rostedt
21136c5ee0beSSteven Rostedtsub patchcheck {
21146c5ee0beSSteven Rostedt    my ($i) = @_;
21156c5ee0beSSteven Rostedt
21166c5ee0beSSteven Rostedt    die "PATCHCHECK_START[$i] not defined\n"
21176c5ee0beSSteven Rostedt	if (!defined($opt{"PATCHCHECK_START[$i]"}));
21186c5ee0beSSteven Rostedt    die "PATCHCHECK_TYPE[$i] not defined\n"
21196c5ee0beSSteven Rostedt	if (!defined($opt{"PATCHCHECK_TYPE[$i]"}));
21206c5ee0beSSteven Rostedt
21216c5ee0beSSteven Rostedt    my $start = $opt{"PATCHCHECK_START[$i]"};
21226c5ee0beSSteven Rostedt
21236c5ee0beSSteven Rostedt    my $end = "HEAD";
21246c5ee0beSSteven Rostedt    if (defined($opt{"PATCHCHECK_END[$i]"})) {
21256c5ee0beSSteven Rostedt	$end = $opt{"PATCHCHECK_END[$i]"};
21266c5ee0beSSteven Rostedt    }
21276c5ee0beSSteven Rostedt
2128a57419b3SSteven Rostedt    # Get the true sha1's since we can use things like HEAD~3
2129a57419b3SSteven Rostedt    $start = get_sha1($start);
2130a57419b3SSteven Rostedt    $end = get_sha1($end);
2131a57419b3SSteven Rostedt
21326c5ee0beSSteven Rostedt    my $type = $opt{"PATCHCHECK_TYPE[$i]"};
21336c5ee0beSSteven Rostedt
21346c5ee0beSSteven Rostedt    # Can't have a test without having a test to run
21356c5ee0beSSteven Rostedt    if ($type eq "test" && !defined($run_test)) {
21366c5ee0beSSteven Rostedt	$type = "boot";
21376c5ee0beSSteven Rostedt    }
21386c5ee0beSSteven Rostedt
21396c5ee0beSSteven Rostedt    open (IN, "git log --pretty=oneline $end|") or
21406c5ee0beSSteven Rostedt	dodie "could not get git list";
21416c5ee0beSSteven Rostedt
21426c5ee0beSSteven Rostedt    my @list;
21436c5ee0beSSteven Rostedt
21446c5ee0beSSteven Rostedt    while (<IN>) {
21456c5ee0beSSteven Rostedt	chomp;
21466c5ee0beSSteven Rostedt	$list[$#list+1] = $_;
21476c5ee0beSSteven Rostedt	last if (/^$start/);
21486c5ee0beSSteven Rostedt    }
21496c5ee0beSSteven Rostedt    close(IN);
21506c5ee0beSSteven Rostedt
21516c5ee0beSSteven Rostedt    if ($list[$#list] !~ /^$start/) {
21522b7d9b21SSteven Rostedt	fail "SHA1 $start not found";
21536c5ee0beSSteven Rostedt    }
21546c5ee0beSSteven Rostedt
21556c5ee0beSSteven Rostedt    # go backwards in the list
21566c5ee0beSSteven Rostedt    @list = reverse @list;
21576c5ee0beSSteven Rostedt
21586c5ee0beSSteven Rostedt    my $save_clean = $noclean;
21591990207dSSteven Rostedt    my %ignored_warnings;
21601990207dSSteven Rostedt
21611990207dSSteven Rostedt    if (defined($ignore_warnings)) {
21621990207dSSteven Rostedt	foreach my $sha1 (split /\s+/, $ignore_warnings) {
21631990207dSSteven Rostedt	    $ignored_warnings{$sha1} = 1;
21641990207dSSteven Rostedt	}
21651990207dSSteven Rostedt    }
21666c5ee0beSSteven Rostedt
21676c5ee0beSSteven Rostedt    $in_patchcheck = 1;
21686c5ee0beSSteven Rostedt    foreach my $item (@list) {
21696c5ee0beSSteven Rostedt	my $sha1 = $item;
21706c5ee0beSSteven Rostedt	$sha1 =~ s/^([[:xdigit:]]+).*/$1/;
21716c5ee0beSSteven Rostedt
21726c5ee0beSSteven Rostedt	doprint "\nProcessing commit $item\n\n";
21736c5ee0beSSteven Rostedt
21746c5ee0beSSteven Rostedt	run_command "git checkout $sha1" or
21756c5ee0beSSteven Rostedt	    die "Failed to checkout $sha1";
21766c5ee0beSSteven Rostedt
21776c5ee0beSSteven Rostedt	# only clean on the first and last patch
21786c5ee0beSSteven Rostedt	if ($item eq $list[0] ||
21796c5ee0beSSteven Rostedt	    $item eq $list[$#list]) {
21806c5ee0beSSteven Rostedt	    $noclean = $save_clean;
21816c5ee0beSSteven Rostedt	} else {
21826c5ee0beSSteven Rostedt	    $noclean = 1;
21836c5ee0beSSteven Rostedt	}
21846c5ee0beSSteven Rostedt
21856c5ee0beSSteven Rostedt	if (defined($minconfig)) {
21862b7d9b21SSteven Rostedt	    build "useconfig:$minconfig" or return 0;
21876c5ee0beSSteven Rostedt	} else {
21886c5ee0beSSteven Rostedt	    # ?? no config to use?
21892b7d9b21SSteven Rostedt	    build "oldconfig" or return 0;
21906c5ee0beSSteven Rostedt	}
21916c5ee0beSSteven Rostedt
21921990207dSSteven Rostedt
21931990207dSSteven Rostedt	if (!defined($ignored_warnings{$sha1})) {
21942b7d9b21SSteven Rostedt	    check_buildlog $sha1 or return 0;
21951990207dSSteven Rostedt	}
21966c5ee0beSSteven Rostedt
21976c5ee0beSSteven Rostedt	next if ($type eq "build");
21986c5ee0beSSteven Rostedt
21997faafbd6SSteven Rostedt	my $failed = 0;
22007faafbd6SSteven Rostedt
2201ddf607e5SSteven Rostedt	start_monitor_and_boot or $failed = 1;
22027faafbd6SSteven Rostedt
22037faafbd6SSteven Rostedt	if (!$failed && $type ne "boot"){
22047faafbd6SSteven Rostedt	    do_run_test or $failed = 1;
22057faafbd6SSteven Rostedt	}
22067faafbd6SSteven Rostedt	end_monitor;
22077faafbd6SSteven Rostedt	return 0 if ($failed);
22087faafbd6SSteven Rostedt
220927d934b2SSteven Rostedt	patchcheck_reboot;
221027d934b2SSteven Rostedt
22116c5ee0beSSteven Rostedt    }
22126c5ee0beSSteven Rostedt    $in_patchcheck = 0;
22136c5ee0beSSteven Rostedt    success $i;
22142b7d9b21SSteven Rostedt
22152b7d9b21SSteven Rostedt    return 1;
22166c5ee0beSSteven Rostedt}
22176c5ee0beSSteven Rostedt
2218b9066f6cSSteven Rostedtmy %depends;
2219b9066f6cSSteven Rostedtmy $iflevel = 0;
2220b9066f6cSSteven Rostedtmy @ifdeps;
2221b9066f6cSSteven Rostedt
2222b9066f6cSSteven Rostedt# prevent recursion
2223b9066f6cSSteven Rostedtmy %read_kconfigs;
2224b9066f6cSSteven Rostedt
2225b9066f6cSSteven Rostedt# taken from streamline_config.pl
2226b9066f6cSSteven Rostedtsub read_kconfig {
2227b9066f6cSSteven Rostedt    my ($kconfig) = @_;
2228b9066f6cSSteven Rostedt
2229b9066f6cSSteven Rostedt    my $state = "NONE";
2230b9066f6cSSteven Rostedt    my $config;
2231b9066f6cSSteven Rostedt    my @kconfigs;
2232b9066f6cSSteven Rostedt
2233b9066f6cSSteven Rostedt    my $cont = 0;
2234b9066f6cSSteven Rostedt    my $line;
2235b9066f6cSSteven Rostedt
2236b9066f6cSSteven Rostedt
2237b9066f6cSSteven Rostedt    if (! -f $kconfig) {
2238b9066f6cSSteven Rostedt	doprint "file $kconfig does not exist, skipping\n";
2239b9066f6cSSteven Rostedt	return;
2240b9066f6cSSteven Rostedt    }
2241b9066f6cSSteven Rostedt
2242b9066f6cSSteven Rostedt    open(KIN, "$kconfig")
2243b9066f6cSSteven Rostedt	or die "Can't open $kconfig";
2244b9066f6cSSteven Rostedt    while (<KIN>) {
2245b9066f6cSSteven Rostedt	chomp;
2246b9066f6cSSteven Rostedt
2247b9066f6cSSteven Rostedt	# Make sure that lines ending with \ continue
2248b9066f6cSSteven Rostedt	if ($cont) {
2249b9066f6cSSteven Rostedt	    $_ = $line . " " . $_;
2250b9066f6cSSteven Rostedt	}
2251b9066f6cSSteven Rostedt
2252b9066f6cSSteven Rostedt	if (s/\\$//) {
2253b9066f6cSSteven Rostedt	    $cont = 1;
2254b9066f6cSSteven Rostedt	    $line = $_;
2255b9066f6cSSteven Rostedt	    next;
2256b9066f6cSSteven Rostedt	}
2257b9066f6cSSteven Rostedt
2258b9066f6cSSteven Rostedt	$cont = 0;
2259b9066f6cSSteven Rostedt
2260b9066f6cSSteven Rostedt	# collect any Kconfig sources
2261b9066f6cSSteven Rostedt	if (/^source\s*"(.*)"/) {
2262b9066f6cSSteven Rostedt	    $kconfigs[$#kconfigs+1] = $1;
2263b9066f6cSSteven Rostedt	}
2264b9066f6cSSteven Rostedt
2265b9066f6cSSteven Rostedt	# configs found
2266b9066f6cSSteven Rostedt	if (/^\s*(menu)?config\s+(\S+)\s*$/) {
2267b9066f6cSSteven Rostedt	    $state = "NEW";
2268b9066f6cSSteven Rostedt	    $config = $2;
2269b9066f6cSSteven Rostedt
2270b9066f6cSSteven Rostedt	    for (my $i = 0; $i < $iflevel; $i++) {
2271b9066f6cSSteven Rostedt		if ($i) {
2272b9066f6cSSteven Rostedt		    $depends{$config} .= " " . $ifdeps[$i];
2273b9066f6cSSteven Rostedt		} else {
2274b9066f6cSSteven Rostedt		    $depends{$config} = $ifdeps[$i];
2275b9066f6cSSteven Rostedt		}
2276b9066f6cSSteven Rostedt		$state = "DEP";
2277b9066f6cSSteven Rostedt	    }
2278b9066f6cSSteven Rostedt
2279b9066f6cSSteven Rostedt	# collect the depends for the config
2280b9066f6cSSteven Rostedt	} elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) {
2281b9066f6cSSteven Rostedt
2282b9066f6cSSteven Rostedt	    if (defined($depends{$1})) {
2283b9066f6cSSteven Rostedt		$depends{$config} .= " " . $1;
2284b9066f6cSSteven Rostedt	    } else {
2285b9066f6cSSteven Rostedt		$depends{$config} = $1;
2286b9066f6cSSteven Rostedt	    }
2287b9066f6cSSteven Rostedt
2288b9066f6cSSteven Rostedt	# Get the configs that select this config
2289b9066f6cSSteven Rostedt	} elsif ($state ne "NONE" && /^\s*select\s+(\S+)/) {
2290b9066f6cSSteven Rostedt	    if (defined($depends{$1})) {
2291b9066f6cSSteven Rostedt		$depends{$1} .= " " . $config;
2292b9066f6cSSteven Rostedt	    } else {
2293b9066f6cSSteven Rostedt		$depends{$1} = $config;
2294b9066f6cSSteven Rostedt	    }
2295b9066f6cSSteven Rostedt
2296b9066f6cSSteven Rostedt	# Check for if statements
2297b9066f6cSSteven Rostedt	} elsif (/^if\s+(.*\S)\s*$/) {
2298b9066f6cSSteven Rostedt	    my $deps = $1;
2299b9066f6cSSteven Rostedt	    # remove beginning and ending non text
2300b9066f6cSSteven Rostedt	    $deps =~ s/^[^a-zA-Z0-9_]*//;
2301b9066f6cSSteven Rostedt	    $deps =~ s/[^a-zA-Z0-9_]*$//;
2302b9066f6cSSteven Rostedt
2303b9066f6cSSteven Rostedt	    my @deps = split /[^a-zA-Z0-9_]+/, $deps;
2304b9066f6cSSteven Rostedt
2305b9066f6cSSteven Rostedt	    $ifdeps[$iflevel++] = join ':', @deps;
2306b9066f6cSSteven Rostedt
2307b9066f6cSSteven Rostedt	} elsif (/^endif/) {
2308b9066f6cSSteven Rostedt
2309b9066f6cSSteven Rostedt	    $iflevel-- if ($iflevel);
2310b9066f6cSSteven Rostedt
2311b9066f6cSSteven Rostedt	# stop on "help"
2312b9066f6cSSteven Rostedt	} elsif (/^\s*help\s*$/) {
2313b9066f6cSSteven Rostedt	    $state = "NONE";
2314b9066f6cSSteven Rostedt	}
2315b9066f6cSSteven Rostedt    }
2316b9066f6cSSteven Rostedt    close(KIN);
2317b9066f6cSSteven Rostedt
2318b9066f6cSSteven Rostedt    # read in any configs that were found.
2319b9066f6cSSteven Rostedt    foreach $kconfig (@kconfigs) {
2320b9066f6cSSteven Rostedt	if (!defined($read_kconfigs{$kconfig})) {
2321b9066f6cSSteven Rostedt	    $read_kconfigs{$kconfig} = 1;
2322b9066f6cSSteven Rostedt	    read_kconfig("$builddir/$kconfig");
2323b9066f6cSSteven Rostedt	}
2324b9066f6cSSteven Rostedt    }
2325b9066f6cSSteven Rostedt}
2326b9066f6cSSteven Rostedt
2327b9066f6cSSteven Rostedtsub read_depends {
2328b9066f6cSSteven Rostedt    # find out which arch this is by the kconfig file
2329b9066f6cSSteven Rostedt    open (IN, $output_config)
2330b9066f6cSSteven Rostedt	or dodie "Failed to read $output_config";
2331b9066f6cSSteven Rostedt    my $arch;
2332b9066f6cSSteven Rostedt    while (<IN>) {
2333b9066f6cSSteven Rostedt	if (m,Linux/(\S+)\s+\S+\s+Kernel Configuration,) {
2334b9066f6cSSteven Rostedt	    $arch = $1;
2335b9066f6cSSteven Rostedt	    last;
2336b9066f6cSSteven Rostedt	}
2337b9066f6cSSteven Rostedt    }
2338b9066f6cSSteven Rostedt    close IN;
2339b9066f6cSSteven Rostedt
2340b9066f6cSSteven Rostedt    if (!defined($arch)) {
2341b9066f6cSSteven Rostedt	doprint "Could not find arch from config file\n";
2342b9066f6cSSteven Rostedt	doprint "no dependencies used\n";
2343b9066f6cSSteven Rostedt	return;
2344b9066f6cSSteven Rostedt    }
2345b9066f6cSSteven Rostedt
2346b9066f6cSSteven Rostedt    # arch is really the subarch, we need to know
2347b9066f6cSSteven Rostedt    # what directory to look at.
2348b9066f6cSSteven Rostedt    if ($arch eq "i386" || $arch eq "x86_64") {
2349b9066f6cSSteven Rostedt	$arch = "x86";
2350b9066f6cSSteven Rostedt    } elsif ($arch =~ /^tile/) {
2351b9066f6cSSteven Rostedt	$arch = "tile";
2352b9066f6cSSteven Rostedt    }
2353b9066f6cSSteven Rostedt
2354b9066f6cSSteven Rostedt    my $kconfig = "$builddir/arch/$arch/Kconfig";
2355b9066f6cSSteven Rostedt
2356b9066f6cSSteven Rostedt    if (! -f $kconfig && $arch =~ /\d$/) {
2357b9066f6cSSteven Rostedt	my $orig = $arch;
2358b9066f6cSSteven Rostedt 	# some subarchs have numbers, truncate them
2359b9066f6cSSteven Rostedt	$arch =~ s/\d*$//;
2360b9066f6cSSteven Rostedt	$kconfig = "$builddir/arch/$arch/Kconfig";
2361b9066f6cSSteven Rostedt	if (! -f $kconfig) {
2362b9066f6cSSteven Rostedt	    doprint "No idea what arch dir $orig is for\n";
2363b9066f6cSSteven Rostedt	    doprint "no dependencies used\n";
2364b9066f6cSSteven Rostedt	    return;
2365b9066f6cSSteven Rostedt	}
2366b9066f6cSSteven Rostedt    }
2367b9066f6cSSteven Rostedt
2368b9066f6cSSteven Rostedt    read_kconfig($kconfig);
2369b9066f6cSSteven Rostedt}
2370b9066f6cSSteven Rostedt
23714c4ab120SSteven Rostedtsub read_config_list {
23724c4ab120SSteven Rostedt    my ($config) = @_;
23734c4ab120SSteven Rostedt
23744c4ab120SSteven Rostedt    open (IN, $config)
23754c4ab120SSteven Rostedt	or dodie "Failed to read $config";
23764c4ab120SSteven Rostedt
23774c4ab120SSteven Rostedt    while (<IN>) {
23784c4ab120SSteven Rostedt	if (/^((CONFIG\S*)=.*)/) {
23794c4ab120SSteven Rostedt	    if (!defined($config_ignore{$2})) {
23804c4ab120SSteven Rostedt		$config_list{$2} = $1;
23814c4ab120SSteven Rostedt	    }
23824c4ab120SSteven Rostedt	}
23834c4ab120SSteven Rostedt    }
23844c4ab120SSteven Rostedt
23854c4ab120SSteven Rostedt    close(IN);
23864c4ab120SSteven Rostedt}
23874c4ab120SSteven Rostedt
23884c4ab120SSteven Rostedtsub read_output_config {
23894c4ab120SSteven Rostedt    my ($config) = @_;
23904c4ab120SSteven Rostedt
23914c4ab120SSteven Rostedt    assign_configs \%config_ignore, $config;
23924c4ab120SSteven Rostedt}
23934c4ab120SSteven Rostedt
23944c4ab120SSteven Rostedtsub make_new_config {
23954c4ab120SSteven Rostedt    my @configs = @_;
23964c4ab120SSteven Rostedt
23974c4ab120SSteven Rostedt    open (OUT, ">$output_config")
23984c4ab120SSteven Rostedt	or dodie "Failed to write $output_config";
23994c4ab120SSteven Rostedt
24004c4ab120SSteven Rostedt    foreach my $config (@configs) {
24014c4ab120SSteven Rostedt	print OUT "$config\n";
24024c4ab120SSteven Rostedt    }
24034c4ab120SSteven Rostedt    close OUT;
24044c4ab120SSteven Rostedt}
24054c4ab120SSteven Rostedt
2406b9066f6cSSteven Rostedtsub get_depends {
2407b9066f6cSSteven Rostedt    my ($dep) = @_;
2408b9066f6cSSteven Rostedt
2409b9066f6cSSteven Rostedt    my $kconfig = $dep;
2410b9066f6cSSteven Rostedt    $kconfig =~ s/CONFIG_//;
2411b9066f6cSSteven Rostedt
2412b9066f6cSSteven Rostedt    $dep = $depends{"$kconfig"};
2413b9066f6cSSteven Rostedt
2414b9066f6cSSteven Rostedt    # the dep string we have saves the dependencies as they
2415b9066f6cSSteven Rostedt    # were found, including expressions like ! && ||. We
2416b9066f6cSSteven Rostedt    # want to split this out into just an array of configs.
2417b9066f6cSSteven Rostedt
2418b9066f6cSSteven Rostedt    my $valid = "A-Za-z_0-9";
2419b9066f6cSSteven Rostedt
2420b9066f6cSSteven Rostedt    my @configs;
2421b9066f6cSSteven Rostedt
2422b9066f6cSSteven Rostedt    while ($dep =~ /[$valid]/) {
2423b9066f6cSSteven Rostedt
2424b9066f6cSSteven Rostedt	if ($dep =~ /^[^$valid]*([$valid]+)/) {
2425b9066f6cSSteven Rostedt	    my $conf = "CONFIG_" . $1;
2426b9066f6cSSteven Rostedt
2427b9066f6cSSteven Rostedt	    $configs[$#configs + 1] = $conf;
2428b9066f6cSSteven Rostedt
2429b9066f6cSSteven Rostedt	    $dep =~ s/^[^$valid]*[$valid]+//;
2430b9066f6cSSteven Rostedt	} else {
2431b9066f6cSSteven Rostedt	    die "this should never happen";
2432b9066f6cSSteven Rostedt	}
2433b9066f6cSSteven Rostedt    }
2434b9066f6cSSteven Rostedt
2435b9066f6cSSteven Rostedt    return @configs;
2436b9066f6cSSteven Rostedt}
2437b9066f6cSSteven Rostedt
2438b9066f6cSSteven Rostedtmy %min_configs;
2439b9066f6cSSteven Rostedtmy %keep_configs;
244043d1b651SSteven Rostedtmy %save_configs;
2441b9066f6cSSteven Rostedtmy %processed_configs;
2442b9066f6cSSteven Rostedtmy %nochange_config;
2443b9066f6cSSteven Rostedt
2444b9066f6cSSteven Rostedtsub test_this_config {
2445b9066f6cSSteven Rostedt    my ($config) = @_;
2446b9066f6cSSteven Rostedt
2447b9066f6cSSteven Rostedt    my $found;
2448b9066f6cSSteven Rostedt
2449b9066f6cSSteven Rostedt    # if we already processed this config, skip it
2450b9066f6cSSteven Rostedt    if (defined($processed_configs{$config})) {
2451b9066f6cSSteven Rostedt	return undef;
2452b9066f6cSSteven Rostedt    }
2453b9066f6cSSteven Rostedt    $processed_configs{$config} = 1;
2454b9066f6cSSteven Rostedt
2455b9066f6cSSteven Rostedt    # if this config failed during this round, skip it
2456b9066f6cSSteven Rostedt    if (defined($nochange_config{$config})) {
2457b9066f6cSSteven Rostedt	return undef;
2458b9066f6cSSteven Rostedt    }
2459b9066f6cSSteven Rostedt
2460b9066f6cSSteven Rostedt    my $kconfig = $config;
2461b9066f6cSSteven Rostedt    $kconfig =~ s/CONFIG_//;
2462b9066f6cSSteven Rostedt
2463b9066f6cSSteven Rostedt    # Test dependencies first
2464b9066f6cSSteven Rostedt    if (defined($depends{"$kconfig"})) {
2465b9066f6cSSteven Rostedt	my @parents = get_depends $config;
2466b9066f6cSSteven Rostedt	foreach my $parent (@parents) {
2467b9066f6cSSteven Rostedt	    # if the parent is in the min config, check it first
2468b9066f6cSSteven Rostedt	    next if (!defined($min_configs{$parent}));
2469b9066f6cSSteven Rostedt	    $found = test_this_config($parent);
2470b9066f6cSSteven Rostedt	    if (defined($found)) {
2471b9066f6cSSteven Rostedt		return $found;
2472b9066f6cSSteven Rostedt	    }
2473b9066f6cSSteven Rostedt	}
2474b9066f6cSSteven Rostedt    }
2475b9066f6cSSteven Rostedt
2476b9066f6cSSteven Rostedt    # Remove this config from the list of configs
2477b9066f6cSSteven Rostedt    # do a make oldnoconfig and then read the resulting
2478b9066f6cSSteven Rostedt    # .config to make sure it is missing the config that
2479b9066f6cSSteven Rostedt    # we had before
2480b9066f6cSSteven Rostedt    my %configs = %min_configs;
2481b9066f6cSSteven Rostedt    delete $configs{$config};
2482b9066f6cSSteven Rostedt    make_new_config ((values %configs), (values %keep_configs));
2483b9066f6cSSteven Rostedt    make_oldconfig;
2484b9066f6cSSteven Rostedt    undef %configs;
2485b9066f6cSSteven Rostedt    assign_configs \%configs, $output_config;
2486b9066f6cSSteven Rostedt
2487b9066f6cSSteven Rostedt    return $config if (!defined($configs{$config}));
2488b9066f6cSSteven Rostedt
2489b9066f6cSSteven Rostedt    doprint "disabling config $config did not change .config\n";
2490b9066f6cSSteven Rostedt
2491b9066f6cSSteven Rostedt    $nochange_config{$config} = 1;
2492b9066f6cSSteven Rostedt
2493b9066f6cSSteven Rostedt    return undef;
2494b9066f6cSSteven Rostedt}
2495b9066f6cSSteven Rostedt
24964c4ab120SSteven Rostedtsub make_min_config {
24974c4ab120SSteven Rostedt    my ($i) = @_;
24984c4ab120SSteven Rostedt
24994c4ab120SSteven Rostedt    if (!defined($output_minconfig)) {
25004c4ab120SSteven Rostedt	fail "OUTPUT_MIN_CONFIG not defined" and return;
25014c4ab120SSteven Rostedt    }
250235ce5952SSteven Rostedt
250335ce5952SSteven Rostedt    # If output_minconfig exists, and the start_minconfig
250435ce5952SSteven Rostedt    # came from min_config, than ask if we should use
250535ce5952SSteven Rostedt    # that instead.
250635ce5952SSteven Rostedt    if (-f $output_minconfig && !$start_minconfig_defined) {
250735ce5952SSteven Rostedt	print "$output_minconfig exists\n";
250835ce5952SSteven Rostedt	if (read_yn " Use it as minconfig?") {
250935ce5952SSteven Rostedt	    $start_minconfig = $output_minconfig;
251035ce5952SSteven Rostedt	}
251135ce5952SSteven Rostedt    }
251235ce5952SSteven Rostedt
25134c4ab120SSteven Rostedt    if (!defined($start_minconfig)) {
25144c4ab120SSteven Rostedt	fail "START_MIN_CONFIG or MIN_CONFIG not defined" and return;
25154c4ab120SSteven Rostedt    }
25164c4ab120SSteven Rostedt
251735ce5952SSteven Rostedt    my $temp_config = "$tmpdir/temp_config";
251835ce5952SSteven Rostedt
25194c4ab120SSteven Rostedt    # First things first. We build an allnoconfig to find
25204c4ab120SSteven Rostedt    # out what the defaults are that we can't touch.
25214c4ab120SSteven Rostedt    # Some are selections, but we really can't handle selections.
25224c4ab120SSteven Rostedt
25234c4ab120SSteven Rostedt    my $save_minconfig = $minconfig;
25244c4ab120SSteven Rostedt    undef $minconfig;
25254c4ab120SSteven Rostedt
25264c4ab120SSteven Rostedt    run_command "$make allnoconfig" or return 0;
25274c4ab120SSteven Rostedt
2528b9066f6cSSteven Rostedt    read_depends;
2529b9066f6cSSteven Rostedt
25304c4ab120SSteven Rostedt    process_config_ignore $output_config;
2531b9066f6cSSteven Rostedt
253243d1b651SSteven Rostedt    undef %save_configs;
2533b9066f6cSSteven Rostedt    undef %min_configs;
25344c4ab120SSteven Rostedt
25354c4ab120SSteven Rostedt    if (defined($ignore_config)) {
25364c4ab120SSteven Rostedt	# make sure the file exists
25374c4ab120SSteven Rostedt	`touch $ignore_config`;
253843d1b651SSteven Rostedt	assign_configs \%save_configs, $ignore_config;
25394c4ab120SSteven Rostedt    }
25404c4ab120SSteven Rostedt
254143d1b651SSteven Rostedt    %keep_configs = %save_configs;
254243d1b651SSteven Rostedt
25434c4ab120SSteven Rostedt    doprint "Load initial configs from $start_minconfig\n";
25444c4ab120SSteven Rostedt
25454c4ab120SSteven Rostedt    # Look at the current min configs, and save off all the
25464c4ab120SSteven Rostedt    # ones that were set via the allnoconfig
25474c4ab120SSteven Rostedt    assign_configs \%min_configs, $start_minconfig;
25484c4ab120SSteven Rostedt
25494c4ab120SSteven Rostedt    my @config_keys = keys %min_configs;
25504c4ab120SSteven Rostedt
25514c4ab120SSteven Rostedt    # Remove anything that was set by the make allnoconfig
25524c4ab120SSteven Rostedt    # we shouldn't need them as they get set for us anyway.
25534c4ab120SSteven Rostedt    foreach my $config (@config_keys) {
25544c4ab120SSteven Rostedt	# Remove anything in the ignore_config
25554c4ab120SSteven Rostedt	if (defined($keep_configs{$config})) {
25564c4ab120SSteven Rostedt	    my $file = $ignore_config;
25574c4ab120SSteven Rostedt	    $file =~ s,.*/(.*?)$,$1,;
25584c4ab120SSteven Rostedt	    doprint "$config set by $file ... ignored\n";
25594c4ab120SSteven Rostedt	    delete $min_configs{$config};
25604c4ab120SSteven Rostedt	    next;
25614c4ab120SSteven Rostedt	}
25624c4ab120SSteven Rostedt	# But make sure the settings are the same. If a min config
25634c4ab120SSteven Rostedt	# sets a selection, we do not want to get rid of it if
25644c4ab120SSteven Rostedt	# it is not the same as what we have. Just move it into
25654c4ab120SSteven Rostedt	# the keep configs.
25664c4ab120SSteven Rostedt	if (defined($config_ignore{$config})) {
25674c4ab120SSteven Rostedt	    if ($config_ignore{$config} ne $min_configs{$config}) {
25684c4ab120SSteven Rostedt		doprint "$config is in allnoconfig as '$config_ignore{$config}'";
25694c4ab120SSteven Rostedt		doprint " but it is '$min_configs{$config}' in minconfig .. keeping\n";
25704c4ab120SSteven Rostedt		$keep_configs{$config} = $min_configs{$config};
25714c4ab120SSteven Rostedt	    } else {
25724c4ab120SSteven Rostedt		doprint "$config set by allnoconfig ... ignored\n";
25734c4ab120SSteven Rostedt	    }
25744c4ab120SSteven Rostedt	    delete $min_configs{$config};
25754c4ab120SSteven Rostedt	}
25764c4ab120SSteven Rostedt    }
25774c4ab120SSteven Rostedt
25784c4ab120SSteven Rostedt    my $done = 0;
2579b9066f6cSSteven Rostedt    my $take_two = 0;
25804c4ab120SSteven Rostedt
25814c4ab120SSteven Rostedt    while (!$done) {
25824c4ab120SSteven Rostedt
25834c4ab120SSteven Rostedt	my $config;
25844c4ab120SSteven Rostedt	my $found;
25854c4ab120SSteven Rostedt
25864c4ab120SSteven Rostedt	# Now disable each config one by one and do a make oldconfig
25874c4ab120SSteven Rostedt	# till we find a config that changes our list.
25884c4ab120SSteven Rostedt
25894c4ab120SSteven Rostedt	# Put configs that did not modify the config at the end.
25904c4ab120SSteven Rostedt	my @test_configs = keys %min_configs;
25914c4ab120SSteven Rostedt	my $reset = 1;
25924c4ab120SSteven Rostedt	for (my $i = 0; $i < $#test_configs; $i++) {
25934c4ab120SSteven Rostedt	    if (!defined($nochange_config{$test_configs[0]})) {
25944c4ab120SSteven Rostedt		$reset = 0;
25954c4ab120SSteven Rostedt		last;
25964c4ab120SSteven Rostedt	    }
25974c4ab120SSteven Rostedt	    # This config didn't change the .config last time.
25984c4ab120SSteven Rostedt	    # Place it at the end
25994c4ab120SSteven Rostedt	    my $config = shift @test_configs;
26004c4ab120SSteven Rostedt	    push @test_configs, $config;
26014c4ab120SSteven Rostedt	}
26024c4ab120SSteven Rostedt
26034c4ab120SSteven Rostedt	# if every test config has failed to modify the .config file
26044c4ab120SSteven Rostedt	# in the past, then reset and start over.
26054c4ab120SSteven Rostedt	if ($reset) {
26064c4ab120SSteven Rostedt	    undef %nochange_config;
26074c4ab120SSteven Rostedt	}
26084c4ab120SSteven Rostedt
2609b9066f6cSSteven Rostedt	undef %processed_configs;
2610b9066f6cSSteven Rostedt
26114c4ab120SSteven Rostedt	foreach my $config (@test_configs) {
26124c4ab120SSteven Rostedt
2613b9066f6cSSteven Rostedt	    $found = test_this_config $config;
26144c4ab120SSteven Rostedt
2615b9066f6cSSteven Rostedt	    last if (defined($found));
26164c4ab120SSteven Rostedt
26174c4ab120SSteven Rostedt	    # oh well, try another config
26184c4ab120SSteven Rostedt	}
26194c4ab120SSteven Rostedt
26204c4ab120SSteven Rostedt	if (!defined($found)) {
2621b9066f6cSSteven Rostedt	    # we could have failed due to the nochange_config hash
2622b9066f6cSSteven Rostedt	    # reset and try again
2623b9066f6cSSteven Rostedt	    if (!$take_two) {
2624b9066f6cSSteven Rostedt		undef %nochange_config;
2625b9066f6cSSteven Rostedt		$take_two = 1;
2626b9066f6cSSteven Rostedt		next;
2627b9066f6cSSteven Rostedt	    }
26284c4ab120SSteven Rostedt	    doprint "No more configs found that we can disable\n";
26294c4ab120SSteven Rostedt	    $done = 1;
26304c4ab120SSteven Rostedt	    last;
26314c4ab120SSteven Rostedt	}
2632b9066f6cSSteven Rostedt	$take_two = 0;
26334c4ab120SSteven Rostedt
26344c4ab120SSteven Rostedt	$config = $found;
26354c4ab120SSteven Rostedt
26364c4ab120SSteven Rostedt	doprint "Test with $config disabled\n";
26374c4ab120SSteven Rostedt
26384c4ab120SSteven Rostedt	# set in_bisect to keep build and monitor from dieing
26394c4ab120SSteven Rostedt	$in_bisect = 1;
26404c4ab120SSteven Rostedt
26414c4ab120SSteven Rostedt	my $failed = 0;
26424c4ab120SSteven Rostedt	build "oldconfig";
26434c4ab120SSteven Rostedt	start_monitor_and_boot or $failed = 1;
26444c4ab120SSteven Rostedt	end_monitor;
26454c4ab120SSteven Rostedt
26464c4ab120SSteven Rostedt	$in_bisect = 0;
26474c4ab120SSteven Rostedt
26484c4ab120SSteven Rostedt	if ($failed) {
2649b9066f6cSSteven Rostedt	    doprint "$min_configs{$config} is needed to boot the box... keeping\n";
26504c4ab120SSteven Rostedt	    # this config is needed, add it to the ignore list.
26514c4ab120SSteven Rostedt	    $keep_configs{$config} = $min_configs{$config};
265243d1b651SSteven Rostedt	    $save_configs{$config} = $min_configs{$config};
26534c4ab120SSteven Rostedt	    delete $min_configs{$config};
265435ce5952SSteven Rostedt
265535ce5952SSteven Rostedt	    # update new ignore configs
265635ce5952SSteven Rostedt	    if (defined($ignore_config)) {
265735ce5952SSteven Rostedt		open (OUT, ">$temp_config")
265835ce5952SSteven Rostedt		    or die "Can't write to $temp_config";
265943d1b651SSteven Rostedt		foreach my $config (keys %save_configs) {
266043d1b651SSteven Rostedt		    print OUT "$save_configs{$config}\n";
266135ce5952SSteven Rostedt		}
266235ce5952SSteven Rostedt		close OUT;
266335ce5952SSteven Rostedt		run_command "mv $temp_config $ignore_config" or
266435ce5952SSteven Rostedt		    dodie "failed to copy update to $ignore_config";
266535ce5952SSteven Rostedt	    }
266635ce5952SSteven Rostedt
26674c4ab120SSteven Rostedt	} else {
26684c4ab120SSteven Rostedt	    # We booted without this config, remove it from the minconfigs.
26694c4ab120SSteven Rostedt	    doprint "$config is not needed, disabling\n";
26704c4ab120SSteven Rostedt
26714c4ab120SSteven Rostedt	    delete $min_configs{$config};
26724c4ab120SSteven Rostedt
26734c4ab120SSteven Rostedt	    # Also disable anything that is not enabled in this config
26744c4ab120SSteven Rostedt	    my %configs;
26754c4ab120SSteven Rostedt	    assign_configs \%configs, $output_config;
26764c4ab120SSteven Rostedt	    my @config_keys = keys %min_configs;
26774c4ab120SSteven Rostedt	    foreach my $config (@config_keys) {
26784c4ab120SSteven Rostedt		if (!defined($configs{$config})) {
26794c4ab120SSteven Rostedt		    doprint "$config is not set, disabling\n";
26804c4ab120SSteven Rostedt		    delete $min_configs{$config};
26814c4ab120SSteven Rostedt		}
26824c4ab120SSteven Rostedt	    }
26834c4ab120SSteven Rostedt
26844c4ab120SSteven Rostedt	    # Save off all the current mandidory configs
268535ce5952SSteven Rostedt	    open (OUT, ">$temp_config")
268635ce5952SSteven Rostedt		or die "Can't write to $temp_config";
26874c4ab120SSteven Rostedt	    foreach my $config (keys %keep_configs) {
26884c4ab120SSteven Rostedt		print OUT "$keep_configs{$config}\n";
26894c4ab120SSteven Rostedt	    }
26904c4ab120SSteven Rostedt	    foreach my $config (keys %min_configs) {
26914c4ab120SSteven Rostedt		print OUT "$min_configs{$config}\n";
26924c4ab120SSteven Rostedt	    }
26934c4ab120SSteven Rostedt	    close OUT;
269435ce5952SSteven Rostedt
269535ce5952SSteven Rostedt	    run_command "mv $temp_config $output_minconfig" or
269635ce5952SSteven Rostedt		dodie "failed to copy update to $output_minconfig";
26974c4ab120SSteven Rostedt	}
26984c4ab120SSteven Rostedt
26994c4ab120SSteven Rostedt	doprint "Reboot and wait $sleep_time seconds\n";
27002728be41SAndrew Jones	reboot $sleep_time;
27014c4ab120SSteven Rostedt    }
27024c4ab120SSteven Rostedt
27034c4ab120SSteven Rostedt    success $i;
27044c4ab120SSteven Rostedt    return 1;
27054c4ab120SSteven Rostedt}
27064c4ab120SSteven Rostedt
27078d1491baSSteven Rostedt$#ARGV < 1 or die "ktest.pl version: $VERSION\n   usage: ktest.pl config-file\n";
27082545eb61SSteven Rostedt
27098d1491baSSteven Rostedtif ($#ARGV == 0) {
27108d1491baSSteven Rostedt    $ktest_config = $ARGV[0];
27118d1491baSSteven Rostedt    if (! -f $ktest_config) {
27128d1491baSSteven Rostedt	print "$ktest_config does not exist.\n";
271335ce5952SSteven Rostedt	if (!read_yn "Create it?") {
27148d1491baSSteven Rostedt	    exit 0;
27158d1491baSSteven Rostedt	}
27168d1491baSSteven Rostedt    }
27178d1491baSSteven Rostedt} else {
27188d1491baSSteven Rostedt    $ktest_config = "ktest.conf";
27198d1491baSSteven Rostedt}
27208d1491baSSteven Rostedt
27218d1491baSSteven Rostedtif (! -f $ktest_config) {
27228d1491baSSteven Rostedt    open(OUT, ">$ktest_config") or die "Can not create $ktest_config";
27238d1491baSSteven Rostedt    print OUT << "EOF"
27248d1491baSSteven Rostedt# Generated by ktest.pl
27258d1491baSSteven Rostedt#
27268d1491baSSteven Rostedt# Define each test with TEST_START
27278d1491baSSteven Rostedt# The config options below it will override the defaults
27288d1491baSSteven RostedtTEST_START
27298d1491baSSteven Rostedt
27308d1491baSSteven RostedtDEFAULTS
27318d1491baSSteven RostedtEOF
27328d1491baSSteven Rostedt;
27338d1491baSSteven Rostedt    close(OUT);
27348d1491baSSteven Rostedt}
27358d1491baSSteven Rostedtread_config $ktest_config;
27368d1491baSSteven Rostedt
273723715c3cSSteven Rostedtif (defined($opt{"LOG_FILE"})) {
273823715c3cSSteven Rostedt    $opt{"LOG_FILE"} = eval_option($opt{"LOG_FILE"}, -1);
273923715c3cSSteven Rostedt}
274023715c3cSSteven Rostedt
27418d1491baSSteven Rostedt# Append any configs entered in manually to the config file.
27428d1491baSSteven Rostedtmy @new_configs = keys %entered_configs;
27438d1491baSSteven Rostedtif ($#new_configs >= 0) {
27448d1491baSSteven Rostedt    print "\nAppending entered in configs to $ktest_config\n";
27458d1491baSSteven Rostedt    open(OUT, ">>$ktest_config") or die "Can not append to $ktest_config";
27468d1491baSSteven Rostedt    foreach my $config (@new_configs) {
27478d1491baSSteven Rostedt	print OUT "$config = $entered_configs{$config}\n";
27488d1491baSSteven Rostedt	$opt{$config} = $entered_configs{$config};
27498d1491baSSteven Rostedt    }
27508d1491baSSteven Rostedt}
27512545eb61SSteven Rostedt
27522b7d9b21SSteven Rostedtif ($opt{"CLEAR_LOG"} && defined($opt{"LOG_FILE"})) {
27532b7d9b21SSteven Rostedt    unlink $opt{"LOG_FILE"};
27542b7d9b21SSteven Rostedt}
27552545eb61SSteven Rostedt
27562b7d9b21SSteven Rostedtdoprint "\n\nSTARTING AUTOMATED TESTS\n\n";
27572b7d9b21SSteven Rostedt
2758a57419b3SSteven Rostedtfor (my $i = 0, my $repeat = 1; $i <= $opt{"NUM_TESTS"}; $i += $repeat) {
2759a57419b3SSteven Rostedt
2760a57419b3SSteven Rostedt    if (!$i) {
2761a57419b3SSteven Rostedt	doprint "DEFAULT OPTIONS:\n";
2762a57419b3SSteven Rostedt    } else {
2763a57419b3SSteven Rostedt	doprint "\nTEST $i OPTIONS";
2764a57419b3SSteven Rostedt	if (defined($repeat_tests{$i})) {
2765a57419b3SSteven Rostedt	    $repeat = $repeat_tests{$i};
2766a57419b3SSteven Rostedt	    doprint " ITERATE $repeat";
2767a57419b3SSteven Rostedt	}
2768a57419b3SSteven Rostedt	doprint "\n";
2769a57419b3SSteven Rostedt    }
2770a57419b3SSteven Rostedt
27712b7d9b21SSteven Rostedt    foreach my $option (sort keys %opt) {
2772a57419b3SSteven Rostedt
2773a57419b3SSteven Rostedt	if ($option =~ /\[(\d+)\]$/) {
2774a57419b3SSteven Rostedt	    next if ($i != $1);
2775a57419b3SSteven Rostedt	} else {
2776a57419b3SSteven Rostedt	    next if ($i);
2777a57419b3SSteven Rostedt	}
2778a57419b3SSteven Rostedt
27792b7d9b21SSteven Rostedt	doprint "$option = $opt{$option}\n";
27802b7d9b21SSteven Rostedt    }
2781a57419b3SSteven Rostedt}
27822545eb61SSteven Rostedt
27832a62512bSSteven Rostedtsub __set_test_option {
27845a391fbfSSteven Rostedt    my ($name, $i) = @_;
27855a391fbfSSteven Rostedt
27865a391fbfSSteven Rostedt    my $option = "$name\[$i\]";
27875a391fbfSSteven Rostedt
27885a391fbfSSteven Rostedt    if (defined($opt{$option})) {
27895a391fbfSSteven Rostedt	return $opt{$option};
27905a391fbfSSteven Rostedt    }
27915a391fbfSSteven Rostedt
2792a57419b3SSteven Rostedt    foreach my $test (keys %repeat_tests) {
2793a57419b3SSteven Rostedt	if ($i >= $test &&
2794a57419b3SSteven Rostedt	    $i < $test + $repeat_tests{$test}) {
2795a57419b3SSteven Rostedt	    $option = "$name\[$test\]";
2796a57419b3SSteven Rostedt	    if (defined($opt{$option})) {
2797a57419b3SSteven Rostedt		return $opt{$option};
2798a57419b3SSteven Rostedt	    }
2799a57419b3SSteven Rostedt	}
2800a57419b3SSteven Rostedt    }
2801a57419b3SSteven Rostedt
28025a391fbfSSteven Rostedt    if (defined($opt{$name})) {
28035a391fbfSSteven Rostedt	return $opt{$name};
28045a391fbfSSteven Rostedt    }
28055a391fbfSSteven Rostedt
28065a391fbfSSteven Rostedt    return undef;
28075a391fbfSSteven Rostedt}
28085a391fbfSSteven Rostedt
28092a62512bSSteven Rostedtsub set_test_option {
28102a62512bSSteven Rostedt    my ($name, $i) = @_;
28112a62512bSSteven Rostedt
28122a62512bSSteven Rostedt    my $option = __set_test_option($name, $i);
28132a62512bSSteven Rostedt    return $option if (!defined($option));
28142a62512bSSteven Rostedt
281523715c3cSSteven Rostedt    return eval_option($option, $i);
28162a62512bSSteven Rostedt}
28172a62512bSSteven Rostedt
28182545eb61SSteven Rostedt# First we need to do is the builds
2819a75fececSSteven Rostedtfor (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
28202545eb61SSteven Rostedt
2821*4ab1cce5SSteven Rostedt    # Do not reboot on failing test options
2822*4ab1cce5SSteven Rostedt    $no_reboot = 1;
2823*4ab1cce5SSteven Rostedt
2824576f627cSSteven Rostedt    $iteration = $i;
2825576f627cSSteven Rostedt
2826a75fececSSteven Rostedt    my $makecmd = set_test_option("MAKE_CMD", $i);
2827a75fececSSteven Rostedt
2828a75fececSSteven Rostedt    $machine = set_test_option("MACHINE", $i);
2829e48c5293SSteven Rostedt    $ssh_user = set_test_option("SSH_USER", $i);
2830a75fececSSteven Rostedt    $tmpdir = set_test_option("TMP_DIR", $i);
2831a75fececSSteven Rostedt    $outputdir = set_test_option("OUTPUT_DIR", $i);
2832a75fececSSteven Rostedt    $builddir = set_test_option("BUILD_DIR", $i);
2833a75fececSSteven Rostedt    $test_type = set_test_option("TEST_TYPE", $i);
2834a75fececSSteven Rostedt    $build_type = set_test_option("BUILD_TYPE", $i);
2835a75fececSSteven Rostedt    $build_options = set_test_option("BUILD_OPTIONS", $i);
28360bd6c1a3SSteven Rostedt    $pre_build = set_test_option("PRE_BUILD", $i);
28370bd6c1a3SSteven Rostedt    $post_build = set_test_option("POST_BUILD", $i);
28380bd6c1a3SSteven Rostedt    $pre_build_die = set_test_option("PRE_BUILD_DIE", $i);
28390bd6c1a3SSteven Rostedt    $post_build_die = set_test_option("POST_BUILD_DIE", $i);
2840a75fececSSteven Rostedt    $power_cycle = set_test_option("POWER_CYCLE", $i);
2841e48c5293SSteven Rostedt    $reboot = set_test_option("REBOOT", $i);
2842a75fececSSteven Rostedt    $noclean = set_test_option("BUILD_NOCLEAN", $i);
2843a75fececSSteven Rostedt    $minconfig = set_test_option("MIN_CONFIG", $i);
28444c4ab120SSteven Rostedt    $output_minconfig = set_test_option("OUTPUT_MIN_CONFIG", $i);
28454c4ab120SSteven Rostedt    $start_minconfig = set_test_option("START_MIN_CONFIG", $i);
28464c4ab120SSteven Rostedt    $ignore_config = set_test_option("IGNORE_CONFIG", $i);
2847a75fececSSteven Rostedt    $run_test = set_test_option("TEST", $i);
2848a75fececSSteven Rostedt    $addconfig = set_test_option("ADD_CONFIG", $i);
2849a75fececSSteven Rostedt    $reboot_type = set_test_option("REBOOT_TYPE", $i);
2850a75fececSSteven Rostedt    $grub_menu = set_test_option("GRUB_MENU", $i);
28518b37ca8cSSteven Rostedt    $post_install = set_test_option("POST_INSTALL", $i);
2852e0a8742eSSteven Rostedt    $no_install = set_test_option("NO_INSTALL", $i);
2853a75fececSSteven Rostedt    $reboot_script = set_test_option("REBOOT_SCRIPT", $i);
2854a75fececSSteven Rostedt    $reboot_on_error = set_test_option("REBOOT_ON_ERROR", $i);
2855a75fececSSteven Rostedt    $poweroff_on_error = set_test_option("POWEROFF_ON_ERROR", $i);
2856a75fececSSteven Rostedt    $die_on_failure = set_test_option("DIE_ON_FAILURE", $i);
2857a75fececSSteven Rostedt    $power_off = set_test_option("POWER_OFF", $i);
2858576f627cSSteven Rostedt    $powercycle_after_reboot = set_test_option("POWERCYCLE_AFTER_REBOOT", $i);
2859576f627cSSteven Rostedt    $poweroff_after_halt = set_test_option("POWEROFF_AFTER_HALT", $i);
2860a75fececSSteven Rostedt    $sleep_time = set_test_option("SLEEP_TIME", $i);
2861a75fececSSteven Rostedt    $bisect_sleep_time = set_test_option("BISECT_SLEEP_TIME", $i);
286227d934b2SSteven Rostedt    $patchcheck_sleep_time = set_test_option("PATCHCHECK_SLEEP_TIME", $i);
28631990207dSSteven Rostedt    $ignore_warnings = set_test_option("IGNORE_WARNINGS", $i);
2864c960bb9fSSteven Rostedt    $bisect_manual = set_test_option("BISECT_MANUAL", $i);
2865c23dca7cSSteven Rostedt    $bisect_skip = set_test_option("BISECT_SKIP", $i);
286630f75da5SSteven Rostedt    $config_bisect_good = set_test_option("CONFIG_BISECT_GOOD", $i);
2867a75fececSSteven Rostedt    $store_failures = set_test_option("STORE_FAILURES", $i);
28689064af52SSteven Rostedt    $test_name = set_test_option("TEST_NAME", $i);
2869a75fececSSteven Rostedt    $timeout = set_test_option("TIMEOUT", $i);
2870a75fececSSteven Rostedt    $booted_timeout = set_test_option("BOOTED_TIMEOUT", $i);
2871a75fececSSteven Rostedt    $console = set_test_option("CONSOLE", $i);
2872f1a5b962SSteven Rostedt    $detect_triplefault = set_test_option("DETECT_TRIPLE_FAULT", $i);
2873a75fececSSteven Rostedt    $success_line = set_test_option("SUCCESS_LINE", $i);
28742b803365SSteven Rostedt    $reboot_success_line = set_test_option("REBOOT_SUCCESS_LINE", $i);
28751c8a617aSSteven Rostedt    $stop_after_success = set_test_option("STOP_AFTER_SUCCESS", $i);
28761c8a617aSSteven Rostedt    $stop_after_failure = set_test_option("STOP_AFTER_FAILURE", $i);
28772d01b26aSSteven Rostedt    $stop_test_after = set_test_option("STOP_TEST_AFTER", $i);
2878a75fececSSteven Rostedt    $build_target = set_test_option("BUILD_TARGET", $i);
2879e48c5293SSteven Rostedt    $ssh_exec = set_test_option("SSH_EXEC", $i);
2880e48c5293SSteven Rostedt    $scp_to_target = set_test_option("SCP_TO_TARGET", $i);
2881a75fececSSteven Rostedt    $target_image = set_test_option("TARGET_IMAGE", $i);
2882a75fececSSteven Rostedt    $localversion = set_test_option("LOCALVERSION", $i);
2883a75fececSSteven Rostedt
288435ce5952SSteven Rostedt    $start_minconfig_defined = 1;
288535ce5952SSteven Rostedt
28864c4ab120SSteven Rostedt    if (!defined($start_minconfig)) {
288735ce5952SSteven Rostedt	$start_minconfig_defined = 0;
28884c4ab120SSteven Rostedt	$start_minconfig = $minconfig;
28894c4ab120SSteven Rostedt    }
28904c4ab120SSteven Rostedt
2891a75fececSSteven Rostedt    chdir $builddir || die "can't change directory to $builddir";
2892a75fececSSteven Rostedt
2893a908a665SAndrew Jones    foreach my $dir ($tmpdir, $outputdir) {
2894a908a665SAndrew Jones	if (!-d $dir) {
2895a908a665SAndrew Jones	    mkpath($dir) or
2896a908a665SAndrew Jones		die "can't create $dir";
2897a908a665SAndrew Jones	}
2898a75fececSSteven Rostedt    }
2899a75fececSSteven Rostedt
2900e48c5293SSteven Rostedt    $ENV{"SSH_USER"} = $ssh_user;
2901e48c5293SSteven Rostedt    $ENV{"MACHINE"} = $machine;
2902e48c5293SSteven Rostedt
2903a75fececSSteven Rostedt    $target = "$ssh_user\@$machine";
2904a75fececSSteven Rostedt
2905a75fececSSteven Rostedt    $buildlog = "$tmpdir/buildlog-$machine";
2906a75fececSSteven Rostedt    $dmesg = "$tmpdir/dmesg-$machine";
2907a75fececSSteven Rostedt    $make = "$makecmd O=$outputdir";
290851ad1dd1SSteven Rostedt    $output_config = "$outputdir/.config";
2909a75fececSSteven Rostedt
2910a75fececSSteven Rostedt    if ($reboot_type eq "grub") {
2911576f627cSSteven Rostedt	dodie "GRUB_MENU not defined" if (!defined($grub_menu));
2912a75fececSSteven Rostedt    } elsif (!defined($reboot_script)) {
2913576f627cSSteven Rostedt	dodie "REBOOT_SCRIPT not defined"
2914a75fececSSteven Rostedt    }
2915a75fececSSteven Rostedt
2916a75fececSSteven Rostedt    my $run_type = $build_type;
2917a75fececSSteven Rostedt    if ($test_type eq "patchcheck") {
2918a75fececSSteven Rostedt	$run_type = $opt{"PATCHCHECK_TYPE[$i]"};
2919a75fececSSteven Rostedt    } elsif ($test_type eq "bisect") {
2920a75fececSSteven Rostedt	$run_type = $opt{"BISECT_TYPE[$i]"};
29210a05c769SSteven Rostedt    } elsif ($test_type eq "config_bisect") {
29220a05c769SSteven Rostedt	$run_type = $opt{"CONFIG_BISECT_TYPE[$i]"};
2923a75fececSSteven Rostedt    }
2924a75fececSSteven Rostedt
29254c4ab120SSteven Rostedt    if ($test_type eq "make_min_config") {
29264c4ab120SSteven Rostedt	$run_type = "";
29274c4ab120SSteven Rostedt    }
29284c4ab120SSteven Rostedt
2929a75fececSSteven Rostedt    # mistake in config file?
2930a75fececSSteven Rostedt    if (!defined($run_type)) {
2931a75fececSSteven Rostedt	$run_type = "ERROR";
2932a75fececSSteven Rostedt    }
29332545eb61SSteven Rostedt
2934e0a8742eSSteven Rostedt    my $installme = "";
2935e0a8742eSSteven Rostedt    $installme = " no_install" if ($no_install);
2936e0a8742eSSteven Rostedt
29372545eb61SSteven Rostedt    doprint "\n\n";
2938e0a8742eSSteven Rostedt    doprint "RUNNING TEST $i of $opt{NUM_TESTS} with option $test_type $run_type$installme\n\n";
29397faafbd6SSteven Rostedt
29407faafbd6SSteven Rostedt    unlink $dmesg;
29417faafbd6SSteven Rostedt    unlink $buildlog;
29422545eb61SSteven Rostedt
2943250bae8bSSteven Rostedt    if (defined($addconfig)) {
2944250bae8bSSteven Rostedt	my $min = $minconfig;
29452b7d9b21SSteven Rostedt	if (!defined($minconfig)) {
2946250bae8bSSteven Rostedt	    $min = "";
2947250bae8bSSteven Rostedt	}
2948250bae8bSSteven Rostedt	run_command "cat $addconfig $min > $tmpdir/add_config" or
29492b7d9b21SSteven Rostedt	    dodie "Failed to create temp config";
29509be2e6b5SSteven Rostedt	$minconfig = "$tmpdir/add_config";
29512b7d9b21SSteven Rostedt    }
29522b7d9b21SSteven Rostedt
29536c5ee0beSSteven Rostedt    my $checkout = $opt{"CHECKOUT[$i]"};
29546c5ee0beSSteven Rostedt    if (defined($checkout)) {
29556c5ee0beSSteven Rostedt	run_command "git checkout $checkout" or
29566c5ee0beSSteven Rostedt	    die "failed to checkout $checkout";
29576c5ee0beSSteven Rostedt    }
29586c5ee0beSSteven Rostedt
2959*4ab1cce5SSteven Rostedt    $no_reboot = 0;
2960*4ab1cce5SSteven Rostedt
2961*4ab1cce5SSteven Rostedt
2962a75fececSSteven Rostedt    if ($test_type eq "bisect") {
29635f9b6cedSSteven Rostedt	bisect $i;
29645f9b6cedSSteven Rostedt	next;
29650a05c769SSteven Rostedt    } elsif ($test_type eq "config_bisect") {
29660a05c769SSteven Rostedt	config_bisect $i;
29670a05c769SSteven Rostedt	next;
2968a75fececSSteven Rostedt    } elsif ($test_type eq "patchcheck") {
29696c5ee0beSSteven Rostedt	patchcheck $i;
29706c5ee0beSSteven Rostedt	next;
29714c4ab120SSteven Rostedt    } elsif ($test_type eq "make_min_config") {
29724c4ab120SSteven Rostedt	make_min_config $i;
29734c4ab120SSteven Rostedt	next;
29745f9b6cedSSteven Rostedt    }
29755f9b6cedSSteven Rostedt
29767faafbd6SSteven Rostedt    if ($build_type ne "nobuild") {
29777faafbd6SSteven Rostedt	build $build_type or next;
29782545eb61SSteven Rostedt    }
29792545eb61SSteven Rostedt
2980cd8e368fSSteven Rostedt    if ($test_type eq "install") {
2981cd8e368fSSteven Rostedt	get_version;
2982cd8e368fSSteven Rostedt	install;
2983cd8e368fSSteven Rostedt	success $i;
2984cd8e368fSSteven Rostedt	next;
2985cd8e368fSSteven Rostedt    }
2986cd8e368fSSteven Rostedt
2987a75fececSSteven Rostedt    if ($test_type ne "build") {
29887faafbd6SSteven Rostedt	my $failed = 0;
2989ddf607e5SSteven Rostedt	start_monitor_and_boot or $failed = 1;
2990a75fececSSteven Rostedt
2991a75fececSSteven Rostedt	if (!$failed && $test_type ne "boot" && defined($run_test)) {
29927faafbd6SSteven Rostedt	    do_run_test or $failed = 1;
29935a391fbfSSteven Rostedt	}
29947faafbd6SSteven Rostedt	end_monitor;
29957faafbd6SSteven Rostedt	next if ($failed);
2996a75fececSSteven Rostedt    }
29975a391fbfSSteven Rostedt
29985f9b6cedSSteven Rostedt    success $i;
299975c3fda7SSteven Rostedt}
30002545eb61SSteven Rostedt
30015c42fc5bSSteven Rostedtif ($opt{"POWEROFF_ON_SUCCESS"}) {
300275c3fda7SSteven Rostedt    halt;
3003576f627cSSteven Rostedt} elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot) {
300475c3fda7SSteven Rostedt    reboot;
30055c42fc5bSSteven Rostedt}
300675c3fda7SSteven Rostedt
3007e48c5293SSteven Rostedtdoprint "\n    $successes of $opt{NUM_TESTS} tests were successful\n\n";
3008e48c5293SSteven Rostedt
30092545eb61SSteven Rostedtexit 0;
3010