xref: /openbmc/linux/tools/testing/ktest/ktest.pl (revision c1434dcc57f97b0e533dedb8814a76ef13e702b4)
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;
212545eb61SSteven Rostedt
222545eb61SSteven Rostedt#default opts
234f43e0dcSSteven Rostedtmy %default = (
244f43e0dcSSteven Rostedt    "NUM_TESTS"			=> 1,
254f43e0dcSSteven Rostedt    "TEST_TYPE"			=> "build",
264f43e0dcSSteven Rostedt    "BUILD_TYPE"		=> "randconfig",
274f43e0dcSSteven Rostedt    "MAKE_CMD"			=> "make",
284f43e0dcSSteven Rostedt    "TIMEOUT"			=> 120,
294f43e0dcSSteven Rostedt    "TMP_DIR"			=> "/tmp/ktest/\${MACHINE}",
304f43e0dcSSteven Rostedt    "SLEEP_TIME"		=> 60,	# sleep time between tests
314f43e0dcSSteven Rostedt    "BUILD_NOCLEAN"		=> 0,
324f43e0dcSSteven Rostedt    "REBOOT_ON_ERROR"		=> 0,
334f43e0dcSSteven Rostedt    "POWEROFF_ON_ERROR"		=> 0,
344f43e0dcSSteven Rostedt    "REBOOT_ON_SUCCESS"		=> 1,
354f43e0dcSSteven Rostedt    "POWEROFF_ON_SUCCESS"	=> 0,
364f43e0dcSSteven Rostedt    "BUILD_OPTIONS"		=> "",
374f43e0dcSSteven Rostedt    "BISECT_SLEEP_TIME"		=> 60,   # sleep time between bisects
384f43e0dcSSteven Rostedt    "PATCHCHECK_SLEEP_TIME"	=> 60, # sleep time between patch checks
394f43e0dcSSteven Rostedt    "CLEAR_LOG"			=> 0,
404f43e0dcSSteven Rostedt    "BISECT_MANUAL"		=> 0,
414f43e0dcSSteven Rostedt    "BISECT_SKIP"		=> 1,
42ccc513b6SSteven Rostedt    "MIN_CONFIG_TYPE"		=> "boot",
434f43e0dcSSteven Rostedt    "SUCCESS_LINE"		=> "login:",
444f43e0dcSSteven Rostedt    "DETECT_TRIPLE_FAULT"	=> 1,
454f43e0dcSSteven Rostedt    "NO_INSTALL"		=> 0,
464f43e0dcSSteven Rostedt    "BOOTED_TIMEOUT"		=> 1,
474f43e0dcSSteven Rostedt    "DIE_ON_FAILURE"		=> 1,
484f43e0dcSSteven Rostedt    "SSH_EXEC"			=> "ssh \$SSH_USER\@\$MACHINE \$SSH_COMMAND",
494f43e0dcSSteven Rostedt    "SCP_TO_TARGET"		=> "scp \$SRC_FILE \$SSH_USER\@\$MACHINE:\$DST_FILE",
5002ad2617SSteven Rostedt    "SCP_TO_TARGET_INSTALL"	=> "\${SCP_TO_TARGET}",
514f43e0dcSSteven Rostedt    "REBOOT"			=> "ssh \$SSH_USER\@\$MACHINE reboot",
524f43e0dcSSteven Rostedt    "STOP_AFTER_SUCCESS"	=> 10,
534f43e0dcSSteven Rostedt    "STOP_AFTER_FAILURE"	=> 60,
544f43e0dcSSteven Rostedt    "STOP_TEST_AFTER"		=> 600,
55407b95b7SSteven Rostedt    "MAX_MONITOR_WAIT"		=> 1800,
56600bbf0aSSteven Rostedt
57600bbf0aSSteven Rostedt# required, and we will ask users if they don't have them but we keep the default
58600bbf0aSSteven Rostedt# value something that is common.
594f43e0dcSSteven Rostedt    "REBOOT_TYPE"		=> "grub",
604f43e0dcSSteven Rostedt    "LOCALVERSION"		=> "-test",
614f43e0dcSSteven Rostedt    "SSH_USER"			=> "root",
624f43e0dcSSteven Rostedt    "BUILD_TARGET"	 	=> "arch/x86/boot/bzImage",
634f43e0dcSSteven Rostedt    "TARGET_IMAGE"		=> "/boot/vmlinuz-test",
649cc9e091SSteven Rostedt
659cc9e091SSteven Rostedt    "LOG_FILE"			=> undef,
669cc9e091SSteven Rostedt    "IGNORE_UNUSED"		=> 0,
674f43e0dcSSteven Rostedt);
682545eb61SSteven Rostedt
698d1491baSSteven Rostedtmy $ktest_config;
702545eb61SSteven Rostedtmy $version;
71683a3e64SSteven Rostedtmy $have_version = 0;
72a75fececSSteven Rostedtmy $machine;
73e48c5293SSteven Rostedtmy $ssh_user;
74a75fececSSteven Rostedtmy $tmpdir;
75a75fececSSteven Rostedtmy $builddir;
76a75fececSSteven Rostedtmy $outputdir;
7751ad1dd1SSteven Rostedtmy $output_config;
78a75fececSSteven Rostedtmy $test_type;
797faafbd6SSteven Rostedtmy $build_type;
80a75fececSSteven Rostedtmy $build_options;
81921ed4c7SSteven Rostedtmy $final_post_ktest;
82921ed4c7SSteven Rostedtmy $pre_ktest;
83921ed4c7SSteven Rostedtmy $post_ktest;
84921ed4c7SSteven Rostedtmy $pre_test;
85921ed4c7SSteven Rostedtmy $post_test;
860bd6c1a3SSteven Rostedtmy $pre_build;
870bd6c1a3SSteven Rostedtmy $post_build;
880bd6c1a3SSteven Rostedtmy $pre_build_die;
890bd6c1a3SSteven Rostedtmy $post_build_die;
90a75fececSSteven Rostedtmy $reboot_type;
91a75fececSSteven Rostedtmy $reboot_script;
92a75fececSSteven Rostedtmy $power_cycle;
93e48c5293SSteven Rostedtmy $reboot;
94a75fececSSteven Rostedtmy $reboot_on_error;
95bc7c5803SSteven Rostedtmy $switch_to_good;
96bc7c5803SSteven Rostedtmy $switch_to_test;
97a75fececSSteven Rostedtmy $poweroff_on_error;
98648a182cSSteven Rostedtmy $reboot_on_success;
99a75fececSSteven Rostedtmy $die_on_failure;
100576f627cSSteven Rostedtmy $powercycle_after_reboot;
101576f627cSSteven Rostedtmy $poweroff_after_halt;
102407b95b7SSteven Rostedtmy $max_monitor_wait;
103e48c5293SSteven Rostedtmy $ssh_exec;
104e48c5293SSteven Rostedtmy $scp_to_target;
10502ad2617SSteven Rostedtmy $scp_to_target_install;
106a75fececSSteven Rostedtmy $power_off;
107a75fececSSteven Rostedtmy $grub_menu;
1082545eb61SSteven Rostedtmy $grub_number;
1092545eb61SSteven Rostedtmy $target;
1102545eb61SSteven Rostedtmy $make;
111e5c2ec11SSteven Rostedtmy $pre_install;
1128b37ca8cSSteven Rostedtmy $post_install;
113e0a8742eSSteven Rostedtmy $no_install;
1145c42fc5bSSteven Rostedtmy $noclean;
1155f9b6cedSSteven Rostedtmy $minconfig;
1164c4ab120SSteven Rostedtmy $start_minconfig;
11735ce5952SSteven Rostedtmy $start_minconfig_defined;
1184c4ab120SSteven Rostedtmy $output_minconfig;
119ccc513b6SSteven Rostedtmy $minconfig_type;
12043de3316SSteven Rostedtmy $use_output_minconfig;
1214c4ab120SSteven Rostedtmy $ignore_config;
122be405f95SSteven Rostedtmy $ignore_errors;
1232b7d9b21SSteven Rostedtmy $addconfig;
1245f9b6cedSSteven Rostedtmy $in_bisect = 0;
125b5f4aea6SSteven Rostedtmy $bisect_bad_commit = "";
126d6ce2a0bSSteven Rostedtmy $reverse_bisect;
127c960bb9fSSteven Rostedtmy $bisect_manual;
128c23dca7cSSteven Rostedtmy $bisect_skip;
12930f75da5SSteven Rostedtmy $config_bisect_good;
130c5dacb88SSteven Rostedtmy $bisect_ret_good;
131c5dacb88SSteven Rostedtmy $bisect_ret_bad;
132c5dacb88SSteven Rostedtmy $bisect_ret_skip;
133c5dacb88SSteven Rostedtmy $bisect_ret_abort;
134c5dacb88SSteven Rostedtmy $bisect_ret_default;
1356c5ee0beSSteven Rostedtmy $in_patchcheck = 0;
1365a391fbfSSteven Rostedtmy $run_test;
1376c5ee0beSSteven Rostedtmy $redirect;
1387faafbd6SSteven Rostedtmy $buildlog;
139a9dd5d63SRabin Vincentmy $testlog;
1407faafbd6SSteven Rostedtmy $dmesg;
1417faafbd6SSteven Rostedtmy $monitor_fp;
1427faafbd6SSteven Rostedtmy $monitor_pid;
1437faafbd6SSteven Rostedtmy $monitor_cnt = 0;
144a75fececSSteven Rostedtmy $sleep_time;
145a75fececSSteven Rostedtmy $bisect_sleep_time;
14627d934b2SSteven Rostedtmy $patchcheck_sleep_time;
1471990207dSSteven Rostedtmy $ignore_warnings;
148a75fececSSteven Rostedtmy $store_failures;
149de5b6e3bSRabin Vincentmy $store_successes;
1509064af52SSteven Rostedtmy $test_name;
151a75fececSSteven Rostedtmy $timeout;
152a75fececSSteven Rostedtmy $booted_timeout;
153f1a5b962SSteven Rostedtmy $detect_triplefault;
154a75fececSSteven Rostedtmy $console;
1552b803365SSteven Rostedtmy $reboot_success_line;
156a75fececSSteven Rostedtmy $success_line;
1571c8a617aSSteven Rostedtmy $stop_after_success;
1581c8a617aSSteven Rostedtmy $stop_after_failure;
1592d01b26aSSteven Rostedtmy $stop_test_after;
160a75fececSSteven Rostedtmy $build_target;
161a75fececSSteven Rostedtmy $target_image;
162b5f4aea6SSteven Rostedtmy $checkout;
163a75fececSSteven Rostedtmy $localversion;
164576f627cSSteven Rostedtmy $iteration = 0;
165e48c5293SSteven Rostedtmy $successes = 0;
1662545eb61SSteven Rostedt
167b5f4aea6SSteven Rostedtmy $bisect_good;
168b5f4aea6SSteven Rostedtmy $bisect_bad;
169b5f4aea6SSteven Rostedtmy $bisect_type;
170b5f4aea6SSteven Rostedtmy $bisect_start;
171b5f4aea6SSteven Rostedtmy $bisect_replay;
172b5f4aea6SSteven Rostedtmy $bisect_files;
173b5f4aea6SSteven Rostedtmy $bisect_reverse;
174b5f4aea6SSteven Rostedtmy $bisect_check;
175b5f4aea6SSteven Rostedt
176b5f4aea6SSteven Rostedtmy $config_bisect;
177b5f4aea6SSteven Rostedtmy $config_bisect_type;
178b0918612SSteven Rostedtmy $config_bisect_check;
179b5f4aea6SSteven Rostedt
180b5f4aea6SSteven Rostedtmy $patchcheck_type;
181b5f4aea6SSteven Rostedtmy $patchcheck_start;
182b5f4aea6SSteven Rostedtmy $patchcheck_end;
183b5f4aea6SSteven Rostedt
184165708b2SSteven Rostedt# set when a test is something other that just building or install
185bb8474b1SSteven Rostedt# which would require more options.
186bb8474b1SSteven Rostedtmy $buildonly = 1;
187bb8474b1SSteven Rostedt
188dbd3783bSSteven Rostedt# set when creating a new config
189dbd3783bSSteven Rostedtmy $newconfig = 0;
190dbd3783bSSteven Rostedt
1918d1491baSSteven Rostedtmy %entered_configs;
1928d1491baSSteven Rostedtmy %config_help;
19377d942ceSSteven Rostedtmy %variable;
194cf79fab6SSteven Rostedt
195cf79fab6SSteven Rostedt# force_config is the list of configs that we force enabled (or disabled)
196cf79fab6SSteven Rostedt# in a .config file. The MIN_CONFIG and ADD_CONFIG configs.
197fcb3f16aSSteven Rostedtmy %force_config;
1988d1491baSSteven Rostedt
1994ab1cce5SSteven Rostedt# do not force reboots on config problems
2004ab1cce5SSteven Rostedtmy $no_reboot = 1;
2014ab1cce5SSteven Rostedt
202759a3cc6SSteven Rostedt# reboot on success
203759a3cc6SSteven Rostedtmy $reboot_success = 0;
204759a3cc6SSteven Rostedt
2059cc9e091SSteven Rostedtmy %option_map = (
2069cc9e091SSteven Rostedt    "MACHINE"			=> \$machine,
2079cc9e091SSteven Rostedt    "SSH_USER"			=> \$ssh_user,
2089cc9e091SSteven Rostedt    "TMP_DIR"			=> \$tmpdir,
2099cc9e091SSteven Rostedt    "OUTPUT_DIR"		=> \$outputdir,
2109cc9e091SSteven Rostedt    "BUILD_DIR"			=> \$builddir,
2119cc9e091SSteven Rostedt    "TEST_TYPE"			=> \$test_type,
212921ed4c7SSteven Rostedt    "PRE_KTEST"			=> \$pre_ktest,
213921ed4c7SSteven Rostedt    "POST_KTEST"		=> \$post_ktest,
214921ed4c7SSteven Rostedt    "PRE_TEST"			=> \$pre_test,
215921ed4c7SSteven Rostedt    "POST_TEST"			=> \$post_test,
2169cc9e091SSteven Rostedt    "BUILD_TYPE"		=> \$build_type,
2179cc9e091SSteven Rostedt    "BUILD_OPTIONS"		=> \$build_options,
2189cc9e091SSteven Rostedt    "PRE_BUILD"			=> \$pre_build,
2199cc9e091SSteven Rostedt    "POST_BUILD"		=> \$post_build,
2209cc9e091SSteven Rostedt    "PRE_BUILD_DIE"		=> \$pre_build_die,
2219cc9e091SSteven Rostedt    "POST_BUILD_DIE"		=> \$post_build_die,
2229cc9e091SSteven Rostedt    "POWER_CYCLE"		=> \$power_cycle,
2239cc9e091SSteven Rostedt    "REBOOT"			=> \$reboot,
2249cc9e091SSteven Rostedt    "BUILD_NOCLEAN"		=> \$noclean,
2259cc9e091SSteven Rostedt    "MIN_CONFIG"		=> \$minconfig,
2269cc9e091SSteven Rostedt    "OUTPUT_MIN_CONFIG"		=> \$output_minconfig,
2279cc9e091SSteven Rostedt    "START_MIN_CONFIG"		=> \$start_minconfig,
228ccc513b6SSteven Rostedt    "MIN_CONFIG_TYPE"		=> \$minconfig_type,
22943de3316SSteven Rostedt    "USE_OUTPUT_MIN_CONFIG"	=> \$use_output_minconfig,
2309cc9e091SSteven Rostedt    "IGNORE_CONFIG"		=> \$ignore_config,
2319cc9e091SSteven Rostedt    "TEST"			=> \$run_test,
2329cc9e091SSteven Rostedt    "ADD_CONFIG"		=> \$addconfig,
2339cc9e091SSteven Rostedt    "REBOOT_TYPE"		=> \$reboot_type,
2349cc9e091SSteven Rostedt    "GRUB_MENU"			=> \$grub_menu,
235e5c2ec11SSteven Rostedt    "PRE_INSTALL"		=> \$pre_install,
2369cc9e091SSteven Rostedt    "POST_INSTALL"		=> \$post_install,
2379cc9e091SSteven Rostedt    "NO_INSTALL"		=> \$no_install,
2389cc9e091SSteven Rostedt    "REBOOT_SCRIPT"		=> \$reboot_script,
2399cc9e091SSteven Rostedt    "REBOOT_ON_ERROR"		=> \$reboot_on_error,
2409cc9e091SSteven Rostedt    "SWITCH_TO_GOOD"		=> \$switch_to_good,
2419cc9e091SSteven Rostedt    "SWITCH_TO_TEST"		=> \$switch_to_test,
2429cc9e091SSteven Rostedt    "POWEROFF_ON_ERROR"		=> \$poweroff_on_error,
243648a182cSSteven Rostedt    "REBOOT_ON_SUCCESS"		=> \$reboot_on_success,
2449cc9e091SSteven Rostedt    "DIE_ON_FAILURE"		=> \$die_on_failure,
2459cc9e091SSteven Rostedt    "POWER_OFF"			=> \$power_off,
2469cc9e091SSteven Rostedt    "POWERCYCLE_AFTER_REBOOT"	=> \$powercycle_after_reboot,
2479cc9e091SSteven Rostedt    "POWEROFF_AFTER_HALT"	=> \$poweroff_after_halt,
248407b95b7SSteven Rostedt    "MAX_MONITOR_WAIT"		=> \$max_monitor_wait,
2499cc9e091SSteven Rostedt    "SLEEP_TIME"		=> \$sleep_time,
2509cc9e091SSteven Rostedt    "BISECT_SLEEP_TIME"		=> \$bisect_sleep_time,
2519cc9e091SSteven Rostedt    "PATCHCHECK_SLEEP_TIME"	=> \$patchcheck_sleep_time,
2529cc9e091SSteven Rostedt    "IGNORE_WARNINGS"		=> \$ignore_warnings,
253be405f95SSteven Rostedt    "IGNORE_ERRORS"		=> \$ignore_errors,
2549cc9e091SSteven Rostedt    "BISECT_MANUAL"		=> \$bisect_manual,
2559cc9e091SSteven Rostedt    "BISECT_SKIP"		=> \$bisect_skip,
2569cc9e091SSteven Rostedt    "CONFIG_BISECT_GOOD"	=> \$config_bisect_good,
2579cc9e091SSteven Rostedt    "BISECT_RET_GOOD"		=> \$bisect_ret_good,
2589cc9e091SSteven Rostedt    "BISECT_RET_BAD"		=> \$bisect_ret_bad,
2599cc9e091SSteven Rostedt    "BISECT_RET_SKIP"		=> \$bisect_ret_skip,
2609cc9e091SSteven Rostedt    "BISECT_RET_ABORT"		=> \$bisect_ret_abort,
2619cc9e091SSteven Rostedt    "BISECT_RET_DEFAULT"	=> \$bisect_ret_default,
2629cc9e091SSteven Rostedt    "STORE_FAILURES"		=> \$store_failures,
2639cc9e091SSteven Rostedt    "STORE_SUCCESSES"		=> \$store_successes,
2649cc9e091SSteven Rostedt    "TEST_NAME"			=> \$test_name,
2659cc9e091SSteven Rostedt    "TIMEOUT"			=> \$timeout,
2669cc9e091SSteven Rostedt    "BOOTED_TIMEOUT"		=> \$booted_timeout,
2679cc9e091SSteven Rostedt    "CONSOLE"			=> \$console,
2689cc9e091SSteven Rostedt    "DETECT_TRIPLE_FAULT"	=> \$detect_triplefault,
2699cc9e091SSteven Rostedt    "SUCCESS_LINE"		=> \$success_line,
2709cc9e091SSteven Rostedt    "REBOOT_SUCCESS_LINE"	=> \$reboot_success_line,
2719cc9e091SSteven Rostedt    "STOP_AFTER_SUCCESS"	=> \$stop_after_success,
2729cc9e091SSteven Rostedt    "STOP_AFTER_FAILURE"	=> \$stop_after_failure,
2739cc9e091SSteven Rostedt    "STOP_TEST_AFTER"		=> \$stop_test_after,
2749cc9e091SSteven Rostedt    "BUILD_TARGET"		=> \$build_target,
2759cc9e091SSteven Rostedt    "SSH_EXEC"			=> \$ssh_exec,
2769cc9e091SSteven Rostedt    "SCP_TO_TARGET"		=> \$scp_to_target,
27702ad2617SSteven Rostedt    "SCP_TO_TARGET_INSTALL"	=> \$scp_to_target_install,
2789cc9e091SSteven Rostedt    "CHECKOUT"			=> \$checkout,
2799cc9e091SSteven Rostedt    "TARGET_IMAGE"		=> \$target_image,
2809cc9e091SSteven Rostedt    "LOCALVERSION"		=> \$localversion,
2819cc9e091SSteven Rostedt
2829cc9e091SSteven Rostedt    "BISECT_GOOD"		=> \$bisect_good,
2839cc9e091SSteven Rostedt    "BISECT_BAD"		=> \$bisect_bad,
2849cc9e091SSteven Rostedt    "BISECT_TYPE"		=> \$bisect_type,
2859cc9e091SSteven Rostedt    "BISECT_START"		=> \$bisect_start,
2869cc9e091SSteven Rostedt    "BISECT_REPLAY"		=> \$bisect_replay,
2879cc9e091SSteven Rostedt    "BISECT_FILES"		=> \$bisect_files,
2889cc9e091SSteven Rostedt    "BISECT_REVERSE"		=> \$bisect_reverse,
2899cc9e091SSteven Rostedt    "BISECT_CHECK"		=> \$bisect_check,
2909cc9e091SSteven Rostedt
2919cc9e091SSteven Rostedt    "CONFIG_BISECT"		=> \$config_bisect,
2929cc9e091SSteven Rostedt    "CONFIG_BISECT_TYPE"	=> \$config_bisect_type,
293b0918612SSteven Rostedt    "CONFIG_BISECT_CHECK"	=> \$config_bisect_check,
2949cc9e091SSteven Rostedt
2959cc9e091SSteven Rostedt    "PATCHCHECK_TYPE"		=> \$patchcheck_type,
2969cc9e091SSteven Rostedt    "PATCHCHECK_START"		=> \$patchcheck_start,
2979cc9e091SSteven Rostedt    "PATCHCHECK_END"		=> \$patchcheck_end,
2989cc9e091SSteven Rostedt);
2999cc9e091SSteven Rostedt
3009cc9e091SSteven Rostedt# Options may be used by other options, record them.
3019cc9e091SSteven Rostedtmy %used_options;
3029cc9e091SSteven Rostedt
3037bf51073SSteven Rostedt# default variables that can be used
3047bf51073SSteven Rostedtchomp ($variable{"PWD"} = `pwd`);
3057bf51073SSteven Rostedt
3068d1491baSSteven Rostedt$config_help{"MACHINE"} = << "EOF"
3078d1491baSSteven Rostedt The machine hostname that you will test.
308bb8474b1SSteven Rostedt For build only tests, it is still needed to differentiate log files.
3098d1491baSSteven RostedtEOF
3108d1491baSSteven Rostedt    ;
3118d1491baSSteven Rostedt$config_help{"SSH_USER"} = << "EOF"
3128d1491baSSteven Rostedt The box is expected to have ssh on normal bootup, provide the user
3138d1491baSSteven Rostedt  (most likely root, since you need privileged operations)
3148d1491baSSteven RostedtEOF
3158d1491baSSteven Rostedt    ;
3168d1491baSSteven Rostedt$config_help{"BUILD_DIR"} = << "EOF"
3178d1491baSSteven Rostedt The directory that contains the Linux source code (full path).
3180e7a22deSSteven Rostedt You can use \${PWD} that will be the path where ktest.pl is run, or use
3190e7a22deSSteven Rostedt \${THIS_DIR} which is assigned \${PWD} but may be changed later.
3208d1491baSSteven RostedtEOF
3218d1491baSSteven Rostedt    ;
3228d1491baSSteven Rostedt$config_help{"OUTPUT_DIR"} = << "EOF"
3238d1491baSSteven Rostedt The directory that the objects will be built (full path).
3248d1491baSSteven Rostedt (can not be same as BUILD_DIR)
3250e7a22deSSteven Rostedt You can use \${PWD} that will be the path where ktest.pl is run, or use
3260e7a22deSSteven Rostedt \${THIS_DIR} which is assigned \${PWD} but may be changed later.
3278d1491baSSteven RostedtEOF
3288d1491baSSteven Rostedt    ;
3298d1491baSSteven Rostedt$config_help{"BUILD_TARGET"} = << "EOF"
3308d1491baSSteven Rostedt The location of the compiled file to copy to the target.
3318d1491baSSteven Rostedt (relative to OUTPUT_DIR)
3328d1491baSSteven RostedtEOF
3338d1491baSSteven Rostedt    ;
334dbd3783bSSteven Rostedt$config_help{"BUILD_OPTIONS"} = << "EOF"
335dbd3783bSSteven Rostedt Options to add to \"make\" when building.
336dbd3783bSSteven Rostedt i.e.  -j20
337dbd3783bSSteven RostedtEOF
338dbd3783bSSteven Rostedt    ;
3398d1491baSSteven Rostedt$config_help{"TARGET_IMAGE"} = << "EOF"
3408d1491baSSteven Rostedt The place to put your image on the test machine.
3418d1491baSSteven RostedtEOF
3428d1491baSSteven Rostedt    ;
3438d1491baSSteven Rostedt$config_help{"POWER_CYCLE"} = << "EOF"
3448d1491baSSteven Rostedt A script or command to reboot the box.
3458d1491baSSteven Rostedt
3468d1491baSSteven Rostedt Here is a digital loggers power switch example
3478d1491baSSteven Rostedt POWER_CYCLE = wget --no-proxy -O /dev/null -q  --auth-no-challenge 'http://admin:admin\@power/outlet?5=CCL'
3488d1491baSSteven Rostedt
3498d1491baSSteven Rostedt Here is an example to reboot a virtual box on the current host
3508d1491baSSteven Rostedt with the name "Guest".
3518d1491baSSteven Rostedt POWER_CYCLE = virsh destroy Guest; sleep 5; virsh start Guest
3528d1491baSSteven RostedtEOF
3538d1491baSSteven Rostedt    ;
3548d1491baSSteven Rostedt$config_help{"CONSOLE"} = << "EOF"
3558d1491baSSteven Rostedt The script or command that reads the console
3568d1491baSSteven Rostedt
3578d1491baSSteven Rostedt  If you use ttywatch server, something like the following would work.
3588d1491baSSteven RostedtCONSOLE = nc -d localhost 3001
3598d1491baSSteven Rostedt
3608d1491baSSteven Rostedt For a virtual machine with guest name "Guest".
3618d1491baSSteven RostedtCONSOLE =  virsh console Guest
3628d1491baSSteven RostedtEOF
3638d1491baSSteven Rostedt    ;
3648d1491baSSteven Rostedt$config_help{"LOCALVERSION"} = << "EOF"
3658d1491baSSteven Rostedt Required version ending to differentiate the test
3668d1491baSSteven Rostedt from other linux builds on the system.
3678d1491baSSteven RostedtEOF
3688d1491baSSteven Rostedt    ;
3698d1491baSSteven Rostedt$config_help{"REBOOT_TYPE"} = << "EOF"
3708d1491baSSteven Rostedt Way to reboot the box to the test kernel.
3718d1491baSSteven Rostedt Only valid options so far are "grub" and "script".
3728d1491baSSteven Rostedt
3738d1491baSSteven Rostedt If you specify grub, it will assume grub version 1
3748d1491baSSteven Rostedt and will search in /boot/grub/menu.lst for the title \$GRUB_MENU
3758d1491baSSteven Rostedt and select that target to reboot to the kernel. If this is not
3768d1491baSSteven Rostedt your setup, then specify "script" and have a command or script
3778d1491baSSteven Rostedt specified in REBOOT_SCRIPT to boot to the target.
3788d1491baSSteven Rostedt
3798d1491baSSteven Rostedt The entry in /boot/grub/menu.lst must be entered in manually.
3808d1491baSSteven Rostedt The test will not modify that file.
3818d1491baSSteven RostedtEOF
3828d1491baSSteven Rostedt    ;
3838d1491baSSteven Rostedt$config_help{"GRUB_MENU"} = << "EOF"
3848d1491baSSteven Rostedt The grub title name for the test kernel to boot
3858d1491baSSteven Rostedt (Only mandatory if REBOOT_TYPE = grub)
3868d1491baSSteven Rostedt
3878d1491baSSteven Rostedt Note, ktest.pl will not update the grub menu.lst, you need to
3888d1491baSSteven Rostedt manually add an option for the test. ktest.pl will search
3898d1491baSSteven Rostedt the grub menu.lst for this option to find what kernel to
3908d1491baSSteven Rostedt reboot into.
3918d1491baSSteven Rostedt
3928d1491baSSteven Rostedt For example, if in the /boot/grub/menu.lst the test kernel title has:
3938d1491baSSteven Rostedt title Test Kernel
3948d1491baSSteven Rostedt kernel vmlinuz-test
3958d1491baSSteven Rostedt GRUB_MENU = Test Kernel
3968d1491baSSteven RostedtEOF
3978d1491baSSteven Rostedt    ;
3988d1491baSSteven Rostedt$config_help{"REBOOT_SCRIPT"} = << "EOF"
3998d1491baSSteven Rostedt A script to reboot the target into the test kernel
4008d1491baSSteven Rostedt (Only mandatory if REBOOT_TYPE = script)
4018d1491baSSteven RostedtEOF
4028d1491baSSteven Rostedt    ;
4038d1491baSSteven Rostedt
404dad98754SSteven Rostedtsub read_prompt {
405dad98754SSteven Rostedt    my ($cancel, $prompt) = @_;
40635ce5952SSteven Rostedt
40735ce5952SSteven Rostedt    my $ans;
40835ce5952SSteven Rostedt
40935ce5952SSteven Rostedt    for (;;) {
410dad98754SSteven Rostedt	if ($cancel) {
411dad98754SSteven Rostedt	    print "$prompt [y/n/C] ";
412dad98754SSteven Rostedt	} else {
41335ce5952SSteven Rostedt	    print "$prompt [Y/n] ";
414dad98754SSteven Rostedt	}
41535ce5952SSteven Rostedt	$ans = <STDIN>;
41635ce5952SSteven Rostedt	chomp $ans;
41735ce5952SSteven Rostedt	if ($ans =~ /^\s*$/) {
418dad98754SSteven Rostedt	    if ($cancel) {
419dad98754SSteven Rostedt		$ans = "c";
420dad98754SSteven Rostedt	    } else {
42135ce5952SSteven Rostedt		$ans = "y";
42235ce5952SSteven Rostedt	    }
423dad98754SSteven Rostedt	}
42435ce5952SSteven Rostedt	last if ($ans =~ /^y$/i || $ans =~ /^n$/i);
425dad98754SSteven Rostedt	if ($cancel) {
426dad98754SSteven Rostedt	    last if ($ans =~ /^c$/i);
427dad98754SSteven Rostedt	    print "Please answer either 'y', 'n' or 'c'.\n";
428dad98754SSteven Rostedt	} else {
42935ce5952SSteven Rostedt	    print "Please answer either 'y' or 'n'.\n";
43035ce5952SSteven Rostedt	}
431dad98754SSteven Rostedt    }
432dad98754SSteven Rostedt    if ($ans =~ /^c/i) {
433dad98754SSteven Rostedt	exit;
434dad98754SSteven Rostedt    }
43535ce5952SSteven Rostedt    if ($ans !~ /^y$/i) {
43635ce5952SSteven Rostedt	return 0;
43735ce5952SSteven Rostedt    }
43835ce5952SSteven Rostedt    return 1;
43935ce5952SSteven Rostedt}
4408d1491baSSteven Rostedt
441dad98754SSteven Rostedtsub read_yn {
442dad98754SSteven Rostedt    my ($prompt) = @_;
443dad98754SSteven Rostedt
444dad98754SSteven Rostedt    return read_prompt 0, $prompt;
445dad98754SSteven Rostedt}
446dad98754SSteven Rostedt
447dad98754SSteven Rostedtsub read_ync {
448dad98754SSteven Rostedt    my ($prompt) = @_;
449dad98754SSteven Rostedt
450dad98754SSteven Rostedt    return read_prompt 1, $prompt;
451dad98754SSteven Rostedt}
452dad98754SSteven Rostedt
4538d1491baSSteven Rostedtsub get_ktest_config {
4548d1491baSSteven Rostedt    my ($config) = @_;
455815e2bd7SSteven Rostedt    my $ans;
4568d1491baSSteven Rostedt
4578d1491baSSteven Rostedt    return if (defined($opt{$config}));
4588d1491baSSteven Rostedt
4598d1491baSSteven Rostedt    if (defined($config_help{$config})) {
4608d1491baSSteven Rostedt	print "\n";
4618d1491baSSteven Rostedt	print $config_help{$config};
4628d1491baSSteven Rostedt    }
4638d1491baSSteven Rostedt
4648d1491baSSteven Rostedt    for (;;) {
4658d1491baSSteven Rostedt	print "$config = ";
466dbd3783bSSteven Rostedt	if (defined($default{$config}) && length($default{$config})) {
4678d1491baSSteven Rostedt	    print "\[$default{$config}\] ";
4688d1491baSSteven Rostedt	}
469815e2bd7SSteven Rostedt	$ans = <STDIN>;
470815e2bd7SSteven Rostedt	$ans =~ s/^\s*(.*\S)\s*$/$1/;
471815e2bd7SSteven Rostedt	if ($ans =~ /^\s*$/) {
4728d1491baSSteven Rostedt	    if ($default{$config}) {
473815e2bd7SSteven Rostedt		$ans = $default{$config};
4748d1491baSSteven Rostedt	    } else {
4758d1491baSSteven Rostedt		print "Your answer can not be blank\n";
4768d1491baSSteven Rostedt		next;
4778d1491baSSteven Rostedt	    }
4788d1491baSSteven Rostedt	}
4790e7a22deSSteven Rostedt	$entered_configs{$config} = ${ans};
4808d1491baSSteven Rostedt	last;
4818d1491baSSteven Rostedt    }
4828d1491baSSteven Rostedt}
4838d1491baSSteven Rostedt
4848d1491baSSteven Rostedtsub get_ktest_configs {
4858d1491baSSteven Rostedt    get_ktest_config("MACHINE");
4868d1491baSSteven Rostedt    get_ktest_config("BUILD_DIR");
4878d1491baSSteven Rostedt    get_ktest_config("OUTPUT_DIR");
488bb8474b1SSteven Rostedt
489dbd3783bSSteven Rostedt    if ($newconfig) {
490dbd3783bSSteven Rostedt	get_ktest_config("BUILD_OPTIONS");
491dbd3783bSSteven Rostedt    }
492dbd3783bSSteven Rostedt
493bb8474b1SSteven Rostedt    # options required for other than just building a kernel
494bb8474b1SSteven Rostedt    if (!$buildonly) {
495165708b2SSteven Rostedt	get_ktest_config("POWER_CYCLE");
496165708b2SSteven Rostedt	get_ktest_config("CONSOLE");
497165708b2SSteven Rostedt    }
498165708b2SSteven Rostedt
499165708b2SSteven Rostedt    # options required for install and more
500165708b2SSteven Rostedt    if ($buildonly != 1) {
501bb8474b1SSteven Rostedt	get_ktest_config("SSH_USER");
5028d1491baSSteven Rostedt	get_ktest_config("BUILD_TARGET");
5038d1491baSSteven Rostedt	get_ktest_config("TARGET_IMAGE");
504bb8474b1SSteven Rostedt    }
505bb8474b1SSteven Rostedt
5068d1491baSSteven Rostedt    get_ktest_config("LOCALVERSION");
5078d1491baSSteven Rostedt
508bb8474b1SSteven Rostedt    return if ($buildonly);
509bb8474b1SSteven Rostedt
5108d1491baSSteven Rostedt    my $rtype = $opt{"REBOOT_TYPE"};
5118d1491baSSteven Rostedt
5128d1491baSSteven Rostedt    if (!defined($rtype)) {
5138d1491baSSteven Rostedt	if (!defined($opt{"GRUB_MENU"})) {
5148d1491baSSteven Rostedt	    get_ktest_config("REBOOT_TYPE");
5158d1491baSSteven Rostedt	    $rtype = $entered_configs{"REBOOT_TYPE"};
5168d1491baSSteven Rostedt	} else {
5178d1491baSSteven Rostedt	    $rtype = "grub";
5188d1491baSSteven Rostedt	}
5198d1491baSSteven Rostedt    }
5208d1491baSSteven Rostedt
5218d1491baSSteven Rostedt    if ($rtype eq "grub") {
5228d1491baSSteven Rostedt	get_ktest_config("GRUB_MENU");
5238d1491baSSteven Rostedt    }
5248d1491baSSteven Rostedt}
5258d1491baSSteven Rostedt
52677d942ceSSteven Rostedtsub process_variables {
5278d735212SSteven Rostedt    my ($value, $remove_undef) = @_;
52877d942ceSSteven Rostedt    my $retval = "";
52977d942ceSSteven Rostedt
53077d942ceSSteven Rostedt    # We want to check for '\', and it is just easier
53177d942ceSSteven Rostedt    # to check the previous characet of '$' and not need
53277d942ceSSteven Rostedt    # to worry if '$' is the first character. By adding
53377d942ceSSteven Rostedt    # a space to $value, we can just check [^\\]\$ and
53477d942ceSSteven Rostedt    # it will still work.
53577d942ceSSteven Rostedt    $value = " $value";
53677d942ceSSteven Rostedt
53777d942ceSSteven Rostedt    while ($value =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) {
53877d942ceSSteven Rostedt	my $begin = $1;
53977d942ceSSteven Rostedt	my $var = $2;
54077d942ceSSteven Rostedt	my $end = $3;
54177d942ceSSteven Rostedt	# append beginning of value to retval
54277d942ceSSteven Rostedt	$retval = "$retval$begin";
54377d942ceSSteven Rostedt	if (defined($variable{$var})) {
54477d942ceSSteven Rostedt	    $retval = "$retval$variable{$var}";
5458d735212SSteven Rostedt	} elsif (defined($remove_undef) && $remove_undef) {
5468d735212SSteven Rostedt	    # for if statements, any variable that is not defined,
5478d735212SSteven Rostedt	    # we simple convert to 0
5488d735212SSteven Rostedt	    $retval = "${retval}0";
54977d942ceSSteven Rostedt	} else {
55077d942ceSSteven Rostedt	    # put back the origin piece.
55177d942ceSSteven Rostedt	    $retval = "$retval\$\{$var\}";
5529cc9e091SSteven Rostedt	    # This could be an option that is used later, save
5539cc9e091SSteven Rostedt	    # it so we don't warn if this option is not one of
5549cc9e091SSteven Rostedt	    # ktests options.
5559cc9e091SSteven Rostedt	    $used_options{$var} = 1;
55677d942ceSSteven Rostedt	}
55777d942ceSSteven Rostedt	$value = $end;
55877d942ceSSteven Rostedt    }
55977d942ceSSteven Rostedt    $retval = "$retval$value";
56077d942ceSSteven Rostedt
56177d942ceSSteven Rostedt    # remove the space added in the beginning
56277d942ceSSteven Rostedt    $retval =~ s/ //;
56377d942ceSSteven Rostedt
56477d942ceSSteven Rostedt    return "$retval"
56577d942ceSSteven Rostedt}
56677d942ceSSteven Rostedt
567a57419b3SSteven Rostedtsub set_value {
5683d1cc414SSteven Rostedt    my ($lvalue, $rvalue, $override, $overrides, $name) = @_;
5692545eb61SSteven Rostedt
570cad96669SSteven Rostedt    my $prvalue = process_variables($rvalue);
571cad96669SSteven Rostedt
572cad96669SSteven Rostedt    if ($buildonly && $lvalue =~ /^TEST_TYPE(\[.*\])?$/ && $prvalue ne "build") {
573bb8474b1SSteven Rostedt	# Note if a test is something other than build, then we
574bb8474b1SSteven Rostedt	# will need other manditory options.
575cad96669SSteven Rostedt	if ($prvalue ne "install") {
576bb8474b1SSteven Rostedt	    $buildonly = 0;
577165708b2SSteven Rostedt	} else {
578165708b2SSteven Rostedt	    # install still limits some manditory options.
579165708b2SSteven Rostedt	    $buildonly = 2;
580165708b2SSteven Rostedt	}
581bb8474b1SSteven Rostedt    }
582bb8474b1SSteven Rostedt
583a75fececSSteven Rostedt    if (defined($opt{$lvalue})) {
5843d1cc414SSteven Rostedt	if (!$override || defined(${$overrides}{$lvalue})) {
5853d1cc414SSteven Rostedt	    my $extra = "";
5863d1cc414SSteven Rostedt	    if ($override) {
5873d1cc414SSteven Rostedt		$extra = "In the same override section!\n";
5883d1cc414SSteven Rostedt	    }
5893d1cc414SSteven Rostedt	    die "$name: $.: Option $lvalue defined more than once!\n$extra";
5903d1cc414SSteven Rostedt	}
591cad96669SSteven Rostedt	${$overrides}{$lvalue} = $prvalue;
592a75fececSSteven Rostedt    }
59321a9679fSSteven Rostedt    if ($rvalue =~ /^\s*$/) {
59421a9679fSSteven Rostedt	delete $opt{$lvalue};
59521a9679fSSteven Rostedt    } else {
596cad96669SSteven Rostedt	$opt{$lvalue} = $prvalue;
59721a9679fSSteven Rostedt    }
5982545eb61SSteven Rostedt}
599a57419b3SSteven Rostedt
60077d942ceSSteven Rostedtsub set_variable {
60177d942ceSSteven Rostedt    my ($lvalue, $rvalue) = @_;
60277d942ceSSteven Rostedt
60377d942ceSSteven Rostedt    if ($rvalue =~ /^\s*$/) {
60477d942ceSSteven Rostedt	delete $variable{$lvalue};
60577d942ceSSteven Rostedt    } else {
60677d942ceSSteven Rostedt	$rvalue = process_variables($rvalue);
60777d942ceSSteven Rostedt	$variable{$lvalue} = $rvalue;
60877d942ceSSteven Rostedt    }
60977d942ceSSteven Rostedt}
61077d942ceSSteven Rostedt
611ab7a3f52SSteven Rostedtsub process_compare {
612ab7a3f52SSteven Rostedt    my ($lval, $cmp, $rval) = @_;
613ab7a3f52SSteven Rostedt
614ab7a3f52SSteven Rostedt    # remove whitespace
615ab7a3f52SSteven Rostedt
616ab7a3f52SSteven Rostedt    $lval =~ s/^\s*//;
617ab7a3f52SSteven Rostedt    $lval =~ s/\s*$//;
618ab7a3f52SSteven Rostedt
619ab7a3f52SSteven Rostedt    $rval =~ s/^\s*//;
620ab7a3f52SSteven Rostedt    $rval =~ s/\s*$//;
621ab7a3f52SSteven Rostedt
622ab7a3f52SSteven Rostedt    if ($cmp eq "==") {
623ab7a3f52SSteven Rostedt	return $lval eq $rval;
624ab7a3f52SSteven Rostedt    } elsif ($cmp eq "!=") {
625ab7a3f52SSteven Rostedt	return $lval ne $rval;
626ab7a3f52SSteven Rostedt    }
627ab7a3f52SSteven Rostedt
628ab7a3f52SSteven Rostedt    my $statement = "$lval $cmp $rval";
629ab7a3f52SSteven Rostedt    my $ret = eval $statement;
630ab7a3f52SSteven Rostedt
631ab7a3f52SSteven Rostedt    # $@ stores error of eval
632ab7a3f52SSteven Rostedt    if ($@) {
633ab7a3f52SSteven Rostedt	return -1;
634ab7a3f52SSteven Rostedt    }
635ab7a3f52SSteven Rostedt
636ab7a3f52SSteven Rostedt    return $ret;
637ab7a3f52SSteven Rostedt}
638ab7a3f52SSteven Rostedt
6399900b5dcSSteven Rostedtsub value_defined {
6409900b5dcSSteven Rostedt    my ($val) = @_;
6419900b5dcSSteven Rostedt
6429900b5dcSSteven Rostedt    return defined($variable{$2}) ||
6439900b5dcSSteven Rostedt	defined($opt{$2});
6449900b5dcSSteven Rostedt}
6459900b5dcSSteven Rostedt
6468d735212SSteven Rostedtmy $d = 0;
6478d735212SSteven Rostedtsub process_expression {
6488d735212SSteven Rostedt    my ($name, $val) = @_;
64945d73a5dSSteven Rostedt
6508d735212SSteven Rostedt    my $c = $d++;
6518d735212SSteven Rostedt
6528d735212SSteven Rostedt    while ($val =~ s/\(([^\(]*?)\)/\&\&\&\&VAL\&\&\&\&/) {
6538d735212SSteven Rostedt	my $express = $1;
6548d735212SSteven Rostedt
6558d735212SSteven Rostedt	if (process_expression($name, $express)) {
6568d735212SSteven Rostedt	    $val =~ s/\&\&\&\&VAL\&\&\&\&/ 1 /;
6578d735212SSteven Rostedt	} else {
6588d735212SSteven Rostedt	    $val =~ s/\&\&\&\&VAL\&\&\&\&/ 0 /;
6598d735212SSteven Rostedt	}
6608d735212SSteven Rostedt    }
6618d735212SSteven Rostedt
6628d735212SSteven Rostedt    $d--;
6638d735212SSteven Rostedt    my $OR = "\\|\\|";
6648d735212SSteven Rostedt    my $AND = "\\&\\&";
6658d735212SSteven Rostedt
6668d735212SSteven Rostedt    while ($val =~ s/^(.*?)($OR|$AND)//) {
6678d735212SSteven Rostedt	my $express = $1;
6688d735212SSteven Rostedt	my $op = $2;
6698d735212SSteven Rostedt
6708d735212SSteven Rostedt	if (process_expression($name, $express)) {
6718d735212SSteven Rostedt	    if ($op eq "||") {
6728d735212SSteven Rostedt		return 1;
6738d735212SSteven Rostedt	    }
6748d735212SSteven Rostedt	} else {
6758d735212SSteven Rostedt	    if ($op eq "&&") {
6768d735212SSteven Rostedt		return 0;
6778d735212SSteven Rostedt	    }
6788d735212SSteven Rostedt	}
6798d735212SSteven Rostedt    }
68045d73a5dSSteven Rostedt
681ab7a3f52SSteven Rostedt    if ($val =~ /(.*)(==|\!=|>=|<=|>|<)(.*)/) {
682ab7a3f52SSteven Rostedt	my $ret = process_compare($1, $2, $3);
683ab7a3f52SSteven Rostedt	if ($ret < 0) {
684ab7a3f52SSteven Rostedt	    die "$name: $.: Unable to process comparison\n";
685ab7a3f52SSteven Rostedt	}
686ab7a3f52SSteven Rostedt	return $ret;
687ab7a3f52SSteven Rostedt    }
688ab7a3f52SSteven Rostedt
6899900b5dcSSteven Rostedt    if ($val =~ /^\s*(NOT\s*)?DEFINED\s+(\S+)\s*$/) {
6909900b5dcSSteven Rostedt	if (defined $1) {
6919900b5dcSSteven Rostedt	    return !value_defined($2);
6929900b5dcSSteven Rostedt	} else {
6939900b5dcSSteven Rostedt	    return value_defined($2);
6949900b5dcSSteven Rostedt	}
6959900b5dcSSteven Rostedt    }
6969900b5dcSSteven Rostedt
69745d73a5dSSteven Rostedt    if ($val =~ /^\s*0\s*$/) {
69845d73a5dSSteven Rostedt	return 0;
69945d73a5dSSteven Rostedt    } elsif ($val =~ /^\s*\d+\s*$/) {
70045d73a5dSSteven Rostedt	return 1;
70145d73a5dSSteven Rostedt    }
70245d73a5dSSteven Rostedt
7039900b5dcSSteven Rostedt    die ("$name: $.: Undefined content $val in if statement\n");
7048d735212SSteven Rostedt}
7058d735212SSteven Rostedt
7068d735212SSteven Rostedtsub process_if {
7078d735212SSteven Rostedt    my ($name, $value) = @_;
7088d735212SSteven Rostedt
7098d735212SSteven Rostedt    # Convert variables and replace undefined ones with 0
7108d735212SSteven Rostedt    my $val = process_variables($value, 1);
7118d735212SSteven Rostedt    my $ret = process_expression $name, $val;
7128d735212SSteven Rostedt
7138d735212SSteven Rostedt    return $ret;
71445d73a5dSSteven Rostedt}
71545d73a5dSSteven Rostedt
7162ed3b161SSteven Rostedtsub __read_config {
7172ed3b161SSteven Rostedt    my ($config, $current_test_num) = @_;
718a57419b3SSteven Rostedt
7192ed3b161SSteven Rostedt    my $in;
7202ed3b161SSteven Rostedt    open($in, $config) || die "can't read file $config";
721a57419b3SSteven Rostedt
722a57419b3SSteven Rostedt    my $name = $config;
723a57419b3SSteven Rostedt    $name =~ s,.*/(.*),$1,;
724a57419b3SSteven Rostedt
7252ed3b161SSteven Rostedt    my $test_num = $$current_test_num;
726a57419b3SSteven Rostedt    my $default = 1;
727a57419b3SSteven Rostedt    my $repeat = 1;
728a57419b3SSteven Rostedt    my $num_tests_set = 0;
729a57419b3SSteven Rostedt    my $skip = 0;
730a57419b3SSteven Rostedt    my $rest;
731a9f84424SSteven Rostedt    my $line;
7320df213caSSteven Rostedt    my $test_case = 0;
73345d73a5dSSteven Rostedt    my $if = 0;
73445d73a5dSSteven Rostedt    my $if_set = 0;
7353d1cc414SSteven Rostedt    my $override = 0;
7363d1cc414SSteven Rostedt
7373d1cc414SSteven Rostedt    my %overrides;
738a57419b3SSteven Rostedt
7392ed3b161SSteven Rostedt    while (<$in>) {
740a57419b3SSteven Rostedt
741a57419b3SSteven Rostedt	# ignore blank lines and comments
742a57419b3SSteven Rostedt	next if (/^\s*$/ || /\s*\#/);
743a57419b3SSteven Rostedt
7440050b6bbSSteven Rostedt	if (/^\s*(TEST_START|DEFAULTS)\b(.*)/) {
745a57419b3SSteven Rostedt
7460050b6bbSSteven Rostedt	    my $type = $1;
7470050b6bbSSteven Rostedt	    $rest = $2;
748a9f84424SSteven Rostedt	    $line = $2;
7490050b6bbSSteven Rostedt
7500050b6bbSSteven Rostedt	    my $old_test_num;
7510050b6bbSSteven Rostedt	    my $old_repeat;
7523d1cc414SSteven Rostedt	    $override = 0;
7530050b6bbSSteven Rostedt
7540050b6bbSSteven Rostedt	    if ($type eq "TEST_START") {
755a57419b3SSteven Rostedt
756a57419b3SSteven Rostedt		if ($num_tests_set) {
757a57419b3SSteven Rostedt		    die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
758a57419b3SSteven Rostedt		}
759a57419b3SSteven Rostedt
7600050b6bbSSteven Rostedt		$old_test_num = $test_num;
7610050b6bbSSteven Rostedt		$old_repeat = $repeat;
762a57419b3SSteven Rostedt
763a57419b3SSteven Rostedt		$test_num += $repeat;
764a57419b3SSteven Rostedt		$default = 0;
765a57419b3SSteven Rostedt		$repeat = 1;
7660050b6bbSSteven Rostedt	    } else {
7670050b6bbSSteven Rostedt		$default = 1;
7680050b6bbSSteven Rostedt	    }
769a57419b3SSteven Rostedt
770a9f84424SSteven Rostedt	    # If SKIP is anywhere in the line, the command will be skipped
771a9f84424SSteven Rostedt	    if ($rest =~ s/\s+SKIP\b//) {
772a57419b3SSteven Rostedt		$skip = 1;
773a57419b3SSteven Rostedt	    } else {
7740df213caSSteven Rostedt		$test_case = 1;
775a57419b3SSteven Rostedt		$skip = 0;
776a57419b3SSteven Rostedt	    }
777a57419b3SSteven Rostedt
778a9f84424SSteven Rostedt	    if ($rest =~ s/\sELSE\b//) {
779a9f84424SSteven Rostedt		if (!$if) {
780a9f84424SSteven Rostedt		    die "$name: $.: ELSE found with out matching IF section\n$_";
781a57419b3SSteven Rostedt		}
782a9f84424SSteven Rostedt		$if = 0;
783a9f84424SSteven Rostedt
784a9f84424SSteven Rostedt		if ($if_set) {
785a9f84424SSteven Rostedt		    $skip = 1;
786a9f84424SSteven Rostedt		} else {
787a9f84424SSteven Rostedt		    $skip = 0;
7883d1cc414SSteven Rostedt		}
7893d1cc414SSteven Rostedt	    }
790a57419b3SSteven Rostedt
791a9f84424SSteven Rostedt	    if ($rest =~ s/\sIF\s+(.*)//) {
79245d73a5dSSteven Rostedt		if (process_if($name, $1)) {
79345d73a5dSSteven Rostedt		    $if_set = 1;
79445d73a5dSSteven Rostedt		} else {
795a57419b3SSteven Rostedt		    $skip = 1;
796a57419b3SSteven Rostedt		}
79745d73a5dSSteven Rostedt		$if = 1;
79845d73a5dSSteven Rostedt	    } else {
79945d73a5dSSteven Rostedt		$if = 0;
800a9f84424SSteven Rostedt		$if_set = 0;
80145d73a5dSSteven Rostedt	    }
802a57419b3SSteven Rostedt
803a9f84424SSteven Rostedt	    if (!$skip) {
804a9f84424SSteven Rostedt		if ($type eq "TEST_START") {
805a9f84424SSteven Rostedt		    if ($rest =~ s/\s+ITERATE\s+(\d+)//) {
806a9f84424SSteven Rostedt			$repeat = $1;
807a9f84424SSteven Rostedt			$repeat_tests{"$test_num"} = $repeat;
808a9f84424SSteven Rostedt		    }
809a9f84424SSteven Rostedt		} elsif ($rest =~ s/\sOVERRIDE\b//) {
810a9f84424SSteven Rostedt		    # DEFAULT only
811a9f84424SSteven Rostedt		    $override = 1;
812a9f84424SSteven Rostedt		    # Clear previous overrides
813a9f84424SSteven Rostedt		    %overrides = ();
814a9f84424SSteven Rostedt		}
815a9f84424SSteven Rostedt	    }
816a9f84424SSteven Rostedt
817a9f84424SSteven Rostedt	    if (!$skip && $rest !~ /^\s*$/) {
8180050b6bbSSteven Rostedt		die "$name: $.: Gargbage found after $type\n$_";
819a57419b3SSteven Rostedt	    }
820a57419b3SSteven Rostedt
8210050b6bbSSteven Rostedt	    if ($skip && $type eq "TEST_START") {
822a57419b3SSteven Rostedt		$test_num = $old_test_num;
823e48c5293SSteven Rostedt		$repeat = $old_repeat;
824a57419b3SSteven Rostedt	    }
825a57419b3SSteven Rostedt
826ab7a3f52SSteven Rostedt	} elsif (/^\s*ELSE\b(.*)$/) {
82745d73a5dSSteven Rostedt	    if (!$if) {
82845d73a5dSSteven Rostedt		die "$name: $.: ELSE found with out matching IF section\n$_";
82945d73a5dSSteven Rostedt	    }
83045d73a5dSSteven Rostedt	    $rest = $1;
83145d73a5dSSteven Rostedt	    if ($if_set) {
83245d73a5dSSteven Rostedt		$skip = 1;
833ab7a3f52SSteven Rostedt		$rest = "";
83445d73a5dSSteven Rostedt	    } else {
83545d73a5dSSteven Rostedt		$skip = 0;
83645d73a5dSSteven Rostedt
837ab7a3f52SSteven Rostedt		if ($rest =~ /\sIF\s+(.*)/) {
83845d73a5dSSteven Rostedt		    # May be a ELSE IF section.
83945d73a5dSSteven Rostedt		    if (!process_if($name, $1)) {
84045d73a5dSSteven Rostedt			$skip = 1;
84145d73a5dSSteven Rostedt		    }
842ab7a3f52SSteven Rostedt		    $rest = "";
84345d73a5dSSteven Rostedt		} else {
84445d73a5dSSteven Rostedt		    $if = 0;
84545d73a5dSSteven Rostedt		}
84645d73a5dSSteven Rostedt	    }
84745d73a5dSSteven Rostedt
848ab7a3f52SSteven Rostedt	    if ($rest !~ /^\s*$/) {
849ab7a3f52SSteven Rostedt		die "$name: $.: Gargbage found after DEFAULTS\n$_";
850ab7a3f52SSteven Rostedt	    }
851ab7a3f52SSteven Rostedt
8522ed3b161SSteven Rostedt	} elsif (/^\s*INCLUDE\s+(\S+)/) {
8532ed3b161SSteven Rostedt
8542ed3b161SSteven Rostedt	    next if ($skip);
8552ed3b161SSteven Rostedt
8562ed3b161SSteven Rostedt	    if (!$default) {
8572ed3b161SSteven Rostedt		die "$name: $.: INCLUDE can only be done in default sections\n$_";
8582ed3b161SSteven Rostedt	    }
8592ed3b161SSteven Rostedt
8602ed3b161SSteven Rostedt	    my $file = process_variables($1);
8612ed3b161SSteven Rostedt
8622ed3b161SSteven Rostedt	    if ($file !~ m,^/,) {
8632ed3b161SSteven Rostedt		# check the path of the config file first
8642ed3b161SSteven Rostedt		if ($config =~ m,(.*)/,) {
8652ed3b161SSteven Rostedt		    if (-f "$1/$file") {
8662ed3b161SSteven Rostedt			$file = "$1/$file";
8672ed3b161SSteven Rostedt		    }
8682ed3b161SSteven Rostedt		}
8692ed3b161SSteven Rostedt	    }
8702ed3b161SSteven Rostedt
8712ed3b161SSteven Rostedt	    if ( ! -r $file ) {
8722ed3b161SSteven Rostedt		die "$name: $.: Can't read file $file\n$_";
8732ed3b161SSteven Rostedt	    }
8742ed3b161SSteven Rostedt
8752ed3b161SSteven Rostedt	    if (__read_config($file, \$test_num)) {
8762ed3b161SSteven Rostedt		$test_case = 1;
8772ed3b161SSteven Rostedt	    }
8782ed3b161SSteven Rostedt
879a57419b3SSteven Rostedt	} elsif (/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) {
880a57419b3SSteven Rostedt
881a57419b3SSteven Rostedt	    next if ($skip);
882a57419b3SSteven Rostedt
883a57419b3SSteven Rostedt	    my $lvalue = $1;
884a57419b3SSteven Rostedt	    my $rvalue = $2;
885a57419b3SSteven Rostedt
886a57419b3SSteven Rostedt	    if (!$default &&
887a57419b3SSteven Rostedt		($lvalue eq "NUM_TESTS" ||
888a57419b3SSteven Rostedt		 $lvalue eq "LOG_FILE" ||
889a57419b3SSteven Rostedt		 $lvalue eq "CLEAR_LOG")) {
890a57419b3SSteven Rostedt		die "$name: $.: $lvalue must be set in DEFAULTS section\n";
891a57419b3SSteven Rostedt	    }
892a57419b3SSteven Rostedt
893a57419b3SSteven Rostedt	    if ($lvalue eq "NUM_TESTS") {
894a57419b3SSteven Rostedt		if ($test_num) {
895a57419b3SSteven Rostedt		    die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
896a57419b3SSteven Rostedt		}
897a57419b3SSteven Rostedt		if (!$default) {
898a57419b3SSteven Rostedt		    die "$name: $.: NUM_TESTS must be set in default section\n";
899a57419b3SSteven Rostedt		}
900a57419b3SSteven Rostedt		$num_tests_set = 1;
901a57419b3SSteven Rostedt	    }
902a57419b3SSteven Rostedt
903a57419b3SSteven Rostedt	    if ($default || $lvalue =~ /\[\d+\]$/) {
9043d1cc414SSteven Rostedt		set_value($lvalue, $rvalue, $override, \%overrides, $name);
905a57419b3SSteven Rostedt	    } else {
906a57419b3SSteven Rostedt		my $val = "$lvalue\[$test_num\]";
9073d1cc414SSteven Rostedt		set_value($val, $rvalue, $override, \%overrides, $name);
908a57419b3SSteven Rostedt
909a57419b3SSteven Rostedt		if ($repeat > 1) {
910a57419b3SSteven Rostedt		    $repeats{$val} = $repeat;
911a57419b3SSteven Rostedt		}
912a57419b3SSteven Rostedt	    }
91377d942ceSSteven Rostedt	} elsif (/^\s*([A-Z_\[\]\d]+)\s*:=\s*(.*?)\s*$/) {
91477d942ceSSteven Rostedt	    next if ($skip);
91577d942ceSSteven Rostedt
91677d942ceSSteven Rostedt	    my $lvalue = $1;
91777d942ceSSteven Rostedt	    my $rvalue = $2;
91877d942ceSSteven Rostedt
91977d942ceSSteven Rostedt	    # process config variables.
92077d942ceSSteven Rostedt	    # Config variables are only active while reading the
92177d942ceSSteven Rostedt	    # config and can be defined anywhere. They also ignore
92277d942ceSSteven Rostedt	    # TEST_START and DEFAULTS, but are skipped if they are in
92377d942ceSSteven Rostedt	    # on of these sections that have SKIP defined.
92477d942ceSSteven Rostedt	    # The save variable can be
92577d942ceSSteven Rostedt	    # defined multiple times and the new one simply overrides
92677d942ceSSteven Rostedt	    # the prevous one.
92777d942ceSSteven Rostedt	    set_variable($lvalue, $rvalue);
92877d942ceSSteven Rostedt
929a57419b3SSteven Rostedt	} else {
930a57419b3SSteven Rostedt	    die "$name: $.: Garbage found in config\n$_";
931a57419b3SSteven Rostedt	}
9322545eb61SSteven Rostedt    }
9332545eb61SSteven Rostedt
934a57419b3SSteven Rostedt    if ($test_num) {
935a57419b3SSteven Rostedt	$test_num += $repeat - 1;
936a57419b3SSteven Rostedt	$opt{"NUM_TESTS"} = $test_num;
937a57419b3SSteven Rostedt    }
938a57419b3SSteven Rostedt
9392ed3b161SSteven Rostedt    close($in);
9402ed3b161SSteven Rostedt
9412ed3b161SSteven Rostedt    $$current_test_num = $test_num;
9422ed3b161SSteven Rostedt
9432ed3b161SSteven Rostedt    return $test_case;
9442ed3b161SSteven Rostedt}
9452ed3b161SSteven Rostedt
946c4261d0fSSteven Rostedtsub get_test_case {
947c4261d0fSSteven Rostedt	print "What test case would you like to run?\n";
948c4261d0fSSteven Rostedt	print " (build, install or boot)\n";
949c4261d0fSSteven Rostedt	print " Other tests are available but require editing the config file\n";
950c4261d0fSSteven Rostedt	my $ans = <STDIN>;
951c4261d0fSSteven Rostedt	chomp $ans;
952c4261d0fSSteven Rostedt	$default{"TEST_TYPE"} = $ans;
953c4261d0fSSteven Rostedt}
954c4261d0fSSteven Rostedt
9552ed3b161SSteven Rostedtsub read_config {
9562ed3b161SSteven Rostedt    my ($config) = @_;
9572ed3b161SSteven Rostedt
9582ed3b161SSteven Rostedt    my $test_case;
9592ed3b161SSteven Rostedt    my $test_num = 0;
9602ed3b161SSteven Rostedt
9612ed3b161SSteven Rostedt    $test_case = __read_config $config, \$test_num;
9622ed3b161SSteven Rostedt
9638d1491baSSteven Rostedt    # make sure we have all mandatory configs
9648d1491baSSteven Rostedt    get_ktest_configs;
9658d1491baSSteven Rostedt
9660df213caSSteven Rostedt    # was a test specified?
9670df213caSSteven Rostedt    if (!$test_case) {
9680df213caSSteven Rostedt	print "No test case specified.\n";
969c4261d0fSSteven Rostedt	get_test_case;
9700df213caSSteven Rostedt    }
9710df213caSSteven Rostedt
972a75fececSSteven Rostedt    # set any defaults
973a75fececSSteven Rostedt
974a75fececSSteven Rostedt    foreach my $default (keys %default) {
975a75fececSSteven Rostedt	if (!defined($opt{$default})) {
976a75fececSSteven Rostedt	    $opt{$default} = $default{$default};
977a75fececSSteven Rostedt	}
978a75fececSSteven Rostedt    }
9799cc9e091SSteven Rostedt
9809cc9e091SSteven Rostedt    if ($opt{"IGNORE_UNUSED"} == 1) {
9819cc9e091SSteven Rostedt	return;
9829cc9e091SSteven Rostedt    }
9839cc9e091SSteven Rostedt
9849cc9e091SSteven Rostedt    my %not_used;
9859cc9e091SSteven Rostedt
9869cc9e091SSteven Rostedt    # check if there are any stragglers (typos?)
9879cc9e091SSteven Rostedt    foreach my $option (keys %opt) {
9889cc9e091SSteven Rostedt	my $op = $option;
9899cc9e091SSteven Rostedt	# remove per test labels.
9909cc9e091SSteven Rostedt	$op =~ s/\[.*\]//;
9919cc9e091SSteven Rostedt	if (!exists($option_map{$op}) &&
9929cc9e091SSteven Rostedt	    !exists($default{$op}) &&
9939cc9e091SSteven Rostedt	    !exists($used_options{$op})) {
9949cc9e091SSteven Rostedt	    $not_used{$op} = 1;
9959cc9e091SSteven Rostedt	}
9969cc9e091SSteven Rostedt    }
9979cc9e091SSteven Rostedt
9989cc9e091SSteven Rostedt    if (%not_used) {
9999cc9e091SSteven Rostedt	my $s = "s are";
10009cc9e091SSteven Rostedt	$s = " is" if (keys %not_used == 1);
10019cc9e091SSteven Rostedt	print "The following option$s not used; could be a typo:\n";
10029cc9e091SSteven Rostedt	foreach my $option (keys %not_used) {
10039cc9e091SSteven Rostedt	    print "$option\n";
10049cc9e091SSteven Rostedt	}
10059cc9e091SSteven Rostedt	print "Set IGRNORE_UNUSED = 1 to have ktest ignore unused variables\n";
10069cc9e091SSteven Rostedt	if (!read_yn "Do you want to continue?") {
10079cc9e091SSteven Rostedt	    exit -1;
10089cc9e091SSteven Rostedt	}
10099cc9e091SSteven Rostedt    }
10102545eb61SSteven Rostedt}
10112545eb61SSteven Rostedt
101223715c3cSSteven Rostedtsub __eval_option {
101323715c3cSSteven Rostedt    my ($option, $i) = @_;
101423715c3cSSteven Rostedt
101523715c3cSSteven Rostedt    # Add space to evaluate the character before $
101623715c3cSSteven Rostedt    $option = " $option";
101723715c3cSSteven Rostedt    my $retval = "";
1018f9dfb65bSRabin Vincent    my $repeated = 0;
1019f9dfb65bSRabin Vincent    my $parent = 0;
1020f9dfb65bSRabin Vincent
1021f9dfb65bSRabin Vincent    foreach my $test (keys %repeat_tests) {
1022f9dfb65bSRabin Vincent	if ($i >= $test &&
1023f9dfb65bSRabin Vincent	    $i < $test + $repeat_tests{$test}) {
1024f9dfb65bSRabin Vincent
1025f9dfb65bSRabin Vincent	    $repeated = 1;
1026f9dfb65bSRabin Vincent	    $parent = $test;
1027f9dfb65bSRabin Vincent	    last;
1028f9dfb65bSRabin Vincent	}
1029f9dfb65bSRabin Vincent    }
103023715c3cSSteven Rostedt
103123715c3cSSteven Rostedt    while ($option =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) {
103223715c3cSSteven Rostedt	my $start = $1;
103323715c3cSSteven Rostedt	my $var = $2;
103423715c3cSSteven Rostedt	my $end = $3;
103523715c3cSSteven Rostedt
103623715c3cSSteven Rostedt	# Append beginning of line
103723715c3cSSteven Rostedt	$retval = "$retval$start";
103823715c3cSSteven Rostedt
103923715c3cSSteven Rostedt	# If the iteration option OPT[$i] exists, then use that.
104023715c3cSSteven Rostedt	# otherwise see if the default OPT (without [$i]) exists.
104123715c3cSSteven Rostedt
104223715c3cSSteven Rostedt	my $o = "$var\[$i\]";
1043f9dfb65bSRabin Vincent	my $parento = "$var\[$parent\]";
104423715c3cSSteven Rostedt
104523715c3cSSteven Rostedt	if (defined($opt{$o})) {
104623715c3cSSteven Rostedt	    $o = $opt{$o};
104723715c3cSSteven Rostedt	    $retval = "$retval$o";
1048f9dfb65bSRabin Vincent	} elsif ($repeated && defined($opt{$parento})) {
1049f9dfb65bSRabin Vincent	    $o = $opt{$parento};
1050f9dfb65bSRabin Vincent	    $retval = "$retval$o";
105123715c3cSSteven Rostedt	} elsif (defined($opt{$var})) {
105223715c3cSSteven Rostedt	    $o = $opt{$var};
105323715c3cSSteven Rostedt	    $retval = "$retval$o";
105423715c3cSSteven Rostedt	} else {
105523715c3cSSteven Rostedt	    $retval = "$retval\$\{$var\}";
105623715c3cSSteven Rostedt	}
105723715c3cSSteven Rostedt
105823715c3cSSteven Rostedt	$option = $end;
105923715c3cSSteven Rostedt    }
106023715c3cSSteven Rostedt
106123715c3cSSteven Rostedt    $retval = "$retval$option";
106223715c3cSSteven Rostedt
106323715c3cSSteven Rostedt    $retval =~ s/^ //;
106423715c3cSSteven Rostedt
106523715c3cSSteven Rostedt    return $retval;
106623715c3cSSteven Rostedt}
106723715c3cSSteven Rostedt
106823715c3cSSteven Rostedtsub eval_option {
106923715c3cSSteven Rostedt    my ($option, $i) = @_;
107023715c3cSSteven Rostedt
107123715c3cSSteven Rostedt    my $prev = "";
107223715c3cSSteven Rostedt
107323715c3cSSteven Rostedt    # Since an option can evaluate to another option,
107423715c3cSSteven Rostedt    # keep iterating until we do not evaluate any more
107523715c3cSSteven Rostedt    # options.
107623715c3cSSteven Rostedt    my $r = 0;
107723715c3cSSteven Rostedt    while ($prev ne $option) {
107823715c3cSSteven Rostedt	# Check for recursive evaluations.
107923715c3cSSteven Rostedt	# 100 deep should be more than enough.
108023715c3cSSteven Rostedt	if ($r++ > 100) {
108123715c3cSSteven Rostedt	    die "Over 100 evaluations accurred with $option\n" .
108223715c3cSSteven Rostedt		"Check for recursive variables\n";
108323715c3cSSteven Rostedt	}
108423715c3cSSteven Rostedt	$prev = $option;
108523715c3cSSteven Rostedt	$option = __eval_option($option, $i);
108623715c3cSSteven Rostedt    }
108723715c3cSSteven Rostedt
108823715c3cSSteven Rostedt    return $option;
108923715c3cSSteven Rostedt}
109023715c3cSSteven Rostedt
1091d1e2f22aSSteven Rostedtsub _logit {
10922545eb61SSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
10932545eb61SSteven Rostedt	open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}";
10942545eb61SSteven Rostedt	print OUT @_;
10952545eb61SSteven Rostedt	close(OUT);
10962545eb61SSteven Rostedt    }
10972545eb61SSteven Rostedt}
10982545eb61SSteven Rostedt
1099d1e2f22aSSteven Rostedtsub logit {
1100d1e2f22aSSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
1101d1e2f22aSSteven Rostedt	_logit @_;
1102d1e2f22aSSteven Rostedt    } else {
1103d1e2f22aSSteven Rostedt	print @_;
1104d1e2f22aSSteven Rostedt    }
1105d1e2f22aSSteven Rostedt}
1106d1e2f22aSSteven Rostedt
11075f9b6cedSSteven Rostedtsub doprint {
11085f9b6cedSSteven Rostedt    print @_;
1109d1e2f22aSSteven Rostedt    _logit @_;
11105f9b6cedSSteven Rostedt}
11115f9b6cedSSteven Rostedt
11127faafbd6SSteven Rostedtsub run_command;
11132728be41SAndrew Jonessub start_monitor;
11142728be41SAndrew Jonessub end_monitor;
11152728be41SAndrew Jonessub wait_for_monitor;
11167faafbd6SSteven Rostedt
11177faafbd6SSteven Rostedtsub reboot {
11182728be41SAndrew Jones    my ($time) = @_;
11192728be41SAndrew Jones
11202b803365SSteven Rostedt    if (defined($time)) {
11212b803365SSteven Rostedt	start_monitor;
11222b803365SSteven Rostedt	# flush out current monitor
11232b803365SSteven Rostedt	# May contain the reboot success line
11242b803365SSteven Rostedt	wait_for_monitor 1;
11252b803365SSteven Rostedt    }
11262b803365SSteven Rostedt
11277faafbd6SSteven Rostedt    # try to reboot normally
1128e48c5293SSteven Rostedt    if (run_command $reboot) {
1129576f627cSSteven Rostedt	if (defined($powercycle_after_reboot)) {
1130576f627cSSteven Rostedt	    sleep $powercycle_after_reboot;
1131576f627cSSteven Rostedt	    run_command "$power_cycle";
1132576f627cSSteven Rostedt	}
1133576f627cSSteven Rostedt    } else {
11347faafbd6SSteven Rostedt	# nope? power cycle it.
1135a75fececSSteven Rostedt	run_command "$power_cycle";
11367faafbd6SSteven Rostedt    }
11372728be41SAndrew Jones
11382728be41SAndrew Jones    if (defined($time)) {
1139407b95b7SSteven Rostedt	if (wait_for_monitor($time, $reboot_success_line)) {
1140407b95b7SSteven Rostedt	    # reboot got stuck?
11418a80c727SSteven Rostedt	    doprint "Reboot did not finish. Forcing power cycle\n";
1142407b95b7SSteven Rostedt	    run_command "$power_cycle";
1143407b95b7SSteven Rostedt	}
11442728be41SAndrew Jones	end_monitor;
11452728be41SAndrew Jones    }
11467faafbd6SSteven Rostedt}
11477faafbd6SSteven Rostedt
1148bc7c5803SSteven Rostedtsub reboot_to_good {
1149bc7c5803SSteven Rostedt    my ($time) = @_;
1150bc7c5803SSteven Rostedt
1151bc7c5803SSteven Rostedt    if (defined($switch_to_good)) {
1152bc7c5803SSteven Rostedt	run_command $switch_to_good;
1153bc7c5803SSteven Rostedt    }
1154bc7c5803SSteven Rostedt
1155bc7c5803SSteven Rostedt    reboot $time;
1156bc7c5803SSteven Rostedt}
1157bc7c5803SSteven Rostedt
1158576f627cSSteven Rostedtsub do_not_reboot {
1159576f627cSSteven Rostedt    my $i = $iteration;
1160576f627cSSteven Rostedt
11614ab1cce5SSteven Rostedt    return $test_type eq "build" || $no_reboot ||
1162576f627cSSteven Rostedt	($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") ||
1163576f627cSSteven Rostedt	($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build");
1164576f627cSSteven Rostedt}
1165576f627cSSteven Rostedt
11665c42fc5bSSteven Rostedtsub dodie {
11675a391fbfSSteven Rostedt    doprint "CRITICAL FAILURE... ", @_, "\n";
11685c42fc5bSSteven Rostedt
1169576f627cSSteven Rostedt    my $i = $iteration;
1170576f627cSSteven Rostedt
1171576f627cSSteven Rostedt    if ($reboot_on_error && !do_not_reboot) {
1172576f627cSSteven Rostedt
117375c3fda7SSteven Rostedt	doprint "REBOOTING\n";
1174bc7c5803SSteven Rostedt	reboot_to_good;
117575c3fda7SSteven Rostedt
1176a75fececSSteven Rostedt    } elsif ($poweroff_on_error && defined($power_off)) {
11775c42fc5bSSteven Rostedt	doprint "POWERING OFF\n";
1178a75fececSSteven Rostedt	`$power_off`;
11795c42fc5bSSteven Rostedt    }
118075c3fda7SSteven Rostedt
1181f80802cbSSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
1182f80802cbSSteven Rostedt	print " See $opt{LOG_FILE} for more info.\n";
1183f80802cbSSteven Rostedt    }
1184f80802cbSSteven Rostedt
1185576f627cSSteven Rostedt    die @_, "\n";
11865c42fc5bSSteven Rostedt}
11875c42fc5bSSteven Rostedt
11887faafbd6SSteven Rostedtsub open_console {
11897faafbd6SSteven Rostedt    my ($fp) = @_;
11907faafbd6SSteven Rostedt
11917faafbd6SSteven Rostedt    my $flags;
11927faafbd6SSteven Rostedt
1193a75fececSSteven Rostedt    my $pid = open($fp, "$console|") or
1194a75fececSSteven Rostedt	dodie "Can't open console $console";
11957faafbd6SSteven Rostedt
11967faafbd6SSteven Rostedt    $flags = fcntl($fp, F_GETFL, 0) or
1197576f627cSSteven Rostedt	dodie "Can't get flags for the socket: $!";
11987faafbd6SSteven Rostedt    $flags = fcntl($fp, F_SETFL, $flags | O_NONBLOCK) or
1199576f627cSSteven Rostedt	dodie "Can't set flags for the socket: $!";
12007faafbd6SSteven Rostedt
12017faafbd6SSteven Rostedt    return $pid;
12027faafbd6SSteven Rostedt}
12037faafbd6SSteven Rostedt
12047faafbd6SSteven Rostedtsub close_console {
12057faafbd6SSteven Rostedt    my ($fp, $pid) = @_;
12067faafbd6SSteven Rostedt
12077faafbd6SSteven Rostedt    doprint "kill child process $pid\n";
12087faafbd6SSteven Rostedt    kill 2, $pid;
12097faafbd6SSteven Rostedt
12107faafbd6SSteven Rostedt    print "closing!\n";
12117faafbd6SSteven Rostedt    close($fp);
12127faafbd6SSteven Rostedt}
12137faafbd6SSteven Rostedt
12147faafbd6SSteven Rostedtsub start_monitor {
12157faafbd6SSteven Rostedt    if ($monitor_cnt++) {
12167faafbd6SSteven Rostedt	return;
12177faafbd6SSteven Rostedt    }
12187faafbd6SSteven Rostedt    $monitor_fp = \*MONFD;
12197faafbd6SSteven Rostedt    $monitor_pid = open_console $monitor_fp;
1220a75fececSSteven Rostedt
1221a75fececSSteven Rostedt    return;
1222a75fececSSteven Rostedt
1223a75fececSSteven Rostedt    open(MONFD, "Stop perl from warning about single use of MONFD");
12247faafbd6SSteven Rostedt}
12257faafbd6SSteven Rostedt
12267faafbd6SSteven Rostedtsub end_monitor {
12277faafbd6SSteven Rostedt    if (--$monitor_cnt) {
12287faafbd6SSteven Rostedt	return;
12297faafbd6SSteven Rostedt    }
12307faafbd6SSteven Rostedt    close_console($monitor_fp, $monitor_pid);
12317faafbd6SSteven Rostedt}
12327faafbd6SSteven Rostedt
12337faafbd6SSteven Rostedtsub wait_for_monitor {
12342b803365SSteven Rostedt    my ($time, $stop) = @_;
12352b803365SSteven Rostedt    my $full_line = "";
12367faafbd6SSteven Rostedt    my $line;
12372b803365SSteven Rostedt    my $booted = 0;
1238407b95b7SSteven Rostedt    my $start_time = time;
12398a80c727SSteven Rostedt    my $skip_call_trace = 0;
12408a80c727SSteven Rostedt    my $bug = 0;
12418a80c727SSteven Rostedt    my $bug_ignored = 0;
1242407b95b7SSteven Rostedt    my $now;
12437faafbd6SSteven Rostedt
1244a75fececSSteven Rostedt    doprint "** Wait for monitor to settle down **\n";
12457faafbd6SSteven Rostedt
12467faafbd6SSteven Rostedt    # read the monitor and wait for the system to calm down
12472b803365SSteven Rostedt    while (!$booted) {
12487faafbd6SSteven Rostedt	$line = wait_for_input($monitor_fp, $time);
12492b803365SSteven Rostedt	last if (!defined($line));
12502b803365SSteven Rostedt	print "$line";
12512b803365SSteven Rostedt	$full_line .= $line;
12522b803365SSteven Rostedt
12532b803365SSteven Rostedt	if (defined($stop) && $full_line =~ /$stop/) {
12542b803365SSteven Rostedt	    doprint "wait for monitor detected $stop\n";
12552b803365SSteven Rostedt	    $booted = 1;
12562b803365SSteven Rostedt	}
12572b803365SSteven Rostedt
12588a80c727SSteven Rostedt	if ($full_line =~ /\[ backtrace testing \]/) {
12598a80c727SSteven Rostedt	    $skip_call_trace = 1;
12608a80c727SSteven Rostedt	}
12618a80c727SSteven Rostedt
12628a80c727SSteven Rostedt	if ($full_line =~ /call trace:/i) {
12638a80c727SSteven Rostedt	    if (!$bug && !$skip_call_trace) {
12648a80c727SSteven Rostedt		if ($ignore_errors) {
12658a80c727SSteven Rostedt		    $bug_ignored = 1;
12668a80c727SSteven Rostedt		} else {
12678a80c727SSteven Rostedt		    $bug = 1;
12688a80c727SSteven Rostedt		}
12698a80c727SSteven Rostedt	    }
12708a80c727SSteven Rostedt	}
12718a80c727SSteven Rostedt
12728a80c727SSteven Rostedt	if ($full_line =~ /\[ end of backtrace testing \]/) {
12738a80c727SSteven Rostedt	    $skip_call_trace = 0;
12748a80c727SSteven Rostedt	}
12758a80c727SSteven Rostedt
12768a80c727SSteven Rostedt	if ($full_line =~ /Kernel panic -/) {
12778a80c727SSteven Rostedt	    $bug = 1;
12788a80c727SSteven Rostedt	}
12798a80c727SSteven Rostedt
12802b803365SSteven Rostedt	if ($line =~ /\n/) {
12812b803365SSteven Rostedt	    $full_line = "";
12822b803365SSteven Rostedt	}
1283407b95b7SSteven Rostedt	$now = time;
1284407b95b7SSteven Rostedt	if ($now - $start_time >= $max_monitor_wait) {
1285407b95b7SSteven Rostedt	    doprint "Exiting monitor flush due to hitting MAX_MONITOR_WAIT\n";
1286407b95b7SSteven Rostedt	    return 1;
1287407b95b7SSteven Rostedt	}
12882b803365SSteven Rostedt    }
1289a75fececSSteven Rostedt    print "** Monitor flushed **\n";
12908a80c727SSteven Rostedt    return $bug;
12917faafbd6SSteven Rostedt}
12927faafbd6SSteven Rostedt
1293de5b6e3bSRabin Vincentsub save_logs {
1294de5b6e3bSRabin Vincent	my ($result, $basedir) = @_;
1295de5b6e3bSRabin Vincent	my @t = localtime;
1296de5b6e3bSRabin Vincent	my $date = sprintf "%04d%02d%02d%02d%02d%02d",
1297de5b6e3bSRabin Vincent		1900+$t[5],$t[4],$t[3],$t[2],$t[1],$t[0];
1298de5b6e3bSRabin Vincent
1299de5b6e3bSRabin Vincent	my $type = $build_type;
1300de5b6e3bSRabin Vincent	if ($type =~ /useconfig/) {
1301de5b6e3bSRabin Vincent	    $type = "useconfig";
1302de5b6e3bSRabin Vincent	}
1303de5b6e3bSRabin Vincent
1304de5b6e3bSRabin Vincent	my $dir = "$machine-$test_type-$type-$result-$date";
1305de5b6e3bSRabin Vincent
1306de5b6e3bSRabin Vincent	$dir = "$basedir/$dir";
1307de5b6e3bSRabin Vincent
1308de5b6e3bSRabin Vincent	if (!-d $dir) {
1309de5b6e3bSRabin Vincent	    mkpath($dir) or
1310de5b6e3bSRabin Vincent		die "can't create $dir";
1311de5b6e3bSRabin Vincent	}
1312de5b6e3bSRabin Vincent
1313de5b6e3bSRabin Vincent	my %files = (
1314de5b6e3bSRabin Vincent		"config" => $output_config,
1315de5b6e3bSRabin Vincent		"buildlog" => $buildlog,
1316de5b6e3bSRabin Vincent		"dmesg" => $dmesg,
1317de5b6e3bSRabin Vincent		"testlog" => $testlog,
1318de5b6e3bSRabin Vincent	);
1319de5b6e3bSRabin Vincent
1320de5b6e3bSRabin Vincent	while (my ($name, $source) = each(%files)) {
1321de5b6e3bSRabin Vincent		if (-f "$source") {
1322de5b6e3bSRabin Vincent			cp "$source", "$dir/$name" or
1323de5b6e3bSRabin Vincent				die "failed to copy $source";
1324de5b6e3bSRabin Vincent		}
1325de5b6e3bSRabin Vincent	}
1326de5b6e3bSRabin Vincent
1327de5b6e3bSRabin Vincent	doprint "*** Saved info to $dir ***\n";
1328de5b6e3bSRabin Vincent}
1329de5b6e3bSRabin Vincent
13302b7d9b21SSteven Rostedtsub fail {
13312b7d9b21SSteven Rostedt
1332921ed4c7SSteven Rostedt	if (defined($post_test)) {
1333921ed4c7SSteven Rostedt		run_command $post_test;
1334921ed4c7SSteven Rostedt	}
1335921ed4c7SSteven Rostedt
1336a75fececSSteven Rostedt	if ($die_on_failure) {
13372b7d9b21SSteven Rostedt		dodie @_;
13382b7d9b21SSteven Rostedt	}
13392b7d9b21SSteven Rostedt
1340a75fececSSteven Rostedt	doprint "FAILED\n";
13417faafbd6SSteven Rostedt
1342576f627cSSteven Rostedt	my $i = $iteration;
1343576f627cSSteven Rostedt
1344a75fececSSteven Rostedt	# no need to reboot for just building.
1345576f627cSSteven Rostedt	if (!do_not_reboot) {
13467faafbd6SSteven Rostedt	    doprint "REBOOTING\n";
1347bc7c5803SSteven Rostedt	    reboot_to_good $sleep_time;
1348a75fececSSteven Rostedt	}
13497faafbd6SSteven Rostedt
13509064af52SSteven Rostedt	my $name = "";
13519064af52SSteven Rostedt
13529064af52SSteven Rostedt	if (defined($test_name)) {
13539064af52SSteven Rostedt	    $name = " ($test_name)";
13549064af52SSteven Rostedt	}
13559064af52SSteven Rostedt
1356576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
1357576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
13589064af52SSteven Rostedt	doprint "KTEST RESULT: TEST $i$name Failed: ", @_, "\n";
1359576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
1360576f627cSSteven Rostedt	doprint "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n";
1361a75fececSSteven Rostedt
1362de5b6e3bSRabin Vincent	if (defined($store_failures)) {
1363de5b6e3bSRabin Vincent	    save_logs "fail", $store_failures;
1364cccae1a6SSteven Rostedt        }
1365cccae1a6SSteven Rostedt
13662b7d9b21SSteven Rostedt	return 1;
13672b7d9b21SSteven Rostedt}
13682b7d9b21SSteven Rostedt
13692545eb61SSteven Rostedtsub run_command {
13702545eb61SSteven Rostedt    my ($command) = @_;
1371d6ce2a0bSSteven Rostedt    my $dolog = 0;
1372d6ce2a0bSSteven Rostedt    my $dord = 0;
1373d6ce2a0bSSteven Rostedt    my $pid;
1374d6ce2a0bSSteven Rostedt
1375e48c5293SSteven Rostedt    $command =~ s/\$SSH_USER/$ssh_user/g;
1376e48c5293SSteven Rostedt    $command =~ s/\$MACHINE/$machine/g;
1377e48c5293SSteven Rostedt
1378d6ce2a0bSSteven Rostedt    doprint("$command ... ");
1379d6ce2a0bSSteven Rostedt
1380d6ce2a0bSSteven Rostedt    $pid = open(CMD, "$command 2>&1 |") or
13812b7d9b21SSteven Rostedt	(fail "unable to exec $command" and return 0);
13822545eb61SSteven Rostedt
13832545eb61SSteven Rostedt    if (defined($opt{"LOG_FILE"})) {
1384d6ce2a0bSSteven Rostedt	open(LOG, ">>$opt{LOG_FILE}") or
1385d6ce2a0bSSteven Rostedt	    dodie "failed to write to log";
1386d6ce2a0bSSteven Rostedt	$dolog = 1;
13876c5ee0beSSteven Rostedt    }
13886c5ee0beSSteven Rostedt
13896c5ee0beSSteven Rostedt    if (defined($redirect)) {
1390d6ce2a0bSSteven Rostedt	open (RD, ">$redirect") or
1391d6ce2a0bSSteven Rostedt	    dodie "failed to write to redirect $redirect";
1392d6ce2a0bSSteven Rostedt	$dord = 1;
13932545eb61SSteven Rostedt    }
13942545eb61SSteven Rostedt
1395d6ce2a0bSSteven Rostedt    while (<CMD>) {
1396d6ce2a0bSSteven Rostedt	print LOG if ($dolog);
1397d6ce2a0bSSteven Rostedt	print RD  if ($dord);
1398d6ce2a0bSSteven Rostedt    }
13992545eb61SSteven Rostedt
1400d6ce2a0bSSteven Rostedt    waitpid($pid, 0);
14012545eb61SSteven Rostedt    my $failed = $?;
14022545eb61SSteven Rostedt
1403d6ce2a0bSSteven Rostedt    close(CMD);
1404d6ce2a0bSSteven Rostedt    close(LOG) if ($dolog);
1405d6ce2a0bSSteven Rostedt    close(RD)  if ($dord);
1406d6ce2a0bSSteven Rostedt
14072545eb61SSteven Rostedt    if ($failed) {
14082545eb61SSteven Rostedt	doprint "FAILED!\n";
14092545eb61SSteven Rostedt    } else {
14102545eb61SSteven Rostedt	doprint "SUCCESS\n";
14112545eb61SSteven Rostedt    }
14122545eb61SSteven Rostedt
14135f9b6cedSSteven Rostedt    return !$failed;
14145f9b6cedSSteven Rostedt}
14155f9b6cedSSteven Rostedt
1416e48c5293SSteven Rostedtsub run_ssh {
1417e48c5293SSteven Rostedt    my ($cmd) = @_;
1418e48c5293SSteven Rostedt    my $cp_exec = $ssh_exec;
1419e48c5293SSteven Rostedt
1420e48c5293SSteven Rostedt    $cp_exec =~ s/\$SSH_COMMAND/$cmd/g;
1421e48c5293SSteven Rostedt    return run_command "$cp_exec";
1422e48c5293SSteven Rostedt}
1423e48c5293SSteven Rostedt
1424e48c5293SSteven Rostedtsub run_scp {
142502ad2617SSteven Rostedt    my ($src, $dst, $cp_scp) = @_;
1426e48c5293SSteven Rostedt
1427e48c5293SSteven Rostedt    $cp_scp =~ s/\$SRC_FILE/$src/g;
1428e48c5293SSteven Rostedt    $cp_scp =~ s/\$DST_FILE/$dst/g;
1429e48c5293SSteven Rostedt
1430e48c5293SSteven Rostedt    return run_command "$cp_scp";
1431e48c5293SSteven Rostedt}
1432e48c5293SSteven Rostedt
143302ad2617SSteven Rostedtsub run_scp_install {
143402ad2617SSteven Rostedt    my ($src, $dst) = @_;
143502ad2617SSteven Rostedt
143602ad2617SSteven Rostedt    my $cp_scp = $scp_to_target_install;
143702ad2617SSteven Rostedt
143802ad2617SSteven Rostedt    return run_scp($src, $dst, $cp_scp);
143902ad2617SSteven Rostedt}
144002ad2617SSteven Rostedt
144102ad2617SSteven Rostedtsub run_scp_mod {
144202ad2617SSteven Rostedt    my ($src, $dst) = @_;
144302ad2617SSteven Rostedt
144402ad2617SSteven Rostedt    my $cp_scp = $scp_to_target;
144502ad2617SSteven Rostedt
144602ad2617SSteven Rostedt    return run_scp($src, $dst, $cp_scp);
144702ad2617SSteven Rostedt}
144802ad2617SSteven Rostedt
14495f9b6cedSSteven Rostedtsub get_grub_index {
14505f9b6cedSSteven Rostedt
1451a75fececSSteven Rostedt    if ($reboot_type ne "grub") {
1452a75fececSSteven Rostedt	return;
1453a75fececSSteven Rostedt    }
14545a391fbfSSteven Rostedt    return if (defined($grub_number));
14555f9b6cedSSteven Rostedt
14565f9b6cedSSteven Rostedt    doprint "Find grub menu ... ";
14575f9b6cedSSteven Rostedt    $grub_number = -1;
1458e48c5293SSteven Rostedt
1459e48c5293SSteven Rostedt    my $ssh_grub = $ssh_exec;
1460e48c5293SSteven Rostedt    $ssh_grub =~ s,\$SSH_COMMAND,cat /boot/grub/menu.lst,g;
1461e48c5293SSteven Rostedt
1462e48c5293SSteven Rostedt    open(IN, "$ssh_grub |")
14635f9b6cedSSteven Rostedt	or die "unable to get menu.lst";
1464e48c5293SSteven Rostedt
1465eaa1fe25SSteven Rostedt    my $found = 0;
1466eaa1fe25SSteven Rostedt
14675f9b6cedSSteven Rostedt    while (<IN>) {
1468a75fececSSteven Rostedt	if (/^\s*title\s+$grub_menu\s*$/) {
14695f9b6cedSSteven Rostedt	    $grub_number++;
1470eaa1fe25SSteven Rostedt	    $found = 1;
14715f9b6cedSSteven Rostedt	    last;
14725f9b6cedSSteven Rostedt	} elsif (/^\s*title\s/) {
14735f9b6cedSSteven Rostedt	    $grub_number++;
14745f9b6cedSSteven Rostedt	}
14755f9b6cedSSteven Rostedt    }
14765f9b6cedSSteven Rostedt    close(IN);
14775f9b6cedSSteven Rostedt
1478a75fececSSteven Rostedt    die "Could not find '$grub_menu' in /boot/grub/menu on $machine"
1479eaa1fe25SSteven Rostedt	if (!$found);
14805f9b6cedSSteven Rostedt    doprint "$grub_number\n";
14812545eb61SSteven Rostedt}
14822545eb61SSteven Rostedt
14832545eb61SSteven Rostedtsub wait_for_input
14842545eb61SSteven Rostedt{
14852545eb61SSteven Rostedt    my ($fp, $time) = @_;
14862545eb61SSteven Rostedt    my $rin;
14872545eb61SSteven Rostedt    my $ready;
14882545eb61SSteven Rostedt    my $line;
14892545eb61SSteven Rostedt    my $ch;
14902545eb61SSteven Rostedt
14912545eb61SSteven Rostedt    if (!defined($time)) {
14922545eb61SSteven Rostedt	$time = $timeout;
14932545eb61SSteven Rostedt    }
14942545eb61SSteven Rostedt
14952545eb61SSteven Rostedt    $rin = '';
14962545eb61SSteven Rostedt    vec($rin, fileno($fp), 1) = 1;
14972545eb61SSteven Rostedt    $ready = select($rin, undef, undef, $time);
14982545eb61SSteven Rostedt
14992545eb61SSteven Rostedt    $line = "";
15002545eb61SSteven Rostedt
15012545eb61SSteven Rostedt    # try to read one char at a time
15022545eb61SSteven Rostedt    while (sysread $fp, $ch, 1) {
15032545eb61SSteven Rostedt	$line .= $ch;
15042545eb61SSteven Rostedt	last if ($ch eq "\n");
15052545eb61SSteven Rostedt    }
15062545eb61SSteven Rostedt
15072545eb61SSteven Rostedt    if (!length($line)) {
15082545eb61SSteven Rostedt	return undef;
15092545eb61SSteven Rostedt    }
15102545eb61SSteven Rostedt
15112545eb61SSteven Rostedt    return $line;
15122545eb61SSteven Rostedt}
15132545eb61SSteven Rostedt
151475c3fda7SSteven Rostedtsub reboot_to {
1515bc7c5803SSteven Rostedt    if (defined($switch_to_test)) {
1516bc7c5803SSteven Rostedt	run_command $switch_to_test;
1517bc7c5803SSteven Rostedt    }
1518bc7c5803SSteven Rostedt
1519a75fececSSteven Rostedt    if ($reboot_type eq "grub") {
1520c54367f9SSteven Rostedt	run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch)'";
152196f6a0dfSSteven Rostedt    } elsif (defined $reboot_script) {
1522a75fececSSteven Rostedt	run_command "$reboot_script";
15232545eb61SSteven Rostedt    }
152496f6a0dfSSteven Rostedt    reboot;
152596f6a0dfSSteven Rostedt}
15262545eb61SSteven Rostedt
1527a57419b3SSteven Rostedtsub get_sha1 {
1528a57419b3SSteven Rostedt    my ($commit) = @_;
1529a57419b3SSteven Rostedt
1530a57419b3SSteven Rostedt    doprint "git rev-list --max-count=1 $commit ... ";
1531a57419b3SSteven Rostedt    my $sha1 = `git rev-list --max-count=1 $commit`;
1532a57419b3SSteven Rostedt    my $ret = $?;
1533a57419b3SSteven Rostedt
1534a57419b3SSteven Rostedt    logit $sha1;
1535a57419b3SSteven Rostedt
1536a57419b3SSteven Rostedt    if ($ret) {
1537a57419b3SSteven Rostedt	doprint "FAILED\n";
1538a57419b3SSteven Rostedt	dodie "Failed to get git $commit";
1539a57419b3SSteven Rostedt    }
1540a57419b3SSteven Rostedt
1541a57419b3SSteven Rostedt    print "SUCCESS\n";
1542a57419b3SSteven Rostedt
1543a57419b3SSteven Rostedt    chomp $sha1;
1544a57419b3SSteven Rostedt
1545a57419b3SSteven Rostedt    return $sha1;
1546a57419b3SSteven Rostedt}
1547a57419b3SSteven Rostedt
15485a391fbfSSteven Rostedtsub monitor {
15492545eb61SSteven Rostedt    my $booted = 0;
15502545eb61SSteven Rostedt    my $bug = 0;
15516ca996ccSSteven Rostedt    my $bug_ignored = 0;
15525c42fc5bSSteven Rostedt    my $skip_call_trace = 0;
15532b7d9b21SSteven Rostedt    my $loops;
15542545eb61SSteven Rostedt
15557faafbd6SSteven Rostedt    wait_for_monitor 5;
15562545eb61SSteven Rostedt
15572545eb61SSteven Rostedt    my $line;
15582545eb61SSteven Rostedt    my $full_line = "";
15592545eb61SSteven Rostedt
15607faafbd6SSteven Rostedt    open(DMESG, "> $dmesg") or
15617faafbd6SSteven Rostedt	die "unable to write to $dmesg";
15622545eb61SSteven Rostedt
156375c3fda7SSteven Rostedt    reboot_to;
15642545eb61SSteven Rostedt
15651c8a617aSSteven Rostedt    my $success_start;
15661c8a617aSSteven Rostedt    my $failure_start;
15672d01b26aSSteven Rostedt    my $monitor_start = time;
15682d01b26aSSteven Rostedt    my $done = 0;
1569f1a5b962SSteven Rostedt    my $version_found = 0;
15701c8a617aSSteven Rostedt
15712d01b26aSSteven Rostedt    while (!$done) {
15722545eb61SSteven Rostedt
1573ecaf8e52SSteven Rostedt	if ($bug && defined($stop_after_failure) &&
1574ecaf8e52SSteven Rostedt	    $stop_after_failure >= 0) {
1575ecaf8e52SSteven Rostedt	    my $time = $stop_after_failure - (time - $failure_start);
1576ecaf8e52SSteven Rostedt	    $line = wait_for_input($monitor_fp, $time);
1577ecaf8e52SSteven Rostedt	    if (!defined($line)) {
1578ecaf8e52SSteven Rostedt		doprint "bug timed out after $booted_timeout seconds\n";
1579ecaf8e52SSteven Rostedt		doprint "Test forced to stop after $stop_after_failure seconds after failure\n";
1580ecaf8e52SSteven Rostedt		last;
1581ecaf8e52SSteven Rostedt	    }
1582ecaf8e52SSteven Rostedt	} elsif ($booted) {
1583a75fececSSteven Rostedt	    $line = wait_for_input($monitor_fp, $booted_timeout);
1584cd4f1d53SSteven Rostedt	    if (!defined($line)) {
1585cd4f1d53SSteven Rostedt		my $s = $booted_timeout == 1 ? "" : "s";
1586cd4f1d53SSteven Rostedt		doprint "Successful boot found: break after $booted_timeout second$s\n";
1587cd4f1d53SSteven Rostedt		last;
1588cd4f1d53SSteven Rostedt	    }
15892b7d9b21SSteven Rostedt	} else {
15907faafbd6SSteven Rostedt	    $line = wait_for_input($monitor_fp);
1591cd4f1d53SSteven Rostedt	    if (!defined($line)) {
1592cd4f1d53SSteven Rostedt		my $s = $timeout == 1 ? "" : "s";
1593cd4f1d53SSteven Rostedt		doprint "Timed out after $timeout second$s\n";
1594cd4f1d53SSteven Rostedt		last;
15952b7d9b21SSteven Rostedt	    }
1596cd4f1d53SSteven Rostedt	}
15972545eb61SSteven Rostedt
15982545eb61SSteven Rostedt	doprint $line;
15997faafbd6SSteven Rostedt	print DMESG $line;
16002545eb61SSteven Rostedt
16012545eb61SSteven Rostedt	# we are not guaranteed to get a full line
16022545eb61SSteven Rostedt	$full_line .= $line;
16032545eb61SSteven Rostedt
1604a75fececSSteven Rostedt	if ($full_line =~ /$success_line/) {
16052545eb61SSteven Rostedt	    $booted = 1;
16061c8a617aSSteven Rostedt	    $success_start = time;
16071c8a617aSSteven Rostedt	}
16081c8a617aSSteven Rostedt
16091c8a617aSSteven Rostedt	if ($booted && defined($stop_after_success) &&
16101c8a617aSSteven Rostedt	    $stop_after_success >= 0) {
16111c8a617aSSteven Rostedt	    my $now = time;
16121c8a617aSSteven Rostedt	    if ($now - $success_start >= $stop_after_success) {
16131c8a617aSSteven Rostedt		doprint "Test forced to stop after $stop_after_success seconds after success\n";
16141c8a617aSSteven Rostedt		last;
16151c8a617aSSteven Rostedt	    }
16162545eb61SSteven Rostedt	}
16172545eb61SSteven Rostedt
16185c42fc5bSSteven Rostedt	if ($full_line =~ /\[ backtrace testing \]/) {
16195c42fc5bSSteven Rostedt	    $skip_call_trace = 1;
16205c42fc5bSSteven Rostedt	}
16215c42fc5bSSteven Rostedt
16222545eb61SSteven Rostedt	if ($full_line =~ /call trace:/i) {
16236ca996ccSSteven Rostedt	    if (!$bug && !$skip_call_trace) {
16246ca996ccSSteven Rostedt		if ($ignore_errors) {
16256ca996ccSSteven Rostedt		    $bug_ignored = 1;
16266ca996ccSSteven Rostedt		} else {
16271c8a617aSSteven Rostedt		    $bug = 1;
16281c8a617aSSteven Rostedt		    $failure_start = time;
16291c8a617aSSteven Rostedt		}
16301c8a617aSSteven Rostedt	    }
16316ca996ccSSteven Rostedt	}
16321c8a617aSSteven Rostedt
16331c8a617aSSteven Rostedt	if ($bug && defined($stop_after_failure) &&
16341c8a617aSSteven Rostedt	    $stop_after_failure >= 0) {
16351c8a617aSSteven Rostedt	    my $now = time;
16361c8a617aSSteven Rostedt	    if ($now - $failure_start >= $stop_after_failure) {
16371c8a617aSSteven Rostedt		doprint "Test forced to stop after $stop_after_failure seconds after failure\n";
16381c8a617aSSteven Rostedt		last;
16391c8a617aSSteven Rostedt	    }
16405c42fc5bSSteven Rostedt	}
16415c42fc5bSSteven Rostedt
16425c42fc5bSSteven Rostedt	if ($full_line =~ /\[ end of backtrace testing \]/) {
16435c42fc5bSSteven Rostedt	    $skip_call_trace = 0;
16445c42fc5bSSteven Rostedt	}
16455c42fc5bSSteven Rostedt
16465c42fc5bSSteven Rostedt	if ($full_line =~ /Kernel panic -/) {
164710abf118SSteven Rostedt	    $failure_start = time;
16482545eb61SSteven Rostedt	    $bug = 1;
16492545eb61SSteven Rostedt	}
16502545eb61SSteven Rostedt
1651f1a5b962SSteven Rostedt	# Detect triple faults by testing the banner
1652f1a5b962SSteven Rostedt	if ($full_line =~ /\bLinux version (\S+).*\n/) {
1653f1a5b962SSteven Rostedt	    if ($1 eq $version) {
1654f1a5b962SSteven Rostedt		$version_found = 1;
1655f1a5b962SSteven Rostedt	    } elsif ($version_found && $detect_triplefault) {
1656f1a5b962SSteven Rostedt		# We already booted into the kernel we are testing,
1657f1a5b962SSteven Rostedt		# but now we booted into another kernel?
1658f1a5b962SSteven Rostedt		# Consider this a triple fault.
1659f1a5b962SSteven Rostedt		doprint "Aleady booted in Linux kernel $version, but now\n";
1660f1a5b962SSteven Rostedt		doprint "we booted into Linux kernel $1.\n";
1661f1a5b962SSteven Rostedt		doprint "Assuming that this is a triple fault.\n";
1662f1a5b962SSteven Rostedt		doprint "To disable this: set DETECT_TRIPLE_FAULT to 0\n";
1663f1a5b962SSteven Rostedt		last;
1664f1a5b962SSteven Rostedt	    }
1665f1a5b962SSteven Rostedt	}
1666f1a5b962SSteven Rostedt
16672545eb61SSteven Rostedt	if ($line =~ /\n/) {
16682545eb61SSteven Rostedt	    $full_line = "";
16692545eb61SSteven Rostedt	}
16702d01b26aSSteven Rostedt
16712d01b26aSSteven Rostedt	if ($stop_test_after > 0 && !$booted && !$bug) {
16722d01b26aSSteven Rostedt	    if (time - $monitor_start > $stop_test_after) {
16734d62bf51SSteven Rostedt		doprint "STOP_TEST_AFTER ($stop_test_after seconds) timed out\n";
16742d01b26aSSteven Rostedt		$done = 1;
16752d01b26aSSteven Rostedt	    }
16762d01b26aSSteven Rostedt	}
16772545eb61SSteven Rostedt    }
16782545eb61SSteven Rostedt
16797faafbd6SSteven Rostedt    close(DMESG);
16802545eb61SSteven Rostedt
16812545eb61SSteven Rostedt    if ($bug) {
16822b7d9b21SSteven Rostedt	return 0 if ($in_bisect);
1683576f627cSSteven Rostedt	fail "failed - got a bug report" and return 0;
16842545eb61SSteven Rostedt    }
16855f9b6cedSSteven Rostedt
1686a75fececSSteven Rostedt    if (!$booted) {
1687a75fececSSteven Rostedt	return 0 if ($in_bisect);
1688576f627cSSteven Rostedt	fail "failed - never got a boot prompt." and return 0;
1689a75fececSSteven Rostedt    }
1690a75fececSSteven Rostedt
16916ca996ccSSteven Rostedt    if ($bug_ignored) {
16926ca996ccSSteven Rostedt	doprint "WARNING: Call Trace detected but ignored due to IGNORE_ERRORS=1\n";
16936ca996ccSSteven Rostedt    }
16946ca996ccSSteven Rostedt
16952b7d9b21SSteven Rostedt    return 1;
16962545eb61SSteven Rostedt}
16972545eb61SSteven Rostedt
16982b29b2f8SSteven Rostedtsub eval_kernel_version {
16992b29b2f8SSteven Rostedt    my ($option) = @_;
17002b29b2f8SSteven Rostedt
17012b29b2f8SSteven Rostedt    $option =~ s/\$KERNEL_VERSION/$version/g;
17022b29b2f8SSteven Rostedt
17032b29b2f8SSteven Rostedt    return $option;
17042b29b2f8SSteven Rostedt}
17052b29b2f8SSteven Rostedt
1706db05cfefSSteven Rostedtsub do_post_install {
1707db05cfefSSteven Rostedt
1708db05cfefSSteven Rostedt    return if (!defined($post_install));
1709db05cfefSSteven Rostedt
17102b29b2f8SSteven Rostedt    my $cp_post_install = eval_kernel_version $post_install;
1711db05cfefSSteven Rostedt    run_command "$cp_post_install" or
1712db05cfefSSteven Rostedt	dodie "Failed to run post install";
1713db05cfefSSteven Rostedt}
1714db05cfefSSteven Rostedt
17152545eb61SSteven Rostedtsub install {
17162545eb61SSteven Rostedt
1717e0a8742eSSteven Rostedt    return if ($no_install);
1718e0a8742eSSteven Rostedt
1719e5c2ec11SSteven Rostedt    if (defined($pre_install)) {
1720e5c2ec11SSteven Rostedt	my $cp_pre_install = eval_kernel_version $pre_install;
1721e5c2ec11SSteven Rostedt	run_command "$cp_pre_install" or
1722e5c2ec11SSteven Rostedt	    dodie "Failed to run pre install";
1723e5c2ec11SSteven Rostedt    }
1724e5c2ec11SSteven Rostedt
17252b29b2f8SSteven Rostedt    my $cp_target = eval_kernel_version $target_image;
17262b29b2f8SSteven Rostedt
172702ad2617SSteven Rostedt    run_scp_install "$outputdir/$build_target", "$cp_target" or
17285c42fc5bSSteven Rostedt	dodie "failed to copy image";
17295f9b6cedSSteven Rostedt
17305f9b6cedSSteven Rostedt    my $install_mods = 0;
17315f9b6cedSSteven Rostedt
17325f9b6cedSSteven Rostedt    # should we process modules?
17335f9b6cedSSteven Rostedt    $install_mods = 0;
173451ad1dd1SSteven Rostedt    open(IN, "$output_config") or dodie("Can't read config file");
17355f9b6cedSSteven Rostedt    while (<IN>) {
17365f9b6cedSSteven Rostedt	if (/CONFIG_MODULES(=y)?/) {
17375f9b6cedSSteven Rostedt	    $install_mods = 1 if (defined($1));
17385f9b6cedSSteven Rostedt	    last;
17395f9b6cedSSteven Rostedt	}
17405f9b6cedSSteven Rostedt    }
17415f9b6cedSSteven Rostedt    close(IN);
17425f9b6cedSSteven Rostedt
17435f9b6cedSSteven Rostedt    if (!$install_mods) {
1744db05cfefSSteven Rostedt	do_post_install;
17455f9b6cedSSteven Rostedt	doprint "No modules needed\n";
17465f9b6cedSSteven Rostedt	return;
17472545eb61SSteven Rostedt    }
17482545eb61SSteven Rostedt
1749627977d8SSteven Rostedt    run_command "$make INSTALL_MOD_STRIP=1 INSTALL_MOD_PATH=$tmpdir modules_install" or
17505f9b6cedSSteven Rostedt	dodie "Failed to install modules";
17515f9b6cedSSteven Rostedt
17522545eb61SSteven Rostedt    my $modlib = "/lib/modules/$version";
1753a57419b3SSteven Rostedt    my $modtar = "ktest-mods.tar.bz2";
17542545eb61SSteven Rostedt
1755e48c5293SSteven Rostedt    run_ssh "rm -rf $modlib" or
17565c42fc5bSSteven Rostedt	dodie "failed to remove old mods: $modlib";
17572545eb61SSteven Rostedt
17585c42fc5bSSteven Rostedt    # would be nice if scp -r did not follow symbolic links
1759a75fececSSteven Rostedt    run_command "cd $tmpdir && tar -cjf $modtar lib/modules/$version" or
17605c42fc5bSSteven Rostedt	dodie "making tarball";
17615c42fc5bSSteven Rostedt
176202ad2617SSteven Rostedt    run_scp_mod "$tmpdir/$modtar", "/tmp" or
17635c42fc5bSSteven Rostedt	dodie "failed to copy modules";
17645c42fc5bSSteven Rostedt
1765a75fececSSteven Rostedt    unlink "$tmpdir/$modtar";
17665c42fc5bSSteven Rostedt
1767e7b13441SSteven Rostedt    run_ssh "'(cd / && tar xjf /tmp/$modtar)'" or
17685c42fc5bSSteven Rostedt	dodie "failed to tar modules";
17695c42fc5bSSteven Rostedt
1770e48c5293SSteven Rostedt    run_ssh "rm -f /tmp/$modtar";
17718b37ca8cSSteven Rostedt
1772db05cfefSSteven Rostedt    do_post_install;
17732545eb61SSteven Rostedt}
17742545eb61SSteven Rostedt
1775ddf607e5SSteven Rostedtsub get_version {
1776ddf607e5SSteven Rostedt    # get the release name
1777683a3e64SSteven Rostedt    return if ($have_version);
1778ddf607e5SSteven Rostedt    doprint "$make kernelrelease ... ";
1779ddf607e5SSteven Rostedt    $version = `$make kernelrelease | tail -1`;
1780ddf607e5SSteven Rostedt    chomp($version);
1781ddf607e5SSteven Rostedt    doprint "$version\n";
1782683a3e64SSteven Rostedt    $have_version = 1;
1783ddf607e5SSteven Rostedt}
1784ddf607e5SSteven Rostedt
1785ddf607e5SSteven Rostedtsub start_monitor_and_boot {
17869f7424ccSSteven Rostedt    # Make sure the stable kernel has finished booting
17879f7424ccSSteven Rostedt    start_monitor;
17889f7424ccSSteven Rostedt    wait_for_monitor 5;
17899f7424ccSSteven Rostedt    end_monitor;
17909f7424ccSSteven Rostedt
1791ddf607e5SSteven Rostedt    get_grub_index;
1792ddf607e5SSteven Rostedt    get_version;
1793ddf607e5SSteven Rostedt    install;
1794ddf607e5SSteven Rostedt
1795ddf607e5SSteven Rostedt    start_monitor;
1796ddf607e5SSteven Rostedt    return monitor;
1797ddf607e5SSteven Rostedt}
1798ddf607e5SSteven Rostedt
17996c5ee0beSSteven Rostedtsub check_buildlog {
18006c5ee0beSSteven Rostedt    my ($patch) = @_;
18016c5ee0beSSteven Rostedt
18026c5ee0beSSteven Rostedt    my @files = `git show $patch | diffstat -l`;
18036c5ee0beSSteven Rostedt
18046c5ee0beSSteven Rostedt    open(IN, "git show $patch |") or
18056c5ee0beSSteven Rostedt	dodie "failed to show $patch";
18066c5ee0beSSteven Rostedt    while (<IN>) {
18076c5ee0beSSteven Rostedt	if (m,^--- a/(.*),) {
18086c5ee0beSSteven Rostedt	    chomp $1;
18096c5ee0beSSteven Rostedt	    $files[$#files] = $1;
18106c5ee0beSSteven Rostedt	}
18116c5ee0beSSteven Rostedt    }
18126c5ee0beSSteven Rostedt    close(IN);
18136c5ee0beSSteven Rostedt
18146c5ee0beSSteven Rostedt    open(IN, $buildlog) or dodie "Can't open $buildlog";
18156c5ee0beSSteven Rostedt    while (<IN>) {
18166c5ee0beSSteven Rostedt	if (/^\s*(.*?):.*(warning|error)/) {
18176c5ee0beSSteven Rostedt	    my $err = $1;
18186c5ee0beSSteven Rostedt	    foreach my $file (@files) {
1819a75fececSSteven Rostedt		my $fullpath = "$builddir/$file";
18206c5ee0beSSteven Rostedt		if ($file eq $err || $fullpath eq $err) {
18212b7d9b21SSteven Rostedt		    fail "$file built with warnings" and return 0;
18226c5ee0beSSteven Rostedt		}
18236c5ee0beSSteven Rostedt	    }
18246c5ee0beSSteven Rostedt	}
18256c5ee0beSSteven Rostedt    }
18266c5ee0beSSteven Rostedt    close(IN);
18272b7d9b21SSteven Rostedt
18282b7d9b21SSteven Rostedt    return 1;
18296c5ee0beSSteven Rostedt}
18306c5ee0beSSteven Rostedt
1831fcb3f16aSSteven Rostedtsub apply_min_config {
1832fcb3f16aSSteven Rostedt    my $outconfig = "$output_config.new";
1833612b9e9bSSteven Rostedt
1834fcb3f16aSSteven Rostedt    # Read the config file and remove anything that
1835fcb3f16aSSteven Rostedt    # is in the force_config hash (from minconfig and others)
1836fcb3f16aSSteven Rostedt    # then add the force config back.
1837fcb3f16aSSteven Rostedt
1838fcb3f16aSSteven Rostedt    doprint "Applying minimum configurations into $output_config.new\n";
1839fcb3f16aSSteven Rostedt
1840fcb3f16aSSteven Rostedt    open (OUT, ">$outconfig") or
1841fcb3f16aSSteven Rostedt	dodie "Can't create $outconfig";
1842fcb3f16aSSteven Rostedt
1843fcb3f16aSSteven Rostedt    if (-f $output_config) {
1844fcb3f16aSSteven Rostedt	open (IN, $output_config) or
1845fcb3f16aSSteven Rostedt	    dodie "Failed to open $output_config";
1846fcb3f16aSSteven Rostedt	while (<IN>) {
1847fcb3f16aSSteven Rostedt	    if (/^(# )?(CONFIG_[^\s=]*)/) {
1848fcb3f16aSSteven Rostedt		next if (defined($force_config{$2}));
1849fcb3f16aSSteven Rostedt	    }
1850fcb3f16aSSteven Rostedt	    print OUT;
1851fcb3f16aSSteven Rostedt	}
1852fcb3f16aSSteven Rostedt	close IN;
1853fcb3f16aSSteven Rostedt    }
1854fcb3f16aSSteven Rostedt    foreach my $config (keys %force_config) {
1855fcb3f16aSSteven Rostedt	print OUT "$force_config{$config}\n";
1856fcb3f16aSSteven Rostedt    }
1857fcb3f16aSSteven Rostedt    close OUT;
1858fcb3f16aSSteven Rostedt
1859fcb3f16aSSteven Rostedt    run_command "mv $outconfig $output_config";
1860fcb3f16aSSteven Rostedt}
1861fcb3f16aSSteven Rostedt
1862fcb3f16aSSteven Rostedtsub make_oldconfig {
1863fcb3f16aSSteven Rostedt
18644c4ab120SSteven Rostedt    my @force_list = keys %force_config;
18654c4ab120SSteven Rostedt
18664c4ab120SSteven Rostedt    if ($#force_list >= 0) {
1867fcb3f16aSSteven Rostedt	apply_min_config;
18684c4ab120SSteven Rostedt    }
1869fcb3f16aSSteven Rostedt
1870fcb3f16aSSteven Rostedt    if (!run_command "$make oldnoconfig") {
1871612b9e9bSSteven Rostedt	# Perhaps oldnoconfig doesn't exist in this version of the kernel
1872612b9e9bSSteven Rostedt	# try a yes '' | oldconfig
1873612b9e9bSSteven Rostedt	doprint "oldnoconfig failed, trying yes '' | make oldconfig\n";
1874fcb3f16aSSteven Rostedt	run_command "yes '' | $make oldconfig" or
1875612b9e9bSSteven Rostedt	    dodie "failed make config oldconfig";
1876612b9e9bSSteven Rostedt    }
1877612b9e9bSSteven Rostedt}
1878612b9e9bSSteven Rostedt
1879fcb3f16aSSteven Rostedt# read a config file and use this to force new configs.
1880fcb3f16aSSteven Rostedtsub load_force_config {
1881fcb3f16aSSteven Rostedt    my ($config) = @_;
1882fcb3f16aSSteven Rostedt
1883cf79fab6SSteven Rostedt    doprint "Loading force configs from $config\n";
1884fcb3f16aSSteven Rostedt    open(IN, $config) or
1885fcb3f16aSSteven Rostedt	dodie "failed to read $config";
1886fcb3f16aSSteven Rostedt    while (<IN>) {
1887fcb3f16aSSteven Rostedt	chomp;
1888fcb3f16aSSteven Rostedt	if (/^(CONFIG[^\s=]*)(\s*=.*)/) {
1889fcb3f16aSSteven Rostedt	    $force_config{$1} = $_;
1890fcb3f16aSSteven Rostedt	} elsif (/^# (CONFIG_\S*) is not set/) {
1891fcb3f16aSSteven Rostedt	    $force_config{$1} = $_;
1892fcb3f16aSSteven Rostedt	}
1893fcb3f16aSSteven Rostedt    }
1894fcb3f16aSSteven Rostedt    close IN;
1895fcb3f16aSSteven Rostedt}
1896fcb3f16aSSteven Rostedt
18972545eb61SSteven Rostedtsub build {
18982545eb61SSteven Rostedt    my ($type) = @_;
18992545eb61SSteven Rostedt
19007faafbd6SSteven Rostedt    unlink $buildlog;
19017faafbd6SSteven Rostedt
19024ab1cce5SSteven Rostedt    # Failed builds should not reboot the target
19034ab1cce5SSteven Rostedt    my $save_no_reboot = $no_reboot;
19044ab1cce5SSteven Rostedt    $no_reboot = 1;
19054ab1cce5SSteven Rostedt
1906683a3e64SSteven Rostedt    # Calculate a new version from here.
1907683a3e64SSteven Rostedt    $have_version = 0;
1908683a3e64SSteven Rostedt
19090bd6c1a3SSteven Rostedt    if (defined($pre_build)) {
19100bd6c1a3SSteven Rostedt	my $ret = run_command $pre_build;
19110bd6c1a3SSteven Rostedt	if (!$ret && defined($pre_build_die) &&
19120bd6c1a3SSteven Rostedt	    $pre_build_die) {
19130bd6c1a3SSteven Rostedt	    dodie "failed to pre_build\n";
19140bd6c1a3SSteven Rostedt	}
19150bd6c1a3SSteven Rostedt    }
19160bd6c1a3SSteven Rostedt
191775c3fda7SSteven Rostedt    if ($type =~ /^useconfig:(.*)/) {
191851ad1dd1SSteven Rostedt	run_command "cp $1 $output_config" or
191975c3fda7SSteven Rostedt	    dodie "could not copy $1 to .config";
19205f9b6cedSSteven Rostedt
192175c3fda7SSteven Rostedt	$type = "oldconfig";
192275c3fda7SSteven Rostedt    }
192375c3fda7SSteven Rostedt
19245c42fc5bSSteven Rostedt    # old config can ask questions
19255c42fc5bSSteven Rostedt    if ($type eq "oldconfig") {
19269386c6abSSteven Rostedt	$type = "oldnoconfig";
192775c3fda7SSteven Rostedt
192875c3fda7SSteven Rostedt	# allow for empty configs
192951ad1dd1SSteven Rostedt	run_command "touch $output_config";
193075c3fda7SSteven Rostedt
193113488231SAndrew Jones	if (!$noclean) {
193251ad1dd1SSteven Rostedt	    run_command "mv $output_config $outputdir/config_temp" or
19335c42fc5bSSteven Rostedt		dodie "moving .config";
19345c42fc5bSSteven Rostedt
193513488231SAndrew Jones	    run_command "$make mrproper" or dodie "make mrproper";
19365c42fc5bSSteven Rostedt
193751ad1dd1SSteven Rostedt	    run_command "mv $outputdir/config_temp $output_config" or
19385c42fc5bSSteven Rostedt		dodie "moving config_temp";
193913488231SAndrew Jones	}
19405c42fc5bSSteven Rostedt
19415c42fc5bSSteven Rostedt    } elsif (!$noclean) {
194251ad1dd1SSteven Rostedt	unlink "$output_config";
19435f9b6cedSSteven Rostedt	run_command "$make mrproper" or
19445c42fc5bSSteven Rostedt	    dodie "make mrproper";
19455c42fc5bSSteven Rostedt    }
19462545eb61SSteven Rostedt
19472545eb61SSteven Rostedt    # add something to distinguish this build
1948a75fececSSteven Rostedt    open(OUT, "> $outputdir/localversion") or dodie("Can't make localversion file");
1949a75fececSSteven Rostedt    print OUT "$localversion\n";
19502545eb61SSteven Rostedt    close(OUT);
19512545eb61SSteven Rostedt
19525f9b6cedSSteven Rostedt    if (defined($minconfig)) {
1953fcb3f16aSSteven Rostedt	load_force_config($minconfig);
19542545eb61SSteven Rostedt    }
19552545eb61SSteven Rostedt
1956fcb3f16aSSteven Rostedt    if ($type ne "oldnoconfig") {
1957fcb3f16aSSteven Rostedt	run_command "$make $type" or
19585c42fc5bSSteven Rostedt	    dodie "failed make config";
1959612b9e9bSSteven Rostedt    }
1960fcb3f16aSSteven Rostedt    # Run old config regardless, to enforce min configurations
1961fcb3f16aSSteven Rostedt    make_oldconfig;
19622545eb61SSteven Rostedt
1963a75fececSSteven Rostedt    $redirect = "$buildlog";
19640bd6c1a3SSteven Rostedt    my $build_ret = run_command "$make $build_options";
19656c5ee0beSSteven Rostedt    undef $redirect;
19660bd6c1a3SSteven Rostedt
19670bd6c1a3SSteven Rostedt    if (defined($post_build)) {
1968683a3e64SSteven Rostedt	# Because a post build may change the kernel version
1969683a3e64SSteven Rostedt	# do it now.
1970683a3e64SSteven Rostedt	get_version;
19710bd6c1a3SSteven Rostedt	my $ret = run_command $post_build;
19720bd6c1a3SSteven Rostedt	if (!$ret && defined($post_build_die) &&
19730bd6c1a3SSteven Rostedt	    $post_build_die) {
19740bd6c1a3SSteven Rostedt	    dodie "failed to post_build\n";
19750bd6c1a3SSteven Rostedt	}
19760bd6c1a3SSteven Rostedt    }
19770bd6c1a3SSteven Rostedt
19780bd6c1a3SSteven Rostedt    if (!$build_ret) {
19795f9b6cedSSteven Rostedt	# bisect may need this to pass
19804ab1cce5SSteven Rostedt	if ($in_bisect) {
19814ab1cce5SSteven Rostedt	    $no_reboot = $save_no_reboot;
19824ab1cce5SSteven Rostedt	    return 0;
19834ab1cce5SSteven Rostedt	}
19842b7d9b21SSteven Rostedt	fail "failed build" and return 0;
19852545eb61SSteven Rostedt    }
19865f9b6cedSSteven Rostedt
19874ab1cce5SSteven Rostedt    $no_reboot = $save_no_reboot;
19884ab1cce5SSteven Rostedt
19892b7d9b21SSteven Rostedt    return 1;
19902545eb61SSteven Rostedt}
19912545eb61SSteven Rostedt
199275c3fda7SSteven Rostedtsub halt {
1993e48c5293SSteven Rostedt    if (!run_ssh "halt" or defined($power_off)) {
1994576f627cSSteven Rostedt	if (defined($poweroff_after_halt)) {
1995576f627cSSteven Rostedt	    sleep $poweroff_after_halt;
1996576f627cSSteven Rostedt	    run_command "$power_off";
1997576f627cSSteven Rostedt	}
1998576f627cSSteven Rostedt    } else {
199975c3fda7SSteven Rostedt	# nope? the zap it!
2000a75fececSSteven Rostedt	run_command "$power_off";
200175c3fda7SSteven Rostedt    }
200275c3fda7SSteven Rostedt}
200375c3fda7SSteven Rostedt
20045f9b6cedSSteven Rostedtsub success {
20055f9b6cedSSteven Rostedt    my ($i) = @_;
20065f9b6cedSSteven Rostedt
2007921ed4c7SSteven Rostedt    if (defined($post_test)) {
2008921ed4c7SSteven Rostedt	run_command $post_test;
2009921ed4c7SSteven Rostedt    }
2010921ed4c7SSteven Rostedt
2011e48c5293SSteven Rostedt    $successes++;
2012e48c5293SSteven Rostedt
20139064af52SSteven Rostedt    my $name = "";
20149064af52SSteven Rostedt
20159064af52SSteven Rostedt    if (defined($test_name)) {
20169064af52SSteven Rostedt	$name = " ($test_name)";
20179064af52SSteven Rostedt    }
20189064af52SSteven Rostedt
20195f9b6cedSSteven Rostedt    doprint "\n\n*******************************************\n";
20205f9b6cedSSteven Rostedt    doprint     "*******************************************\n";
20219064af52SSteven Rostedt    doprint     "KTEST RESULT: TEST $i$name SUCCESS!!!!         **\n";
20225f9b6cedSSteven Rostedt    doprint     "*******************************************\n";
20235f9b6cedSSteven Rostedt    doprint     "*******************************************\n";
20245f9b6cedSSteven Rostedt
2025de5b6e3bSRabin Vincent    if (defined($store_successes)) {
2026de5b6e3bSRabin Vincent        save_logs "success", $store_successes;
2027de5b6e3bSRabin Vincent    }
2028de5b6e3bSRabin Vincent
2029576f627cSSteven Rostedt    if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) {
2030a75fececSSteven Rostedt	doprint "Reboot and wait $sleep_time seconds\n";
2031bc7c5803SSteven Rostedt	reboot_to_good $sleep_time;
20325f9b6cedSSteven Rostedt    }
20335f9b6cedSSteven Rostedt}
20345f9b6cedSSteven Rostedt
2035c960bb9fSSteven Rostedtsub answer_bisect {
2036c960bb9fSSteven Rostedt    for (;;) {
2037c960bb9fSSteven Rostedt	doprint "Pass or fail? [p/f]";
2038c960bb9fSSteven Rostedt	my $ans = <STDIN>;
2039c960bb9fSSteven Rostedt	chomp $ans;
2040c960bb9fSSteven Rostedt	if ($ans eq "p" || $ans eq "P") {
2041c960bb9fSSteven Rostedt	    return 1;
2042c960bb9fSSteven Rostedt	} elsif ($ans eq "f" || $ans eq "F") {
2043c960bb9fSSteven Rostedt	    return 0;
2044c960bb9fSSteven Rostedt	} else {
2045c960bb9fSSteven Rostedt	    print "Please answer 'P' or 'F'\n";
2046c960bb9fSSteven Rostedt	}
2047c960bb9fSSteven Rostedt    }
2048c960bb9fSSteven Rostedt}
2049c960bb9fSSteven Rostedt
20505a391fbfSSteven Rostedtsub child_run_test {
20517faafbd6SSteven Rostedt    my $failed = 0;
20525a391fbfSSteven Rostedt
20537faafbd6SSteven Rostedt    # child should have no power
2054a75fececSSteven Rostedt    $reboot_on_error = 0;
2055a75fececSSteven Rostedt    $poweroff_on_error = 0;
2056a75fececSSteven Rostedt    $die_on_failure = 1;
20577faafbd6SSteven Rostedt
2058a9dd5d63SRabin Vincent    $redirect = "$testlog";
20597faafbd6SSteven Rostedt    run_command $run_test or $failed = 1;
2060a9dd5d63SRabin Vincent    undef $redirect;
2061a9dd5d63SRabin Vincent
20625a391fbfSSteven Rostedt    exit $failed;
20635a391fbfSSteven Rostedt}
20645a391fbfSSteven Rostedt
20655a391fbfSSteven Rostedtmy $child_done;
20665a391fbfSSteven Rostedt
20675a391fbfSSteven Rostedtsub child_finished {
20685a391fbfSSteven Rostedt    $child_done = 1;
20695a391fbfSSteven Rostedt}
20705a391fbfSSteven Rostedt
20715a391fbfSSteven Rostedtsub do_run_test {
20725a391fbfSSteven Rostedt    my $child_pid;
20735a391fbfSSteven Rostedt    my $child_exit;
20745a391fbfSSteven Rostedt    my $line;
20755a391fbfSSteven Rostedt    my $full_line;
20765a391fbfSSteven Rostedt    my $bug = 0;
20775a391fbfSSteven Rostedt
20787faafbd6SSteven Rostedt    wait_for_monitor 1;
20795a391fbfSSteven Rostedt
20807faafbd6SSteven Rostedt    doprint "run test $run_test\n";
20815a391fbfSSteven Rostedt
20825a391fbfSSteven Rostedt    $child_done = 0;
20835a391fbfSSteven Rostedt
20845a391fbfSSteven Rostedt    $SIG{CHLD} = qw(child_finished);
20855a391fbfSSteven Rostedt
20865a391fbfSSteven Rostedt    $child_pid = fork;
20875a391fbfSSteven Rostedt
20885a391fbfSSteven Rostedt    child_run_test if (!$child_pid);
20895a391fbfSSteven Rostedt
20905a391fbfSSteven Rostedt    $full_line = "";
20915a391fbfSSteven Rostedt
20925a391fbfSSteven Rostedt    do {
20937faafbd6SSteven Rostedt	$line = wait_for_input($monitor_fp, 1);
20945a391fbfSSteven Rostedt	if (defined($line)) {
20955a391fbfSSteven Rostedt
20965a391fbfSSteven Rostedt	    # we are not guaranteed to get a full line
20975a391fbfSSteven Rostedt	    $full_line .= $line;
20988ea0e063SSteven Rostedt	    doprint $line;
20995a391fbfSSteven Rostedt
21005a391fbfSSteven Rostedt	    if ($full_line =~ /call trace:/i) {
21015a391fbfSSteven Rostedt		$bug = 1;
21025a391fbfSSteven Rostedt	    }
21035a391fbfSSteven Rostedt
21045a391fbfSSteven Rostedt	    if ($full_line =~ /Kernel panic -/) {
21055a391fbfSSteven Rostedt		$bug = 1;
21065a391fbfSSteven Rostedt	    }
21075a391fbfSSteven Rostedt
21085a391fbfSSteven Rostedt	    if ($line =~ /\n/) {
21095a391fbfSSteven Rostedt		$full_line = "";
21105a391fbfSSteven Rostedt	    }
21115a391fbfSSteven Rostedt	}
21125a391fbfSSteven Rostedt    } while (!$child_done && !$bug);
21135a391fbfSSteven Rostedt
21145a391fbfSSteven Rostedt    if ($bug) {
21158ea0e063SSteven Rostedt	my $failure_start = time;
21168ea0e063SSteven Rostedt	my $now;
21178ea0e063SSteven Rostedt	do {
21188ea0e063SSteven Rostedt	    $line = wait_for_input($monitor_fp, 1);
21198ea0e063SSteven Rostedt	    if (defined($line)) {
21208ea0e063SSteven Rostedt		doprint $line;
21218ea0e063SSteven Rostedt	    }
21228ea0e063SSteven Rostedt	    $now = time;
21238ea0e063SSteven Rostedt	    if ($now - $failure_start >= $stop_after_failure) {
21248ea0e063SSteven Rostedt		last;
21258ea0e063SSteven Rostedt	    }
21268ea0e063SSteven Rostedt	} while (defined($line));
21278ea0e063SSteven Rostedt
21285a391fbfSSteven Rostedt	doprint "Detected kernel crash!\n";
21295a391fbfSSteven Rostedt	# kill the child with extreme prejudice
21305a391fbfSSteven Rostedt	kill 9, $child_pid;
21315a391fbfSSteven Rostedt    }
21325a391fbfSSteven Rostedt
21335a391fbfSSteven Rostedt    waitpid $child_pid, 0;
21345a391fbfSSteven Rostedt    $child_exit = $?;
21355a391fbfSSteven Rostedt
2136c5dacb88SSteven Rostedt    if (!$bug && $in_bisect) {
2137c5dacb88SSteven Rostedt	if (defined($bisect_ret_good)) {
2138c5dacb88SSteven Rostedt	    if ($child_exit == $bisect_ret_good) {
2139c5dacb88SSteven Rostedt		return 1;
2140c5dacb88SSteven Rostedt	    }
2141c5dacb88SSteven Rostedt	}
2142c5dacb88SSteven Rostedt	if (defined($bisect_ret_skip)) {
2143c5dacb88SSteven Rostedt	    if ($child_exit == $bisect_ret_skip) {
2144c5dacb88SSteven Rostedt		return -1;
2145c5dacb88SSteven Rostedt	    }
2146c5dacb88SSteven Rostedt	}
2147c5dacb88SSteven Rostedt	if (defined($bisect_ret_abort)) {
2148c5dacb88SSteven Rostedt	    if ($child_exit == $bisect_ret_abort) {
2149c5dacb88SSteven Rostedt		fail "test abort" and return -2;
2150c5dacb88SSteven Rostedt	    }
2151c5dacb88SSteven Rostedt	}
2152c5dacb88SSteven Rostedt	if (defined($bisect_ret_bad)) {
2153c5dacb88SSteven Rostedt	    if ($child_exit == $bisect_ret_skip) {
2154c5dacb88SSteven Rostedt		return 0;
2155c5dacb88SSteven Rostedt	    }
2156c5dacb88SSteven Rostedt	}
2157c5dacb88SSteven Rostedt	if (defined($bisect_ret_default)) {
2158c5dacb88SSteven Rostedt	    if ($bisect_ret_default eq "good") {
2159c5dacb88SSteven Rostedt		return 1;
2160c5dacb88SSteven Rostedt	    } elsif ($bisect_ret_default eq "bad") {
2161c5dacb88SSteven Rostedt		return 0;
2162c5dacb88SSteven Rostedt	    } elsif ($bisect_ret_default eq "skip") {
2163c5dacb88SSteven Rostedt		return -1;
2164c5dacb88SSteven Rostedt	    } elsif ($bisect_ret_default eq "abort") {
2165c5dacb88SSteven Rostedt		return -2;
2166c5dacb88SSteven Rostedt	    } else {
2167c5dacb88SSteven Rostedt		fail "unknown default action: $bisect_ret_default"
2168c5dacb88SSteven Rostedt		    and return -2;
2169c5dacb88SSteven Rostedt	    }
2170c5dacb88SSteven Rostedt	}
2171c5dacb88SSteven Rostedt    }
2172c5dacb88SSteven Rostedt
21735a391fbfSSteven Rostedt    if ($bug || $child_exit) {
21742b7d9b21SSteven Rostedt	return 0 if $in_bisect;
21752b7d9b21SSteven Rostedt	fail "test failed" and return 0;
21765a391fbfSSteven Rostedt    }
21772b7d9b21SSteven Rostedt    return 1;
21785a391fbfSSteven Rostedt}
21795a391fbfSSteven Rostedt
2180a75fececSSteven Rostedtsub run_git_bisect {
2181a75fececSSteven Rostedt    my ($command) = @_;
2182a75fececSSteven Rostedt
2183a75fececSSteven Rostedt    doprint "$command ... ";
2184a75fececSSteven Rostedt
2185a75fececSSteven Rostedt    my $output = `$command 2>&1`;
2186a75fececSSteven Rostedt    my $ret = $?;
2187a75fececSSteven Rostedt
2188a75fececSSteven Rostedt    logit $output;
2189a75fececSSteven Rostedt
2190a75fececSSteven Rostedt    if ($ret) {
2191a75fececSSteven Rostedt	doprint "FAILED\n";
2192a75fececSSteven Rostedt	dodie "Failed to git bisect";
2193a75fececSSteven Rostedt    }
2194a75fececSSteven Rostedt
2195a75fececSSteven Rostedt    doprint "SUCCESS\n";
2196a75fececSSteven Rostedt    if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\))\s+\[([[:xdigit:]]+)\]/) {
2197a75fececSSteven Rostedt	doprint "$1 [$2]\n";
2198a75fececSSteven Rostedt    } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) {
2199b5f4aea6SSteven Rostedt	$bisect_bad_commit = $1;
2200a75fececSSteven Rostedt	doprint "Found bad commit... $1\n";
2201a75fececSSteven Rostedt	return 0;
2202a75fececSSteven Rostedt    } else {
2203a75fececSSteven Rostedt	# we already logged it, just print it now.
2204a75fececSSteven Rostedt	print $output;
2205a75fececSSteven Rostedt    }
2206a75fececSSteven Rostedt
2207a75fececSSteven Rostedt    return 1;
2208a75fececSSteven Rostedt}
2209a75fececSSteven Rostedt
2210c23dca7cSSteven Rostedtsub bisect_reboot {
2211c23dca7cSSteven Rostedt    doprint "Reboot and sleep $bisect_sleep_time seconds\n";
2212bc7c5803SSteven Rostedt    reboot_to_good $bisect_sleep_time;
2213c23dca7cSSteven Rostedt}
2214c23dca7cSSteven Rostedt
2215c23dca7cSSteven Rostedt# returns 1 on success, 0 on failure, -1 on skip
22160a05c769SSteven Rostedtsub run_bisect_test {
22170a05c769SSteven Rostedt    my ($type, $buildtype) = @_;
22185f9b6cedSSteven Rostedt
22192b7d9b21SSteven Rostedt    my $failed = 0;
22205f9b6cedSSteven Rostedt    my $result;
22215f9b6cedSSteven Rostedt    my $output;
22225f9b6cedSSteven Rostedt    my $ret;
22235f9b6cedSSteven Rostedt
22240a05c769SSteven Rostedt    $in_bisect = 1;
22250a05c769SSteven Rostedt
22260a05c769SSteven Rostedt    build $buildtype or $failed = 1;
22275f9b6cedSSteven Rostedt
22285f9b6cedSSteven Rostedt    if ($type ne "build") {
2229c23dca7cSSteven Rostedt	if ($failed && $bisect_skip) {
2230c23dca7cSSteven Rostedt	    $in_bisect = 0;
2231c23dca7cSSteven Rostedt	    return -1;
2232c23dca7cSSteven Rostedt	}
22337faafbd6SSteven Rostedt	dodie "Failed on build" if $failed;
22345f9b6cedSSteven Rostedt
22355f9b6cedSSteven Rostedt	# Now boot the box
2236ddf607e5SSteven Rostedt	start_monitor_and_boot or $failed = 1;
22375f9b6cedSSteven Rostedt
22385f9b6cedSSteven Rostedt	if ($type ne "boot") {
2239c23dca7cSSteven Rostedt	    if ($failed && $bisect_skip) {
2240c23dca7cSSteven Rostedt		end_monitor;
2241c23dca7cSSteven Rostedt		bisect_reboot;
2242c23dca7cSSteven Rostedt		$in_bisect = 0;
2243c23dca7cSSteven Rostedt		return -1;
2244c23dca7cSSteven Rostedt	    }
22457faafbd6SSteven Rostedt	    dodie "Failed on boot" if $failed;
22465a391fbfSSteven Rostedt
22472b7d9b21SSteven Rostedt	    do_run_test or $failed = 1;
22485f9b6cedSSteven Rostedt	}
22497faafbd6SSteven Rostedt	end_monitor;
22505f9b6cedSSteven Rostedt    }
22515f9b6cedSSteven Rostedt
22525f9b6cedSSteven Rostedt    if ($failed) {
22530a05c769SSteven Rostedt	$result = 0;
22545f9b6cedSSteven Rostedt    } else {
22550a05c769SSteven Rostedt	$result = 1;
22565f9b6cedSSteven Rostedt    }
22574025bc62SSteven Rostedt
22584025bc62SSteven Rostedt    # reboot the box to a kernel we can ssh to
22594025bc62SSteven Rostedt    if ($type ne "build") {
22604025bc62SSteven Rostedt	bisect_reboot;
22614025bc62SSteven Rostedt    }
22620a05c769SSteven Rostedt    $in_bisect = 0;
22630a05c769SSteven Rostedt
22640a05c769SSteven Rostedt    return $result;
22650a05c769SSteven Rostedt}
22660a05c769SSteven Rostedt
22670a05c769SSteven Rostedtsub run_bisect {
22680a05c769SSteven Rostedt    my ($type) = @_;
22690a05c769SSteven Rostedt    my $buildtype = "oldconfig";
22700a05c769SSteven Rostedt
22710a05c769SSteven Rostedt    # We should have a minconfig to use?
22720a05c769SSteven Rostedt    if (defined($minconfig)) {
22730a05c769SSteven Rostedt	$buildtype = "useconfig:$minconfig";
22740a05c769SSteven Rostedt    }
22750a05c769SSteven Rostedt
22760a05c769SSteven Rostedt    my $ret = run_bisect_test $type, $buildtype;
22770a05c769SSteven Rostedt
2278c960bb9fSSteven Rostedt    if ($bisect_manual) {
2279c960bb9fSSteven Rostedt	$ret = answer_bisect;
2280c960bb9fSSteven Rostedt    }
22815f9b6cedSSteven Rostedt
2282d6ce2a0bSSteven Rostedt    # Are we looking for where it worked, not failed?
22835158ba3eSRuss Dill    if ($reverse_bisect && $ret >= 0) {
22840a05c769SSteven Rostedt	$ret = !$ret;
2285d6ce2a0bSSteven Rostedt    }
2286d6ce2a0bSSteven Rostedt
2287c23dca7cSSteven Rostedt    if ($ret > 0) {
22880a05c769SSteven Rostedt	return "good";
2289c23dca7cSSteven Rostedt    } elsif ($ret == 0) {
22900a05c769SSteven Rostedt	return  "bad";
2291c23dca7cSSteven Rostedt    } elsif ($bisect_skip) {
2292c23dca7cSSteven Rostedt	doprint "HIT A BAD COMMIT ... SKIPPING\n";
2293c23dca7cSSteven Rostedt	return "skip";
22940a05c769SSteven Rostedt    }
22955f9b6cedSSteven Rostedt}
22965f9b6cedSSteven Rostedt
2297dad98754SSteven Rostedtsub update_bisect_replay {
2298dad98754SSteven Rostedt    my $tmp_log = "$tmpdir/ktest_bisect_log";
2299dad98754SSteven Rostedt    run_command "git bisect log > $tmp_log" or
2300dad98754SSteven Rostedt	die "can't create bisect log";
2301dad98754SSteven Rostedt    return $tmp_log;
2302dad98754SSteven Rostedt}
2303dad98754SSteven Rostedt
23045f9b6cedSSteven Rostedtsub bisect {
23055f9b6cedSSteven Rostedt    my ($i) = @_;
23065f9b6cedSSteven Rostedt
23075f9b6cedSSteven Rostedt    my $result;
23085f9b6cedSSteven Rostedt
2309b5f4aea6SSteven Rostedt    die "BISECT_GOOD[$i] not defined\n"	if (!defined($bisect_good));
2310b5f4aea6SSteven Rostedt    die "BISECT_BAD[$i] not defined\n"	if (!defined($bisect_bad));
2311b5f4aea6SSteven Rostedt    die "BISECT_TYPE[$i] not defined\n"	if (!defined($bisect_type));
23125f9b6cedSSteven Rostedt
2313b5f4aea6SSteven Rostedt    my $good = $bisect_good;
2314b5f4aea6SSteven Rostedt    my $bad = $bisect_bad;
2315b5f4aea6SSteven Rostedt    my $type = $bisect_type;
2316b5f4aea6SSteven Rostedt    my $start = $bisect_start;
2317b5f4aea6SSteven Rostedt    my $replay = $bisect_replay;
2318b5f4aea6SSteven Rostedt    my $start_files = $bisect_files;
23193410f6fdSSteven Rostedt
23203410f6fdSSteven Rostedt    if (defined($start_files)) {
23213410f6fdSSteven Rostedt	$start_files = " -- " . $start_files;
23223410f6fdSSteven Rostedt    } else {
23233410f6fdSSteven Rostedt	$start_files = "";
23243410f6fdSSteven Rostedt    }
23255f9b6cedSSteven Rostedt
2326a57419b3SSteven Rostedt    # convert to true sha1's
2327a57419b3SSteven Rostedt    $good = get_sha1($good);
2328a57419b3SSteven Rostedt    $bad = get_sha1($bad);
2329a57419b3SSteven Rostedt
2330b5f4aea6SSteven Rostedt    if (defined($bisect_reverse) && $bisect_reverse == 1) {
2331d6ce2a0bSSteven Rostedt	doprint "Performing a reverse bisect (bad is good, good is bad!)\n";
2332d6ce2a0bSSteven Rostedt	$reverse_bisect = 1;
2333d6ce2a0bSSteven Rostedt    } else {
2334d6ce2a0bSSteven Rostedt	$reverse_bisect = 0;
2335d6ce2a0bSSteven Rostedt    }
2336d6ce2a0bSSteven Rostedt
23375a391fbfSSteven Rostedt    # Can't have a test without having a test to run
23385a391fbfSSteven Rostedt    if ($type eq "test" && !defined($run_test)) {
23395a391fbfSSteven Rostedt	$type = "boot";
23405a391fbfSSteven Rostedt    }
23415a391fbfSSteven Rostedt
2342dad98754SSteven Rostedt    # Check if a bisect was running
2343dad98754SSteven Rostedt    my $bisect_start_file = "$builddir/.git/BISECT_START";
2344dad98754SSteven Rostedt
2345b5f4aea6SSteven Rostedt    my $check = $bisect_check;
2346dad98754SSteven Rostedt    my $do_check = defined($check) && $check ne "0";
2347dad98754SSteven Rostedt
2348dad98754SSteven Rostedt    if ( -f $bisect_start_file ) {
2349dad98754SSteven Rostedt	print "Bisect in progress found\n";
2350dad98754SSteven Rostedt	if ($do_check) {
2351dad98754SSteven Rostedt	    print " If you say yes, then no checks of good or bad will be done\n";
2352dad98754SSteven Rostedt	}
2353dad98754SSteven Rostedt	if (defined($replay)) {
2354dad98754SSteven Rostedt	    print "** BISECT_REPLAY is defined in config file **";
2355dad98754SSteven Rostedt	    print " Ignore config option and perform new git bisect log?\n";
2356dad98754SSteven Rostedt	    if (read_ync " (yes, no, or cancel) ") {
2357dad98754SSteven Rostedt		$replay = update_bisect_replay;
2358dad98754SSteven Rostedt		$do_check = 0;
2359dad98754SSteven Rostedt	    }
2360dad98754SSteven Rostedt	} elsif (read_yn "read git log and continue?") {
2361dad98754SSteven Rostedt	    $replay = update_bisect_replay;
2362dad98754SSteven Rostedt	    $do_check = 0;
2363dad98754SSteven Rostedt	}
2364dad98754SSteven Rostedt    }
2365dad98754SSteven Rostedt
2366dad98754SSteven Rostedt    if ($do_check) {
2367a75fececSSteven Rostedt
2368a75fececSSteven Rostedt	# get current HEAD
2369a57419b3SSteven Rostedt	my $head = get_sha1("HEAD");
2370a75fececSSteven Rostedt
2371a75fececSSteven Rostedt	if ($check ne "good") {
2372a75fececSSteven Rostedt	    doprint "TESTING BISECT BAD [$bad]\n";
2373a75fececSSteven Rostedt	    run_command "git checkout $bad" or
2374a75fececSSteven Rostedt		die "Failed to checkout $bad";
2375a75fececSSteven Rostedt
2376a75fececSSteven Rostedt	    $result = run_bisect $type;
2377a75fececSSteven Rostedt
2378a75fececSSteven Rostedt	    if ($result ne "bad") {
2379a75fececSSteven Rostedt		fail "Tested BISECT_BAD [$bad] and it succeeded" and return 0;
2380a75fececSSteven Rostedt	    }
2381a75fececSSteven Rostedt	}
2382a75fececSSteven Rostedt
2383a75fececSSteven Rostedt	if ($check ne "bad") {
2384a75fececSSteven Rostedt	    doprint "TESTING BISECT GOOD [$good]\n";
2385a75fececSSteven Rostedt	    run_command "git checkout $good" or
2386a75fececSSteven Rostedt		die "Failed to checkout $good";
2387a75fececSSteven Rostedt
2388a75fececSSteven Rostedt	    $result = run_bisect $type;
2389a75fececSSteven Rostedt
2390a75fececSSteven Rostedt	    if ($result ne "good") {
2391a75fececSSteven Rostedt		fail "Tested BISECT_GOOD [$good] and it failed" and return 0;
2392a75fececSSteven Rostedt	    }
2393a75fececSSteven Rostedt	}
2394a75fececSSteven Rostedt
2395a75fececSSteven Rostedt	# checkout where we started
2396a75fececSSteven Rostedt	run_command "git checkout $head" or
2397a75fececSSteven Rostedt	    die "Failed to checkout $head";
2398a75fececSSteven Rostedt    }
2399a75fececSSteven Rostedt
24003410f6fdSSteven Rostedt    run_command "git bisect start$start_files" or
2401a75fececSSteven Rostedt	dodie "could not start bisect";
2402a75fececSSteven Rostedt
2403a75fececSSteven Rostedt    run_command "git bisect good $good" or
2404a75fececSSteven Rostedt	dodie "could not set bisect good to $good";
2405a75fececSSteven Rostedt
2406a75fececSSteven Rostedt    run_git_bisect "git bisect bad $bad" or
2407a75fececSSteven Rostedt	dodie "could not set bisect bad to $bad";
2408a75fececSSteven Rostedt
2409a75fececSSteven Rostedt    if (defined($replay)) {
2410a75fececSSteven Rostedt	run_command "git bisect replay $replay" or
2411a75fececSSteven Rostedt	    dodie "failed to run replay";
2412a75fececSSteven Rostedt    }
2413a75fececSSteven Rostedt
2414a75fececSSteven Rostedt    if (defined($start)) {
2415a75fececSSteven Rostedt	run_command "git checkout $start" or
2416a75fececSSteven Rostedt	    dodie "failed to checkout $start";
2417a75fececSSteven Rostedt    }
2418a75fececSSteven Rostedt
2419a75fececSSteven Rostedt    my $test;
24205f9b6cedSSteven Rostedt    do {
24215f9b6cedSSteven Rostedt	$result = run_bisect $type;
2422a75fececSSteven Rostedt	$test = run_git_bisect "git bisect $result";
2423a75fececSSteven Rostedt    } while ($test);
24245f9b6cedSSteven Rostedt
24255f9b6cedSSteven Rostedt    run_command "git bisect log" or
24265f9b6cedSSteven Rostedt	dodie "could not capture git bisect log";
24275f9b6cedSSteven Rostedt
24285f9b6cedSSteven Rostedt    run_command "git bisect reset" or
24295f9b6cedSSteven Rostedt	dodie "could not reset git bisect";
24305f9b6cedSSteven Rostedt
2431b5f4aea6SSteven Rostedt    doprint "Bad commit was [$bisect_bad_commit]\n";
24325f9b6cedSSteven Rostedt
24330a05c769SSteven Rostedt    success $i;
24340a05c769SSteven Rostedt}
24350a05c769SSteven Rostedt
2436cf79fab6SSteven Rostedt# config_ignore holds the configs that were set (or unset) for
2437cf79fab6SSteven Rostedt# a good config and we will ignore these configs for the rest
2438cf79fab6SSteven Rostedt# of a config bisect. These configs stay as they were.
24390a05c769SSteven Rostedtmy %config_ignore;
2440cf79fab6SSteven Rostedt
2441cf79fab6SSteven Rostedt# config_set holds what all configs were set as.
24420a05c769SSteven Rostedtmy %config_set;
24430a05c769SSteven Rostedt
2444cf79fab6SSteven Rostedt# config_off holds the set of configs that the bad config had disabled.
2445cf79fab6SSteven Rostedt# We need to record them and set them in the .config when running
2446cf79fab6SSteven Rostedt# oldnoconfig, because oldnoconfig does not turn off new symbols, but
2447cf79fab6SSteven Rostedt# instead just keeps the defaults.
2448cf79fab6SSteven Rostedtmy %config_off;
2449cf79fab6SSteven Rostedt
2450cf79fab6SSteven Rostedt# config_off_tmp holds a set of configs to turn off for now
2451cf79fab6SSteven Rostedtmy @config_off_tmp;
2452cf79fab6SSteven Rostedt
2453cf79fab6SSteven Rostedt# config_list is the set of configs that are being tested
24540a05c769SSteven Rostedtmy %config_list;
24550a05c769SSteven Rostedtmy %null_config;
24560a05c769SSteven Rostedt
24570a05c769SSteven Rostedtmy %dependency;
24580a05c769SSteven Rostedt
24594c4ab120SSteven Rostedtsub assign_configs {
24604c4ab120SSteven Rostedt    my ($hash, $config) = @_;
24610a05c769SSteven Rostedt
24620a05c769SSteven Rostedt    open (IN, $config)
24630a05c769SSteven Rostedt	or dodie "Failed to read $config";
24640a05c769SSteven Rostedt
24650a05c769SSteven Rostedt    while (<IN>) {
24669bf71749SSteven Rostedt	if (/^((CONFIG\S*)=.*)/) {
24674c4ab120SSteven Rostedt	    ${$hash}{$2} = $1;
24680a05c769SSteven Rostedt	}
24690a05c769SSteven Rostedt    }
24700a05c769SSteven Rostedt
24710a05c769SSteven Rostedt    close(IN);
24720a05c769SSteven Rostedt}
24730a05c769SSteven Rostedt
24744c4ab120SSteven Rostedtsub process_config_ignore {
24754c4ab120SSteven Rostedt    my ($config) = @_;
24764c4ab120SSteven Rostedt
24774c4ab120SSteven Rostedt    assign_configs \%config_ignore, $config;
24784c4ab120SSteven Rostedt}
24794c4ab120SSteven Rostedt
24800a05c769SSteven Rostedtsub read_current_config {
24810a05c769SSteven Rostedt    my ($config_ref) = @_;
24820a05c769SSteven Rostedt
24830a05c769SSteven Rostedt    %{$config_ref} = ();
24840a05c769SSteven Rostedt    undef %{$config_ref};
24850a05c769SSteven Rostedt
24860a05c769SSteven Rostedt    my @key = keys %{$config_ref};
24870a05c769SSteven Rostedt    if ($#key >= 0) {
24880a05c769SSteven Rostedt	print "did not delete!\n";
24890a05c769SSteven Rostedt	exit;
24900a05c769SSteven Rostedt    }
24910a05c769SSteven Rostedt    open (IN, "$output_config");
24920a05c769SSteven Rostedt
24930a05c769SSteven Rostedt    while (<IN>) {
24940a05c769SSteven Rostedt	if (/^(CONFIG\S+)=(.*)/) {
24950a05c769SSteven Rostedt	    ${$config_ref}{$1} = $2;
24960a05c769SSteven Rostedt	}
24970a05c769SSteven Rostedt    }
24980a05c769SSteven Rostedt    close(IN);
24990a05c769SSteven Rostedt}
25000a05c769SSteven Rostedt
25010a05c769SSteven Rostedtsub get_dependencies {
25020a05c769SSteven Rostedt    my ($config) = @_;
25030a05c769SSteven Rostedt
25040a05c769SSteven Rostedt    my $arr = $dependency{$config};
25050a05c769SSteven Rostedt    if (!defined($arr)) {
25060a05c769SSteven Rostedt	return ();
25070a05c769SSteven Rostedt    }
25080a05c769SSteven Rostedt
25090a05c769SSteven Rostedt    my @deps = @{$arr};
25100a05c769SSteven Rostedt
25110a05c769SSteven Rostedt    foreach my $dep (@{$arr}) {
25120a05c769SSteven Rostedt	print "ADD DEP $dep\n";
25130a05c769SSteven Rostedt	@deps = (@deps, get_dependencies $dep);
25140a05c769SSteven Rostedt    }
25150a05c769SSteven Rostedt
25160a05c769SSteven Rostedt    return @deps;
25170a05c769SSteven Rostedt}
25180a05c769SSteven Rostedt
25190a05c769SSteven Rostedtsub create_config {
25200a05c769SSteven Rostedt    my @configs = @_;
25210a05c769SSteven Rostedt
25220a05c769SSteven Rostedt    open(OUT, ">$output_config") or dodie "Can not write to $output_config";
25230a05c769SSteven Rostedt
25240a05c769SSteven Rostedt    foreach my $config (@configs) {
25250a05c769SSteven Rostedt	print OUT "$config_set{$config}\n";
25260a05c769SSteven Rostedt	my @deps = get_dependencies $config;
25270a05c769SSteven Rostedt	foreach my $dep (@deps) {
25280a05c769SSteven Rostedt	    print OUT "$config_set{$dep}\n";
25290a05c769SSteven Rostedt	}
25300a05c769SSteven Rostedt    }
25310a05c769SSteven Rostedt
2532cf79fab6SSteven Rostedt    # turn off configs to keep off
2533cf79fab6SSteven Rostedt    foreach my $config (keys %config_off) {
2534cf79fab6SSteven Rostedt	print OUT "# $config is not set\n";
2535cf79fab6SSteven Rostedt    }
2536cf79fab6SSteven Rostedt
2537cf79fab6SSteven Rostedt    # turn off configs that should be off for now
2538cf79fab6SSteven Rostedt    foreach my $config (@config_off_tmp) {
2539cf79fab6SSteven Rostedt	print OUT "# $config is not set\n";
2540cf79fab6SSteven Rostedt    }
2541cf79fab6SSteven Rostedt
25420a05c769SSteven Rostedt    foreach my $config (keys %config_ignore) {
25430a05c769SSteven Rostedt	print OUT "$config_ignore{$config}\n";
25440a05c769SSteven Rostedt    }
25450a05c769SSteven Rostedt    close(OUT);
25460a05c769SSteven Rostedt
2547fcb3f16aSSteven Rostedt    make_oldconfig;
25480a05c769SSteven Rostedt}
25490a05c769SSteven Rostedt
25500a05c769SSteven Rostedtsub compare_configs {
25510a05c769SSteven Rostedt    my (%a, %b) = @_;
25520a05c769SSteven Rostedt
25530a05c769SSteven Rostedt    foreach my $item (keys %a) {
25540a05c769SSteven Rostedt	if (!defined($b{$item})) {
25550a05c769SSteven Rostedt	    print "diff $item\n";
25560a05c769SSteven Rostedt	    return 1;
25570a05c769SSteven Rostedt	}
25580a05c769SSteven Rostedt	delete $b{$item};
25590a05c769SSteven Rostedt    }
25600a05c769SSteven Rostedt
25610a05c769SSteven Rostedt    my @keys = keys %b;
25620a05c769SSteven Rostedt    if ($#keys) {
25630a05c769SSteven Rostedt	print "diff2 $keys[0]\n";
25640a05c769SSteven Rostedt    }
25650a05c769SSteven Rostedt    return -1 if ($#keys >= 0);
25660a05c769SSteven Rostedt
25670a05c769SSteven Rostedt    return 0;
25680a05c769SSteven Rostedt}
25690a05c769SSteven Rostedt
25700a05c769SSteven Rostedtsub run_config_bisect_test {
25710a05c769SSteven Rostedt    my ($type) = @_;
25720a05c769SSteven Rostedt
25730a05c769SSteven Rostedt    return run_bisect_test $type, "oldconfig";
25740a05c769SSteven Rostedt}
25750a05c769SSteven Rostedt
25760a05c769SSteven Rostedtsub process_passed {
25770a05c769SSteven Rostedt    my (%configs) = @_;
25780a05c769SSteven Rostedt
25790a05c769SSteven Rostedt    doprint "These configs had no failure: (Enabling them for further compiles)\n";
25800a05c769SSteven Rostedt    # Passed! All these configs are part of a good compile.
25810a05c769SSteven Rostedt    # Add them to the min options.
25820a05c769SSteven Rostedt    foreach my $config (keys %configs) {
25830a05c769SSteven Rostedt	if (defined($config_list{$config})) {
25840a05c769SSteven Rostedt	    doprint " removing $config\n";
25850a05c769SSteven Rostedt	    $config_ignore{$config} = $config_list{$config};
25860a05c769SSteven Rostedt	    delete $config_list{$config};
25870a05c769SSteven Rostedt	}
25880a05c769SSteven Rostedt    }
2589f1a27850SSteven Rostedt    doprint "config copied to $outputdir/config_good\n";
2590f1a27850SSteven Rostedt    run_command "cp -f $output_config $outputdir/config_good";
25910a05c769SSteven Rostedt}
25920a05c769SSteven Rostedt
25930a05c769SSteven Rostedtsub process_failed {
25940a05c769SSteven Rostedt    my ($config) = @_;
25950a05c769SSteven Rostedt
25960a05c769SSteven Rostedt    doprint "\n\n***************************************\n";
25970a05c769SSteven Rostedt    doprint "Found bad config: $config\n";
25980a05c769SSteven Rostedt    doprint "***************************************\n\n";
25990a05c769SSteven Rostedt}
26000a05c769SSteven Rostedt
26010a05c769SSteven Rostedtsub run_config_bisect {
26020a05c769SSteven Rostedt
26030a05c769SSteven Rostedt    my @start_list = keys %config_list;
26040a05c769SSteven Rostedt
26050a05c769SSteven Rostedt    if ($#start_list < 0) {
26060a05c769SSteven Rostedt	doprint "No more configs to test!!!\n";
26070a05c769SSteven Rostedt	return -1;
26080a05c769SSteven Rostedt    }
26090a05c769SSteven Rostedt
26100a05c769SSteven Rostedt    doprint "***** RUN TEST ***\n";
2611b5f4aea6SSteven Rostedt    my $type = $config_bisect_type;
26120a05c769SSteven Rostedt    my $ret;
26130a05c769SSteven Rostedt    my %current_config;
26140a05c769SSteven Rostedt
26150a05c769SSteven Rostedt    my $count = $#start_list + 1;
26160a05c769SSteven Rostedt    doprint "  $count configs to test\n";
26170a05c769SSteven Rostedt
26180a05c769SSteven Rostedt    my $half = int($#start_list / 2);
26190a05c769SSteven Rostedt
26200a05c769SSteven Rostedt    do {
26210a05c769SSteven Rostedt	my @tophalf = @start_list[0 .. $half];
26220a05c769SSteven Rostedt
2623cf79fab6SSteven Rostedt	# keep the bottom half off
2624cf79fab6SSteven Rostedt	if ($half < $#start_list) {
2625cf79fab6SSteven Rostedt	    @config_off_tmp = @start_list[$half + 1 .. $#start_list];
2626cf79fab6SSteven Rostedt	} else {
2627cf79fab6SSteven Rostedt	    @config_off_tmp = ();
2628cf79fab6SSteven Rostedt	}
2629cf79fab6SSteven Rostedt
26300a05c769SSteven Rostedt	create_config @tophalf;
26310a05c769SSteven Rostedt	read_current_config \%current_config;
26320a05c769SSteven Rostedt
26330a05c769SSteven Rostedt	$count = $#tophalf + 1;
26340a05c769SSteven Rostedt	doprint "Testing $count configs\n";
26350a05c769SSteven Rostedt	my $found = 0;
26360a05c769SSteven Rostedt	# make sure we test something
26370a05c769SSteven Rostedt	foreach my $config (@tophalf) {
26380a05c769SSteven Rostedt	    if (defined($current_config{$config})) {
26390a05c769SSteven Rostedt		logit " $config\n";
26400a05c769SSteven Rostedt		$found = 1;
26410a05c769SSteven Rostedt	    }
26420a05c769SSteven Rostedt	}
26430a05c769SSteven Rostedt	if (!$found) {
26440a05c769SSteven Rostedt	    # try the other half
26450a05c769SSteven Rostedt	    doprint "Top half produced no set configs, trying bottom half\n";
2646cf79fab6SSteven Rostedt
2647cf79fab6SSteven Rostedt	    # keep the top half off
2648cf79fab6SSteven Rostedt	    @config_off_tmp = @tophalf;
26494c8cc55bSSteven Rostedt	    @tophalf = @start_list[$half + 1 .. $#start_list];
2650cf79fab6SSteven Rostedt
26510a05c769SSteven Rostedt	    create_config @tophalf;
26520a05c769SSteven Rostedt	    read_current_config \%current_config;
26530a05c769SSteven Rostedt	    foreach my $config (@tophalf) {
26540a05c769SSteven Rostedt		if (defined($current_config{$config})) {
26550a05c769SSteven Rostedt		    logit " $config\n";
26560a05c769SSteven Rostedt		    $found = 1;
26570a05c769SSteven Rostedt		}
26580a05c769SSteven Rostedt	    }
26590a05c769SSteven Rostedt	    if (!$found) {
26600a05c769SSteven Rostedt		doprint "Failed: Can't make new config with current configs\n";
26610a05c769SSteven Rostedt		foreach my $config (@start_list) {
26620a05c769SSteven Rostedt		    doprint "  CONFIG: $config\n";
26630a05c769SSteven Rostedt		}
26640a05c769SSteven Rostedt		return -1;
26650a05c769SSteven Rostedt	    }
26660a05c769SSteven Rostedt	    $count = $#tophalf + 1;
26670a05c769SSteven Rostedt	    doprint "Testing $count configs\n";
26680a05c769SSteven Rostedt	}
26690a05c769SSteven Rostedt
26700a05c769SSteven Rostedt	$ret = run_config_bisect_test $type;
2671c960bb9fSSteven Rostedt	if ($bisect_manual) {
2672c960bb9fSSteven Rostedt	    $ret = answer_bisect;
2673c960bb9fSSteven Rostedt	}
26740a05c769SSteven Rostedt	if ($ret) {
26750a05c769SSteven Rostedt	    process_passed %current_config;
26760a05c769SSteven Rostedt	    return 0;
26770a05c769SSteven Rostedt	}
26780a05c769SSteven Rostedt
26790a05c769SSteven Rostedt	doprint "This config had a failure.\n";
26800a05c769SSteven Rostedt	doprint "Removing these configs that were not set in this config:\n";
2681f1a27850SSteven Rostedt	doprint "config copied to $outputdir/config_bad\n";
2682f1a27850SSteven Rostedt	run_command "cp -f $output_config $outputdir/config_bad";
26830a05c769SSteven Rostedt
26840a05c769SSteven Rostedt	# A config exists in this group that was bad.
26850a05c769SSteven Rostedt	foreach my $config (keys %config_list) {
26860a05c769SSteven Rostedt	    if (!defined($current_config{$config})) {
26870a05c769SSteven Rostedt		doprint " removing $config\n";
26880a05c769SSteven Rostedt		delete $config_list{$config};
26890a05c769SSteven Rostedt	    }
26900a05c769SSteven Rostedt	}
26910a05c769SSteven Rostedt
26920a05c769SSteven Rostedt	@start_list = @tophalf;
26930a05c769SSteven Rostedt
26940a05c769SSteven Rostedt	if ($#start_list == 0) {
26950a05c769SSteven Rostedt	    process_failed $start_list[0];
26960a05c769SSteven Rostedt	    return 1;
26970a05c769SSteven Rostedt	}
26980a05c769SSteven Rostedt
26990a05c769SSteven Rostedt	# remove half the configs we are looking at and see if
27000a05c769SSteven Rostedt	# they are good.
27010a05c769SSteven Rostedt	$half = int($#start_list / 2);
27024c8cc55bSSteven Rostedt    } while ($#start_list > 0);
27030a05c769SSteven Rostedt
2704c960bb9fSSteven Rostedt    # we found a single config, try it again unless we are running manually
2705c960bb9fSSteven Rostedt
2706c960bb9fSSteven Rostedt    if ($bisect_manual) {
2707c960bb9fSSteven Rostedt	process_failed $start_list[0];
2708c960bb9fSSteven Rostedt	return 1;
2709c960bb9fSSteven Rostedt    }
2710c960bb9fSSteven Rostedt
27110a05c769SSteven Rostedt    my @tophalf = @start_list[0 .. 0];
27120a05c769SSteven Rostedt
27130a05c769SSteven Rostedt    $ret = run_config_bisect_test $type;
27140a05c769SSteven Rostedt    if ($ret) {
27150a05c769SSteven Rostedt	process_passed %current_config;
27160a05c769SSteven Rostedt	return 0;
27170a05c769SSteven Rostedt    }
27180a05c769SSteven Rostedt
27190a05c769SSteven Rostedt    process_failed $start_list[0];
27200a05c769SSteven Rostedt    return 1;
27210a05c769SSteven Rostedt}
27220a05c769SSteven Rostedt
27230a05c769SSteven Rostedtsub config_bisect {
27240a05c769SSteven Rostedt    my ($i) = @_;
27250a05c769SSteven Rostedt
2726b5f4aea6SSteven Rostedt    my $start_config = $config_bisect;
27270a05c769SSteven Rostedt
27280a05c769SSteven Rostedt    my $tmpconfig = "$tmpdir/use_config";
27290a05c769SSteven Rostedt
273030f75da5SSteven Rostedt    if (defined($config_bisect_good)) {
273130f75da5SSteven Rostedt	process_config_ignore $config_bisect_good;
273230f75da5SSteven Rostedt    }
273330f75da5SSteven Rostedt
27340a05c769SSteven Rostedt    # Make the file with the bad config and the min config
27350a05c769SSteven Rostedt    if (defined($minconfig)) {
27360a05c769SSteven Rostedt	# read the min config for things to ignore
27370a05c769SSteven Rostedt	run_command "cp $minconfig $tmpconfig" or
27380a05c769SSteven Rostedt	    dodie "failed to copy $minconfig to $tmpconfig";
27390a05c769SSteven Rostedt    } else {
27400a05c769SSteven Rostedt	unlink $tmpconfig;
27410a05c769SSteven Rostedt    }
27420a05c769SSteven Rostedt
27430a05c769SSteven Rostedt    if (-f $tmpconfig) {
2744fcb3f16aSSteven Rostedt	load_force_config($tmpconfig);
27450a05c769SSteven Rostedt	process_config_ignore $tmpconfig;
27460a05c769SSteven Rostedt    }
27470a05c769SSteven Rostedt
27480a05c769SSteven Rostedt    # now process the start config
27490a05c769SSteven Rostedt    run_command "cp $start_config $output_config" or
27500a05c769SSteven Rostedt	dodie "failed to copy $start_config to $output_config";
27510a05c769SSteven Rostedt
27520a05c769SSteven Rostedt    # read directly what we want to check
27530a05c769SSteven Rostedt    my %config_check;
27540a05c769SSteven Rostedt    open (IN, $output_config)
2755f9dee311SMasanari Iida	or dodie "failed to open $output_config";
27560a05c769SSteven Rostedt
27570a05c769SSteven Rostedt    while (<IN>) {
27580a05c769SSteven Rostedt	if (/^((CONFIG\S*)=.*)/) {
27590a05c769SSteven Rostedt	    $config_check{$2} = $1;
27600a05c769SSteven Rostedt	}
27610a05c769SSteven Rostedt    }
27620a05c769SSteven Rostedt    close(IN);
27630a05c769SSteven Rostedt
2764250bae8bSSteven Rostedt    # Now run oldconfig with the minconfig
2765fcb3f16aSSteven Rostedt    make_oldconfig;
27660a05c769SSteven Rostedt
27670a05c769SSteven Rostedt    # check to see what we lost (or gained)
27680a05c769SSteven Rostedt    open (IN, $output_config)
27690a05c769SSteven Rostedt	or dodie "Failed to read $start_config";
27700a05c769SSteven Rostedt
27710a05c769SSteven Rostedt    my %removed_configs;
27720a05c769SSteven Rostedt    my %added_configs;
27730a05c769SSteven Rostedt
27740a05c769SSteven Rostedt    while (<IN>) {
27750a05c769SSteven Rostedt	if (/^((CONFIG\S*)=.*)/) {
27760a05c769SSteven Rostedt	    # save off all options
27770a05c769SSteven Rostedt	    $config_set{$2} = $1;
27780a05c769SSteven Rostedt	    if (defined($config_check{$2})) {
27790a05c769SSteven Rostedt		if (defined($config_ignore{$2})) {
27800a05c769SSteven Rostedt		    $removed_configs{$2} = $1;
27810a05c769SSteven Rostedt		} else {
27820a05c769SSteven Rostedt		    $config_list{$2} = $1;
27830a05c769SSteven Rostedt		}
27840a05c769SSteven Rostedt	    } elsif (!defined($config_ignore{$2})) {
27850a05c769SSteven Rostedt		$added_configs{$2} = $1;
27860a05c769SSteven Rostedt		$config_list{$2} = $1;
27870a05c769SSteven Rostedt	    }
2788cf79fab6SSteven Rostedt	} elsif (/^# ((CONFIG\S*).*)/) {
2789cf79fab6SSteven Rostedt	    # Keep these configs disabled
2790cf79fab6SSteven Rostedt	    $config_set{$2} = $1;
2791cf79fab6SSteven Rostedt	    $config_off{$2} = $1;
27920a05c769SSteven Rostedt	}
27930a05c769SSteven Rostedt    }
27940a05c769SSteven Rostedt    close(IN);
27950a05c769SSteven Rostedt
27960a05c769SSteven Rostedt    my @confs = keys %removed_configs;
27970a05c769SSteven Rostedt    if ($#confs >= 0) {
27980a05c769SSteven Rostedt	doprint "Configs overridden by default configs and removed from check:\n";
27990a05c769SSteven Rostedt	foreach my $config (@confs) {
28000a05c769SSteven Rostedt	    doprint " $config\n";
28010a05c769SSteven Rostedt	}
28020a05c769SSteven Rostedt    }
28030a05c769SSteven Rostedt    @confs = keys %added_configs;
28040a05c769SSteven Rostedt    if ($#confs >= 0) {
28050a05c769SSteven Rostedt	doprint "Configs appearing in make oldconfig and added:\n";
28060a05c769SSteven Rostedt	foreach my $config (@confs) {
28070a05c769SSteven Rostedt	    doprint " $config\n";
28080a05c769SSteven Rostedt	}
28090a05c769SSteven Rostedt    }
28100a05c769SSteven Rostedt
28110a05c769SSteven Rostedt    my %config_test;
28120a05c769SSteven Rostedt    my $once = 0;
28130a05c769SSteven Rostedt
2814cf79fab6SSteven Rostedt    @config_off_tmp = ();
2815cf79fab6SSteven Rostedt
28160a05c769SSteven Rostedt    # Sometimes kconfig does weird things. We must make sure
28170a05c769SSteven Rostedt    # that the config we autocreate has everything we need
28180a05c769SSteven Rostedt    # to test, otherwise we may miss testing configs, or
28190a05c769SSteven Rostedt    # may not be able to create a new config.
28200a05c769SSteven Rostedt    # Here we create a config with everything set.
28210a05c769SSteven Rostedt    create_config (keys %config_list);
28220a05c769SSteven Rostedt    read_current_config \%config_test;
28230a05c769SSteven Rostedt    foreach my $config (keys %config_list) {
28240a05c769SSteven Rostedt	if (!defined($config_test{$config})) {
28250a05c769SSteven Rostedt	    if (!$once) {
28260a05c769SSteven Rostedt		$once = 1;
28270a05c769SSteven Rostedt		doprint "Configs not produced by kconfig (will not be checked):\n";
28280a05c769SSteven Rostedt	    }
28290a05c769SSteven Rostedt	    doprint "  $config\n";
28300a05c769SSteven Rostedt	    delete $config_list{$config};
28310a05c769SSteven Rostedt	}
28320a05c769SSteven Rostedt    }
28330a05c769SSteven Rostedt    my $ret;
2834b0918612SSteven Rostedt
2835b0918612SSteven Rostedt    if (defined($config_bisect_check) && $config_bisect_check) {
2836b0918612SSteven Rostedt	doprint " Checking to make sure bad config with min config fails\n";
2837b0918612SSteven Rostedt	create_config keys %config_list;
2838b0918612SSteven Rostedt	$ret = run_config_bisect_test $config_bisect_type;
2839b0918612SSteven Rostedt	if ($ret) {
2840b0918612SSteven Rostedt	    doprint " FAILED! Bad config with min config boots fine\n";
2841b0918612SSteven Rostedt	    return -1;
2842b0918612SSteven Rostedt	}
2843b0918612SSteven Rostedt	doprint " Bad config with min config fails as expected\n";
2844b0918612SSteven Rostedt    }
2845b0918612SSteven Rostedt
28460a05c769SSteven Rostedt    do {
28470a05c769SSteven Rostedt	$ret = run_config_bisect;
28480a05c769SSteven Rostedt    } while (!$ret);
28490a05c769SSteven Rostedt
28500a05c769SSteven Rostedt    return $ret if ($ret < 0);
28515f9b6cedSSteven Rostedt
28525f9b6cedSSteven Rostedt    success $i;
28535f9b6cedSSteven Rostedt}
28545f9b6cedSSteven Rostedt
285527d934b2SSteven Rostedtsub patchcheck_reboot {
285627d934b2SSteven Rostedt    doprint "Reboot and sleep $patchcheck_sleep_time seconds\n";
2857bc7c5803SSteven Rostedt    reboot_to_good $patchcheck_sleep_time;
285827d934b2SSteven Rostedt}
285927d934b2SSteven Rostedt
28606c5ee0beSSteven Rostedtsub patchcheck {
28616c5ee0beSSteven Rostedt    my ($i) = @_;
28626c5ee0beSSteven Rostedt
28636c5ee0beSSteven Rostedt    die "PATCHCHECK_START[$i] not defined\n"
2864b5f4aea6SSteven Rostedt	if (!defined($patchcheck_start));
28656c5ee0beSSteven Rostedt    die "PATCHCHECK_TYPE[$i] not defined\n"
2866b5f4aea6SSteven Rostedt	if (!defined($patchcheck_type));
28676c5ee0beSSteven Rostedt
2868b5f4aea6SSteven Rostedt    my $start = $patchcheck_start;
28696c5ee0beSSteven Rostedt
28706c5ee0beSSteven Rostedt    my $end = "HEAD";
2871b5f4aea6SSteven Rostedt    if (defined($patchcheck_end)) {
2872b5f4aea6SSteven Rostedt	$end = $patchcheck_end;
28736c5ee0beSSteven Rostedt    }
28746c5ee0beSSteven Rostedt
2875a57419b3SSteven Rostedt    # Get the true sha1's since we can use things like HEAD~3
2876a57419b3SSteven Rostedt    $start = get_sha1($start);
2877a57419b3SSteven Rostedt    $end = get_sha1($end);
2878a57419b3SSteven Rostedt
2879b5f4aea6SSteven Rostedt    my $type = $patchcheck_type;
28806c5ee0beSSteven Rostedt
28816c5ee0beSSteven Rostedt    # Can't have a test without having a test to run
28826c5ee0beSSteven Rostedt    if ($type eq "test" && !defined($run_test)) {
28836c5ee0beSSteven Rostedt	$type = "boot";
28846c5ee0beSSteven Rostedt    }
28856c5ee0beSSteven Rostedt
28866c5ee0beSSteven Rostedt    open (IN, "git log --pretty=oneline $end|") or
28876c5ee0beSSteven Rostedt	dodie "could not get git list";
28886c5ee0beSSteven Rostedt
28896c5ee0beSSteven Rostedt    my @list;
28906c5ee0beSSteven Rostedt
28916c5ee0beSSteven Rostedt    while (<IN>) {
28926c5ee0beSSteven Rostedt	chomp;
28936c5ee0beSSteven Rostedt	$list[$#list+1] = $_;
28946c5ee0beSSteven Rostedt	last if (/^$start/);
28956c5ee0beSSteven Rostedt    }
28966c5ee0beSSteven Rostedt    close(IN);
28976c5ee0beSSteven Rostedt
28986c5ee0beSSteven Rostedt    if ($list[$#list] !~ /^$start/) {
28992b7d9b21SSteven Rostedt	fail "SHA1 $start not found";
29006c5ee0beSSteven Rostedt    }
29016c5ee0beSSteven Rostedt
29026c5ee0beSSteven Rostedt    # go backwards in the list
29036c5ee0beSSteven Rostedt    @list = reverse @list;
29046c5ee0beSSteven Rostedt
29056c5ee0beSSteven Rostedt    my $save_clean = $noclean;
29061990207dSSteven Rostedt    my %ignored_warnings;
29071990207dSSteven Rostedt
29081990207dSSteven Rostedt    if (defined($ignore_warnings)) {
29091990207dSSteven Rostedt	foreach my $sha1 (split /\s+/, $ignore_warnings) {
29101990207dSSteven Rostedt	    $ignored_warnings{$sha1} = 1;
29111990207dSSteven Rostedt	}
29121990207dSSteven Rostedt    }
29136c5ee0beSSteven Rostedt
29146c5ee0beSSteven Rostedt    $in_patchcheck = 1;
29156c5ee0beSSteven Rostedt    foreach my $item (@list) {
29166c5ee0beSSteven Rostedt	my $sha1 = $item;
29176c5ee0beSSteven Rostedt	$sha1 =~ s/^([[:xdigit:]]+).*/$1/;
29186c5ee0beSSteven Rostedt
29196c5ee0beSSteven Rostedt	doprint "\nProcessing commit $item\n\n";
29206c5ee0beSSteven Rostedt
29216c5ee0beSSteven Rostedt	run_command "git checkout $sha1" or
29226c5ee0beSSteven Rostedt	    die "Failed to checkout $sha1";
29236c5ee0beSSteven Rostedt
29246c5ee0beSSteven Rostedt	# only clean on the first and last patch
29256c5ee0beSSteven Rostedt	if ($item eq $list[0] ||
29266c5ee0beSSteven Rostedt	    $item eq $list[$#list]) {
29276c5ee0beSSteven Rostedt	    $noclean = $save_clean;
29286c5ee0beSSteven Rostedt	} else {
29296c5ee0beSSteven Rostedt	    $noclean = 1;
29306c5ee0beSSteven Rostedt	}
29316c5ee0beSSteven Rostedt
29326c5ee0beSSteven Rostedt	if (defined($minconfig)) {
29332b7d9b21SSteven Rostedt	    build "useconfig:$minconfig" or return 0;
29346c5ee0beSSteven Rostedt	} else {
29356c5ee0beSSteven Rostedt	    # ?? no config to use?
29362b7d9b21SSteven Rostedt	    build "oldconfig" or return 0;
29376c5ee0beSSteven Rostedt	}
29386c5ee0beSSteven Rostedt
29391990207dSSteven Rostedt
29401990207dSSteven Rostedt	if (!defined($ignored_warnings{$sha1})) {
29412b7d9b21SSteven Rostedt	    check_buildlog $sha1 or return 0;
29421990207dSSteven Rostedt	}
29436c5ee0beSSteven Rostedt
29446c5ee0beSSteven Rostedt	next if ($type eq "build");
29456c5ee0beSSteven Rostedt
29467faafbd6SSteven Rostedt	my $failed = 0;
29477faafbd6SSteven Rostedt
2948ddf607e5SSteven Rostedt	start_monitor_and_boot or $failed = 1;
29497faafbd6SSteven Rostedt
29507faafbd6SSteven Rostedt	if (!$failed && $type ne "boot"){
29517faafbd6SSteven Rostedt	    do_run_test or $failed = 1;
29527faafbd6SSteven Rostedt	}
29537faafbd6SSteven Rostedt	end_monitor;
29547faafbd6SSteven Rostedt	return 0 if ($failed);
29557faafbd6SSteven Rostedt
295627d934b2SSteven Rostedt	patchcheck_reboot;
295727d934b2SSteven Rostedt
29586c5ee0beSSteven Rostedt    }
29596c5ee0beSSteven Rostedt    $in_patchcheck = 0;
29606c5ee0beSSteven Rostedt    success $i;
29612b7d9b21SSteven Rostedt
29622b7d9b21SSteven Rostedt    return 1;
29636c5ee0beSSteven Rostedt}
29646c5ee0beSSteven Rostedt
2965b9066f6cSSteven Rostedtmy %depends;
2966ac6974c7SSteven Rostedtmy %depcount;
2967b9066f6cSSteven Rostedtmy $iflevel = 0;
2968b9066f6cSSteven Rostedtmy @ifdeps;
2969b9066f6cSSteven Rostedt
2970b9066f6cSSteven Rostedt# prevent recursion
2971b9066f6cSSteven Rostedtmy %read_kconfigs;
2972b9066f6cSSteven Rostedt
2973ac6974c7SSteven Rostedtsub add_dep {
2974ac6974c7SSteven Rostedt    # $config depends on $dep
2975ac6974c7SSteven Rostedt    my ($config, $dep) = @_;
2976ac6974c7SSteven Rostedt
2977ac6974c7SSteven Rostedt    if (defined($depends{$config})) {
2978ac6974c7SSteven Rostedt	$depends{$config} .= " " . $dep;
2979ac6974c7SSteven Rostedt    } else {
2980ac6974c7SSteven Rostedt	$depends{$config} = $dep;
2981ac6974c7SSteven Rostedt    }
2982ac6974c7SSteven Rostedt
2983ac6974c7SSteven Rostedt    # record the number of configs depending on $dep
2984ac6974c7SSteven Rostedt    if (defined $depcount{$dep}) {
2985ac6974c7SSteven Rostedt	$depcount{$dep}++;
2986ac6974c7SSteven Rostedt    } else {
2987ac6974c7SSteven Rostedt	$depcount{$dep} = 1;
2988ac6974c7SSteven Rostedt    }
2989ac6974c7SSteven Rostedt}
2990ac6974c7SSteven Rostedt
2991b9066f6cSSteven Rostedt# taken from streamline_config.pl
2992b9066f6cSSteven Rostedtsub read_kconfig {
2993b9066f6cSSteven Rostedt    my ($kconfig) = @_;
2994b9066f6cSSteven Rostedt
2995b9066f6cSSteven Rostedt    my $state = "NONE";
2996b9066f6cSSteven Rostedt    my $config;
2997b9066f6cSSteven Rostedt    my @kconfigs;
2998b9066f6cSSteven Rostedt
2999b9066f6cSSteven Rostedt    my $cont = 0;
3000b9066f6cSSteven Rostedt    my $line;
3001b9066f6cSSteven Rostedt
3002b9066f6cSSteven Rostedt
3003b9066f6cSSteven Rostedt    if (! -f $kconfig) {
3004b9066f6cSSteven Rostedt	doprint "file $kconfig does not exist, skipping\n";
3005b9066f6cSSteven Rostedt	return;
3006b9066f6cSSteven Rostedt    }
3007b9066f6cSSteven Rostedt
3008b9066f6cSSteven Rostedt    open(KIN, "$kconfig")
3009b9066f6cSSteven Rostedt	or die "Can't open $kconfig";
3010b9066f6cSSteven Rostedt    while (<KIN>) {
3011b9066f6cSSteven Rostedt	chomp;
3012b9066f6cSSteven Rostedt
3013b9066f6cSSteven Rostedt	# Make sure that lines ending with \ continue
3014b9066f6cSSteven Rostedt	if ($cont) {
3015b9066f6cSSteven Rostedt	    $_ = $line . " " . $_;
3016b9066f6cSSteven Rostedt	}
3017b9066f6cSSteven Rostedt
3018b9066f6cSSteven Rostedt	if (s/\\$//) {
3019b9066f6cSSteven Rostedt	    $cont = 1;
3020b9066f6cSSteven Rostedt	    $line = $_;
3021b9066f6cSSteven Rostedt	    next;
3022b9066f6cSSteven Rostedt	}
3023b9066f6cSSteven Rostedt
3024b9066f6cSSteven Rostedt	$cont = 0;
3025b9066f6cSSteven Rostedt
3026b9066f6cSSteven Rostedt	# collect any Kconfig sources
3027b9066f6cSSteven Rostedt	if (/^source\s*"(.*)"/) {
3028b9066f6cSSteven Rostedt	    $kconfigs[$#kconfigs+1] = $1;
3029b9066f6cSSteven Rostedt	}
3030b9066f6cSSteven Rostedt
3031b9066f6cSSteven Rostedt	# configs found
3032b9066f6cSSteven Rostedt	if (/^\s*(menu)?config\s+(\S+)\s*$/) {
3033b9066f6cSSteven Rostedt	    $state = "NEW";
3034b9066f6cSSteven Rostedt	    $config = $2;
3035b9066f6cSSteven Rostedt
3036b9066f6cSSteven Rostedt	    for (my $i = 0; $i < $iflevel; $i++) {
3037ac6974c7SSteven Rostedt		add_dep $config, $ifdeps[$i];
3038b9066f6cSSteven Rostedt	    }
3039b9066f6cSSteven Rostedt
3040b9066f6cSSteven Rostedt	# collect the depends for the config
3041b9066f6cSSteven Rostedt	} elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) {
3042b9066f6cSSteven Rostedt
3043ac6974c7SSteven Rostedt	    add_dep $config, $1;
3044b9066f6cSSteven Rostedt
3045b9066f6cSSteven Rostedt	# Get the configs that select this config
3046ac6974c7SSteven Rostedt	} elsif ($state eq "NEW" && /^\s*select\s+(\S+)/) {
3047ac6974c7SSteven Rostedt
3048ac6974c7SSteven Rostedt	    # selected by depends on config
3049ac6974c7SSteven Rostedt	    add_dep $1, $config;
3050b9066f6cSSteven Rostedt
3051b9066f6cSSteven Rostedt	# Check for if statements
3052b9066f6cSSteven Rostedt	} elsif (/^if\s+(.*\S)\s*$/) {
3053b9066f6cSSteven Rostedt	    my $deps = $1;
3054b9066f6cSSteven Rostedt	    # remove beginning and ending non text
3055b9066f6cSSteven Rostedt	    $deps =~ s/^[^a-zA-Z0-9_]*//;
3056b9066f6cSSteven Rostedt	    $deps =~ s/[^a-zA-Z0-9_]*$//;
3057b9066f6cSSteven Rostedt
3058b9066f6cSSteven Rostedt	    my @deps = split /[^a-zA-Z0-9_]+/, $deps;
3059b9066f6cSSteven Rostedt
3060b9066f6cSSteven Rostedt	    $ifdeps[$iflevel++] = join ':', @deps;
3061b9066f6cSSteven Rostedt
3062b9066f6cSSteven Rostedt	} elsif (/^endif/) {
3063b9066f6cSSteven Rostedt
3064b9066f6cSSteven Rostedt	    $iflevel-- if ($iflevel);
3065b9066f6cSSteven Rostedt
3066b9066f6cSSteven Rostedt	# stop on "help"
3067b9066f6cSSteven Rostedt	} elsif (/^\s*help\s*$/) {
3068b9066f6cSSteven Rostedt	    $state = "NONE";
3069b9066f6cSSteven Rostedt	}
3070b9066f6cSSteven Rostedt    }
3071b9066f6cSSteven Rostedt    close(KIN);
3072b9066f6cSSteven Rostedt
3073b9066f6cSSteven Rostedt    # read in any configs that were found.
3074b9066f6cSSteven Rostedt    foreach $kconfig (@kconfigs) {
3075b9066f6cSSteven Rostedt	if (!defined($read_kconfigs{$kconfig})) {
3076b9066f6cSSteven Rostedt	    $read_kconfigs{$kconfig} = 1;
3077b9066f6cSSteven Rostedt	    read_kconfig("$builddir/$kconfig");
3078b9066f6cSSteven Rostedt	}
3079b9066f6cSSteven Rostedt    }
3080b9066f6cSSteven Rostedt}
3081b9066f6cSSteven Rostedt
3082b9066f6cSSteven Rostedtsub read_depends {
3083b9066f6cSSteven Rostedt    # find out which arch this is by the kconfig file
3084b9066f6cSSteven Rostedt    open (IN, $output_config)
3085b9066f6cSSteven Rostedt	or dodie "Failed to read $output_config";
3086b9066f6cSSteven Rostedt    my $arch;
3087b9066f6cSSteven Rostedt    while (<IN>) {
3088b9066f6cSSteven Rostedt	if (m,Linux/(\S+)\s+\S+\s+Kernel Configuration,) {
3089b9066f6cSSteven Rostedt	    $arch = $1;
3090b9066f6cSSteven Rostedt	    last;
3091b9066f6cSSteven Rostedt	}
3092b9066f6cSSteven Rostedt    }
3093b9066f6cSSteven Rostedt    close IN;
3094b9066f6cSSteven Rostedt
3095b9066f6cSSteven Rostedt    if (!defined($arch)) {
3096b9066f6cSSteven Rostedt	doprint "Could not find arch from config file\n";
3097b9066f6cSSteven Rostedt	doprint "no dependencies used\n";
3098b9066f6cSSteven Rostedt	return;
3099b9066f6cSSteven Rostedt    }
3100b9066f6cSSteven Rostedt
3101b9066f6cSSteven Rostedt    # arch is really the subarch, we need to know
3102b9066f6cSSteven Rostedt    # what directory to look at.
3103b9066f6cSSteven Rostedt    if ($arch eq "i386" || $arch eq "x86_64") {
3104b9066f6cSSteven Rostedt	$arch = "x86";
3105b9066f6cSSteven Rostedt    } elsif ($arch =~ /^tile/) {
3106b9066f6cSSteven Rostedt	$arch = "tile";
3107b9066f6cSSteven Rostedt    }
3108b9066f6cSSteven Rostedt
3109b9066f6cSSteven Rostedt    my $kconfig = "$builddir/arch/$arch/Kconfig";
3110b9066f6cSSteven Rostedt
3111b9066f6cSSteven Rostedt    if (! -f $kconfig && $arch =~ /\d$/) {
3112b9066f6cSSteven Rostedt	my $orig = $arch;
3113b9066f6cSSteven Rostedt 	# some subarchs have numbers, truncate them
3114b9066f6cSSteven Rostedt	$arch =~ s/\d*$//;
3115b9066f6cSSteven Rostedt	$kconfig = "$builddir/arch/$arch/Kconfig";
3116b9066f6cSSteven Rostedt	if (! -f $kconfig) {
3117b9066f6cSSteven Rostedt	    doprint "No idea what arch dir $orig is for\n";
3118b9066f6cSSteven Rostedt	    doprint "no dependencies used\n";
3119b9066f6cSSteven Rostedt	    return;
3120b9066f6cSSteven Rostedt	}
3121b9066f6cSSteven Rostedt    }
3122b9066f6cSSteven Rostedt
3123b9066f6cSSteven Rostedt    read_kconfig($kconfig);
3124b9066f6cSSteven Rostedt}
3125b9066f6cSSteven Rostedt
31264c4ab120SSteven Rostedtsub read_config_list {
31274c4ab120SSteven Rostedt    my ($config) = @_;
31284c4ab120SSteven Rostedt
31294c4ab120SSteven Rostedt    open (IN, $config)
31304c4ab120SSteven Rostedt	or dodie "Failed to read $config";
31314c4ab120SSteven Rostedt
31324c4ab120SSteven Rostedt    while (<IN>) {
31334c4ab120SSteven Rostedt	if (/^((CONFIG\S*)=.*)/) {
31344c4ab120SSteven Rostedt	    if (!defined($config_ignore{$2})) {
31354c4ab120SSteven Rostedt		$config_list{$2} = $1;
31364c4ab120SSteven Rostedt	    }
31374c4ab120SSteven Rostedt	}
31384c4ab120SSteven Rostedt    }
31394c4ab120SSteven Rostedt
31404c4ab120SSteven Rostedt    close(IN);
31414c4ab120SSteven Rostedt}
31424c4ab120SSteven Rostedt
31434c4ab120SSteven Rostedtsub read_output_config {
31444c4ab120SSteven Rostedt    my ($config) = @_;
31454c4ab120SSteven Rostedt
31464c4ab120SSteven Rostedt    assign_configs \%config_ignore, $config;
31474c4ab120SSteven Rostedt}
31484c4ab120SSteven Rostedt
31494c4ab120SSteven Rostedtsub make_new_config {
31504c4ab120SSteven Rostedt    my @configs = @_;
31514c4ab120SSteven Rostedt
31524c4ab120SSteven Rostedt    open (OUT, ">$output_config")
31534c4ab120SSteven Rostedt	or dodie "Failed to write $output_config";
31544c4ab120SSteven Rostedt
31554c4ab120SSteven Rostedt    foreach my $config (@configs) {
31564c4ab120SSteven Rostedt	print OUT "$config\n";
31574c4ab120SSteven Rostedt    }
31584c4ab120SSteven Rostedt    close OUT;
31594c4ab120SSteven Rostedt}
31604c4ab120SSteven Rostedt
3161ac6974c7SSteven Rostedtsub chomp_config {
3162ac6974c7SSteven Rostedt    my ($config) = @_;
3163ac6974c7SSteven Rostedt
3164ac6974c7SSteven Rostedt    $config =~ s/CONFIG_//;
3165ac6974c7SSteven Rostedt
3166ac6974c7SSteven Rostedt    return $config;
3167ac6974c7SSteven Rostedt}
3168ac6974c7SSteven Rostedt
3169b9066f6cSSteven Rostedtsub get_depends {
3170b9066f6cSSteven Rostedt    my ($dep) = @_;
3171b9066f6cSSteven Rostedt
3172ac6974c7SSteven Rostedt    my $kconfig = chomp_config $dep;
3173b9066f6cSSteven Rostedt
3174b9066f6cSSteven Rostedt    $dep = $depends{"$kconfig"};
3175b9066f6cSSteven Rostedt
3176b9066f6cSSteven Rostedt    # the dep string we have saves the dependencies as they
3177b9066f6cSSteven Rostedt    # were found, including expressions like ! && ||. We
3178b9066f6cSSteven Rostedt    # want to split this out into just an array of configs.
3179b9066f6cSSteven Rostedt
3180b9066f6cSSteven Rostedt    my $valid = "A-Za-z_0-9";
3181b9066f6cSSteven Rostedt
3182b9066f6cSSteven Rostedt    my @configs;
3183b9066f6cSSteven Rostedt
3184b9066f6cSSteven Rostedt    while ($dep =~ /[$valid]/) {
3185b9066f6cSSteven Rostedt
3186b9066f6cSSteven Rostedt	if ($dep =~ /^[^$valid]*([$valid]+)/) {
3187b9066f6cSSteven Rostedt	    my $conf = "CONFIG_" . $1;
3188b9066f6cSSteven Rostedt
3189b9066f6cSSteven Rostedt	    $configs[$#configs + 1] = $conf;
3190b9066f6cSSteven Rostedt
3191b9066f6cSSteven Rostedt	    $dep =~ s/^[^$valid]*[$valid]+//;
3192b9066f6cSSteven Rostedt	} else {
3193b9066f6cSSteven Rostedt	    die "this should never happen";
3194b9066f6cSSteven Rostedt	}
3195b9066f6cSSteven Rostedt    }
3196b9066f6cSSteven Rostedt
3197b9066f6cSSteven Rostedt    return @configs;
3198b9066f6cSSteven Rostedt}
3199b9066f6cSSteven Rostedt
3200b9066f6cSSteven Rostedtmy %min_configs;
3201b9066f6cSSteven Rostedtmy %keep_configs;
320243d1b651SSteven Rostedtmy %save_configs;
3203b9066f6cSSteven Rostedtmy %processed_configs;
3204b9066f6cSSteven Rostedtmy %nochange_config;
3205b9066f6cSSteven Rostedt
3206b9066f6cSSteven Rostedtsub test_this_config {
3207b9066f6cSSteven Rostedt    my ($config) = @_;
3208b9066f6cSSteven Rostedt
3209b9066f6cSSteven Rostedt    my $found;
3210b9066f6cSSteven Rostedt
3211b9066f6cSSteven Rostedt    # if we already processed this config, skip it
3212b9066f6cSSteven Rostedt    if (defined($processed_configs{$config})) {
3213b9066f6cSSteven Rostedt	return undef;
3214b9066f6cSSteven Rostedt    }
3215b9066f6cSSteven Rostedt    $processed_configs{$config} = 1;
3216b9066f6cSSteven Rostedt
3217b9066f6cSSteven Rostedt    # if this config failed during this round, skip it
3218b9066f6cSSteven Rostedt    if (defined($nochange_config{$config})) {
3219b9066f6cSSteven Rostedt	return undef;
3220b9066f6cSSteven Rostedt    }
3221b9066f6cSSteven Rostedt
3222ac6974c7SSteven Rostedt    my $kconfig = chomp_config $config;
3223b9066f6cSSteven Rostedt
3224b9066f6cSSteven Rostedt    # Test dependencies first
3225b9066f6cSSteven Rostedt    if (defined($depends{"$kconfig"})) {
3226b9066f6cSSteven Rostedt	my @parents = get_depends $config;
3227b9066f6cSSteven Rostedt	foreach my $parent (@parents) {
3228b9066f6cSSteven Rostedt	    # if the parent is in the min config, check it first
3229b9066f6cSSteven Rostedt	    next if (!defined($min_configs{$parent}));
3230b9066f6cSSteven Rostedt	    $found = test_this_config($parent);
3231b9066f6cSSteven Rostedt	    if (defined($found)) {
3232b9066f6cSSteven Rostedt		return $found;
3233b9066f6cSSteven Rostedt	    }
3234b9066f6cSSteven Rostedt	}
3235b9066f6cSSteven Rostedt    }
3236b9066f6cSSteven Rostedt
3237b9066f6cSSteven Rostedt    # Remove this config from the list of configs
3238b9066f6cSSteven Rostedt    # do a make oldnoconfig and then read the resulting
3239b9066f6cSSteven Rostedt    # .config to make sure it is missing the config that
3240b9066f6cSSteven Rostedt    # we had before
3241b9066f6cSSteven Rostedt    my %configs = %min_configs;
3242b9066f6cSSteven Rostedt    delete $configs{$config};
3243b9066f6cSSteven Rostedt    make_new_config ((values %configs), (values %keep_configs));
3244b9066f6cSSteven Rostedt    make_oldconfig;
3245b9066f6cSSteven Rostedt    undef %configs;
3246b9066f6cSSteven Rostedt    assign_configs \%configs, $output_config;
3247b9066f6cSSteven Rostedt
3248b9066f6cSSteven Rostedt    return $config if (!defined($configs{$config}));
3249b9066f6cSSteven Rostedt
3250b9066f6cSSteven Rostedt    doprint "disabling config $config did not change .config\n";
3251b9066f6cSSteven Rostedt
3252b9066f6cSSteven Rostedt    $nochange_config{$config} = 1;
3253b9066f6cSSteven Rostedt
3254b9066f6cSSteven Rostedt    return undef;
3255b9066f6cSSteven Rostedt}
3256b9066f6cSSteven Rostedt
32574c4ab120SSteven Rostedtsub make_min_config {
32584c4ab120SSteven Rostedt    my ($i) = @_;
32594c4ab120SSteven Rostedt
3260ccc513b6SSteven Rostedt    my $type = $minconfig_type;
3261ccc513b6SSteven Rostedt    if ($type ne "boot" && $type ne "test") {
3262ccc513b6SSteven Rostedt	fail "Invalid MIN_CONFIG_TYPE '$minconfig_type'\n" .
3263ccc513b6SSteven Rostedt	    " make_min_config works only with 'boot' and 'test'\n" and return;
3264ccc513b6SSteven Rostedt    }
3265ccc513b6SSteven Rostedt
32664c4ab120SSteven Rostedt    if (!defined($output_minconfig)) {
32674c4ab120SSteven Rostedt	fail "OUTPUT_MIN_CONFIG not defined" and return;
32684c4ab120SSteven Rostedt    }
326935ce5952SSteven Rostedt
327035ce5952SSteven Rostedt    # If output_minconfig exists, and the start_minconfig
327135ce5952SSteven Rostedt    # came from min_config, than ask if we should use
327235ce5952SSteven Rostedt    # that instead.
327335ce5952SSteven Rostedt    if (-f $output_minconfig && !$start_minconfig_defined) {
327435ce5952SSteven Rostedt	print "$output_minconfig exists\n";
327543de3316SSteven Rostedt	if (!defined($use_output_minconfig)) {
327635ce5952SSteven Rostedt	    if (read_yn " Use it as minconfig?") {
327735ce5952SSteven Rostedt		$start_minconfig = $output_minconfig;
327835ce5952SSteven Rostedt	    }
327943de3316SSteven Rostedt	} elsif ($use_output_minconfig > 0) {
328043de3316SSteven Rostedt	    doprint "Using $output_minconfig as MIN_CONFIG\n";
328143de3316SSteven Rostedt	    $start_minconfig = $output_minconfig;
328243de3316SSteven Rostedt	} else {
328343de3316SSteven Rostedt	    doprint "Set to still use MIN_CONFIG as starting point\n";
328443de3316SSteven Rostedt	}
328535ce5952SSteven Rostedt    }
328635ce5952SSteven Rostedt
32874c4ab120SSteven Rostedt    if (!defined($start_minconfig)) {
32884c4ab120SSteven Rostedt	fail "START_MIN_CONFIG or MIN_CONFIG not defined" and return;
32894c4ab120SSteven Rostedt    }
32904c4ab120SSteven Rostedt
329135ce5952SSteven Rostedt    my $temp_config = "$tmpdir/temp_config";
329235ce5952SSteven Rostedt
32934c4ab120SSteven Rostedt    # First things first. We build an allnoconfig to find
32944c4ab120SSteven Rostedt    # out what the defaults are that we can't touch.
32954c4ab120SSteven Rostedt    # Some are selections, but we really can't handle selections.
32964c4ab120SSteven Rostedt
32974c4ab120SSteven Rostedt    my $save_minconfig = $minconfig;
32984c4ab120SSteven Rostedt    undef $minconfig;
32994c4ab120SSteven Rostedt
33004c4ab120SSteven Rostedt    run_command "$make allnoconfig" or return 0;
33014c4ab120SSteven Rostedt
3302b9066f6cSSteven Rostedt    read_depends;
3303b9066f6cSSteven Rostedt
33044c4ab120SSteven Rostedt    process_config_ignore $output_config;
3305b9066f6cSSteven Rostedt
330643d1b651SSteven Rostedt    undef %save_configs;
3307b9066f6cSSteven Rostedt    undef %min_configs;
33084c4ab120SSteven Rostedt
33094c4ab120SSteven Rostedt    if (defined($ignore_config)) {
33104c4ab120SSteven Rostedt	# make sure the file exists
33114c4ab120SSteven Rostedt	`touch $ignore_config`;
331243d1b651SSteven Rostedt	assign_configs \%save_configs, $ignore_config;
33134c4ab120SSteven Rostedt    }
33144c4ab120SSteven Rostedt
331543d1b651SSteven Rostedt    %keep_configs = %save_configs;
331643d1b651SSteven Rostedt
33174c4ab120SSteven Rostedt    doprint "Load initial configs from $start_minconfig\n";
33184c4ab120SSteven Rostedt
33194c4ab120SSteven Rostedt    # Look at the current min configs, and save off all the
33204c4ab120SSteven Rostedt    # ones that were set via the allnoconfig
33214c4ab120SSteven Rostedt    assign_configs \%min_configs, $start_minconfig;
33224c4ab120SSteven Rostedt
33234c4ab120SSteven Rostedt    my @config_keys = keys %min_configs;
33244c4ab120SSteven Rostedt
3325ac6974c7SSteven Rostedt    # All configs need a depcount
3326ac6974c7SSteven Rostedt    foreach my $config (@config_keys) {
3327ac6974c7SSteven Rostedt	my $kconfig = chomp_config $config;
3328ac6974c7SSteven Rostedt	if (!defined $depcount{$kconfig}) {
3329ac6974c7SSteven Rostedt		$depcount{$kconfig} = 0;
3330ac6974c7SSteven Rostedt	}
3331ac6974c7SSteven Rostedt    }
3332ac6974c7SSteven Rostedt
33334c4ab120SSteven Rostedt    # Remove anything that was set by the make allnoconfig
33344c4ab120SSteven Rostedt    # we shouldn't need them as they get set for us anyway.
33354c4ab120SSteven Rostedt    foreach my $config (@config_keys) {
33364c4ab120SSteven Rostedt	# Remove anything in the ignore_config
33374c4ab120SSteven Rostedt	if (defined($keep_configs{$config})) {
33384c4ab120SSteven Rostedt	    my $file = $ignore_config;
33394c4ab120SSteven Rostedt	    $file =~ s,.*/(.*?)$,$1,;
33404c4ab120SSteven Rostedt	    doprint "$config set by $file ... ignored\n";
33414c4ab120SSteven Rostedt	    delete $min_configs{$config};
33424c4ab120SSteven Rostedt	    next;
33434c4ab120SSteven Rostedt	}
33444c4ab120SSteven Rostedt	# But make sure the settings are the same. If a min config
33454c4ab120SSteven Rostedt	# sets a selection, we do not want to get rid of it if
33464c4ab120SSteven Rostedt	# it is not the same as what we have. Just move it into
33474c4ab120SSteven Rostedt	# the keep configs.
33484c4ab120SSteven Rostedt	if (defined($config_ignore{$config})) {
33494c4ab120SSteven Rostedt	    if ($config_ignore{$config} ne $min_configs{$config}) {
33504c4ab120SSteven Rostedt		doprint "$config is in allnoconfig as '$config_ignore{$config}'";
33514c4ab120SSteven Rostedt		doprint " but it is '$min_configs{$config}' in minconfig .. keeping\n";
33524c4ab120SSteven Rostedt		$keep_configs{$config} = $min_configs{$config};
33534c4ab120SSteven Rostedt	    } else {
33544c4ab120SSteven Rostedt		doprint "$config set by allnoconfig ... ignored\n";
33554c4ab120SSteven Rostedt	    }
33564c4ab120SSteven Rostedt	    delete $min_configs{$config};
33574c4ab120SSteven Rostedt	}
33584c4ab120SSteven Rostedt    }
33594c4ab120SSteven Rostedt
33604c4ab120SSteven Rostedt    my $done = 0;
3361b9066f6cSSteven Rostedt    my $take_two = 0;
33624c4ab120SSteven Rostedt
33634c4ab120SSteven Rostedt    while (!$done) {
33644c4ab120SSteven Rostedt
33654c4ab120SSteven Rostedt	my $config;
33664c4ab120SSteven Rostedt	my $found;
33674c4ab120SSteven Rostedt
33684c4ab120SSteven Rostedt	# Now disable each config one by one and do a make oldconfig
33694c4ab120SSteven Rostedt	# till we find a config that changes our list.
33704c4ab120SSteven Rostedt
33714c4ab120SSteven Rostedt	my @test_configs = keys %min_configs;
3372ac6974c7SSteven Rostedt
3373ac6974c7SSteven Rostedt	# Sort keys by who is most dependent on
3374ac6974c7SSteven Rostedt	@test_configs = sort  { $depcount{chomp_config($b)} <=> $depcount{chomp_config($a)} }
3375ac6974c7SSteven Rostedt			  @test_configs ;
3376ac6974c7SSteven Rostedt
3377ac6974c7SSteven Rostedt	# Put configs that did not modify the config at the end.
33784c4ab120SSteven Rostedt	my $reset = 1;
33794c4ab120SSteven Rostedt	for (my $i = 0; $i < $#test_configs; $i++) {
33804c4ab120SSteven Rostedt	    if (!defined($nochange_config{$test_configs[0]})) {
33814c4ab120SSteven Rostedt		$reset = 0;
33824c4ab120SSteven Rostedt		last;
33834c4ab120SSteven Rostedt	    }
33844c4ab120SSteven Rostedt	    # This config didn't change the .config last time.
33854c4ab120SSteven Rostedt	    # Place it at the end
33864c4ab120SSteven Rostedt	    my $config = shift @test_configs;
33874c4ab120SSteven Rostedt	    push @test_configs, $config;
33884c4ab120SSteven Rostedt	}
33894c4ab120SSteven Rostedt
33904c4ab120SSteven Rostedt	# if every test config has failed to modify the .config file
33914c4ab120SSteven Rostedt	# in the past, then reset and start over.
33924c4ab120SSteven Rostedt	if ($reset) {
33934c4ab120SSteven Rostedt	    undef %nochange_config;
33944c4ab120SSteven Rostedt	}
33954c4ab120SSteven Rostedt
3396b9066f6cSSteven Rostedt	undef %processed_configs;
3397b9066f6cSSteven Rostedt
33984c4ab120SSteven Rostedt	foreach my $config (@test_configs) {
33994c4ab120SSteven Rostedt
3400b9066f6cSSteven Rostedt	    $found = test_this_config $config;
34014c4ab120SSteven Rostedt
3402b9066f6cSSteven Rostedt	    last if (defined($found));
34034c4ab120SSteven Rostedt
34044c4ab120SSteven Rostedt	    # oh well, try another config
34054c4ab120SSteven Rostedt	}
34064c4ab120SSteven Rostedt
34074c4ab120SSteven Rostedt	if (!defined($found)) {
3408b9066f6cSSteven Rostedt	    # we could have failed due to the nochange_config hash
3409b9066f6cSSteven Rostedt	    # reset and try again
3410b9066f6cSSteven Rostedt	    if (!$take_two) {
3411b9066f6cSSteven Rostedt		undef %nochange_config;
3412b9066f6cSSteven Rostedt		$take_two = 1;
3413b9066f6cSSteven Rostedt		next;
3414b9066f6cSSteven Rostedt	    }
34154c4ab120SSteven Rostedt	    doprint "No more configs found that we can disable\n";
34164c4ab120SSteven Rostedt	    $done = 1;
34174c4ab120SSteven Rostedt	    last;
34184c4ab120SSteven Rostedt	}
3419b9066f6cSSteven Rostedt	$take_two = 0;
34204c4ab120SSteven Rostedt
34214c4ab120SSteven Rostedt	$config = $found;
34224c4ab120SSteven Rostedt
34234c4ab120SSteven Rostedt	doprint "Test with $config disabled\n";
34244c4ab120SSteven Rostedt
34254c4ab120SSteven Rostedt	# set in_bisect to keep build and monitor from dieing
34264c4ab120SSteven Rostedt	$in_bisect = 1;
34274c4ab120SSteven Rostedt
34284c4ab120SSteven Rostedt	my $failed = 0;
3429bf1c95abSSteven Rostedt	build "oldconfig" or $failed = 1;
3430bf1c95abSSteven Rostedt	if (!$failed) {
34314c4ab120SSteven Rostedt		start_monitor_and_boot or $failed = 1;
3432ccc513b6SSteven Rostedt
3433ccc513b6SSteven Rostedt		if ($type eq "test" && !$failed) {
3434ccc513b6SSteven Rostedt		    do_run_test or $failed = 1;
3435ccc513b6SSteven Rostedt		}
3436ccc513b6SSteven Rostedt
34374c4ab120SSteven Rostedt		end_monitor;
3438bf1c95abSSteven Rostedt	}
34394c4ab120SSteven Rostedt
34404c4ab120SSteven Rostedt	$in_bisect = 0;
34414c4ab120SSteven Rostedt
34424c4ab120SSteven Rostedt	if ($failed) {
3443b9066f6cSSteven Rostedt	    doprint "$min_configs{$config} is needed to boot the box... keeping\n";
34444c4ab120SSteven Rostedt	    # this config is needed, add it to the ignore list.
34454c4ab120SSteven Rostedt	    $keep_configs{$config} = $min_configs{$config};
344643d1b651SSteven Rostedt	    $save_configs{$config} = $min_configs{$config};
34474c4ab120SSteven Rostedt	    delete $min_configs{$config};
344835ce5952SSteven Rostedt
344935ce5952SSteven Rostedt	    # update new ignore configs
345035ce5952SSteven Rostedt	    if (defined($ignore_config)) {
345135ce5952SSteven Rostedt		open (OUT, ">$temp_config")
345235ce5952SSteven Rostedt		    or die "Can't write to $temp_config";
345343d1b651SSteven Rostedt		foreach my $config (keys %save_configs) {
345443d1b651SSteven Rostedt		    print OUT "$save_configs{$config}\n";
345535ce5952SSteven Rostedt		}
345635ce5952SSteven Rostedt		close OUT;
345735ce5952SSteven Rostedt		run_command "mv $temp_config $ignore_config" or
345835ce5952SSteven Rostedt		    dodie "failed to copy update to $ignore_config";
345935ce5952SSteven Rostedt	    }
346035ce5952SSteven Rostedt
34614c4ab120SSteven Rostedt	} else {
34624c4ab120SSteven Rostedt	    # We booted without this config, remove it from the minconfigs.
34634c4ab120SSteven Rostedt	    doprint "$config is not needed, disabling\n";
34644c4ab120SSteven Rostedt
34654c4ab120SSteven Rostedt	    delete $min_configs{$config};
34664c4ab120SSteven Rostedt
34674c4ab120SSteven Rostedt	    # Also disable anything that is not enabled in this config
34684c4ab120SSteven Rostedt	    my %configs;
34694c4ab120SSteven Rostedt	    assign_configs \%configs, $output_config;
34704c4ab120SSteven Rostedt	    my @config_keys = keys %min_configs;
34714c4ab120SSteven Rostedt	    foreach my $config (@config_keys) {
34724c4ab120SSteven Rostedt		if (!defined($configs{$config})) {
34734c4ab120SSteven Rostedt		    doprint "$config is not set, disabling\n";
34744c4ab120SSteven Rostedt		    delete $min_configs{$config};
34754c4ab120SSteven Rostedt		}
34764c4ab120SSteven Rostedt	    }
34774c4ab120SSteven Rostedt
34784c4ab120SSteven Rostedt	    # Save off all the current mandidory configs
347935ce5952SSteven Rostedt	    open (OUT, ">$temp_config")
348035ce5952SSteven Rostedt		or die "Can't write to $temp_config";
34814c4ab120SSteven Rostedt	    foreach my $config (keys %keep_configs) {
34824c4ab120SSteven Rostedt		print OUT "$keep_configs{$config}\n";
34834c4ab120SSteven Rostedt	    }
34844c4ab120SSteven Rostedt	    foreach my $config (keys %min_configs) {
34854c4ab120SSteven Rostedt		print OUT "$min_configs{$config}\n";
34864c4ab120SSteven Rostedt	    }
34874c4ab120SSteven Rostedt	    close OUT;
348835ce5952SSteven Rostedt
348935ce5952SSteven Rostedt	    run_command "mv $temp_config $output_minconfig" or
349035ce5952SSteven Rostedt		dodie "failed to copy update to $output_minconfig";
34914c4ab120SSteven Rostedt	}
34924c4ab120SSteven Rostedt
34934c4ab120SSteven Rostedt	doprint "Reboot and wait $sleep_time seconds\n";
3494bc7c5803SSteven Rostedt	reboot_to_good $sleep_time;
34954c4ab120SSteven Rostedt    }
34964c4ab120SSteven Rostedt
34974c4ab120SSteven Rostedt    success $i;
34984c4ab120SSteven Rostedt    return 1;
34994c4ab120SSteven Rostedt}
35004c4ab120SSteven Rostedt
35018d1491baSSteven Rostedt$#ARGV < 1 or die "ktest.pl version: $VERSION\n   usage: ktest.pl config-file\n";
35022545eb61SSteven Rostedt
35038d1491baSSteven Rostedtif ($#ARGV == 0) {
35048d1491baSSteven Rostedt    $ktest_config = $ARGV[0];
35058d1491baSSteven Rostedt    if (! -f $ktest_config) {
35068d1491baSSteven Rostedt	print "$ktest_config does not exist.\n";
350735ce5952SSteven Rostedt	if (!read_yn "Create it?") {
35088d1491baSSteven Rostedt	    exit 0;
35098d1491baSSteven Rostedt	}
35108d1491baSSteven Rostedt    }
35118d1491baSSteven Rostedt} else {
35128d1491baSSteven Rostedt    $ktest_config = "ktest.conf";
35138d1491baSSteven Rostedt}
35148d1491baSSteven Rostedt
35158d1491baSSteven Rostedtif (! -f $ktest_config) {
3516dbd3783bSSteven Rostedt    $newconfig = 1;
3517c4261d0fSSteven Rostedt    get_test_case;
35188d1491baSSteven Rostedt    open(OUT, ">$ktest_config") or die "Can not create $ktest_config";
35198d1491baSSteven Rostedt    print OUT << "EOF"
35208d1491baSSteven Rostedt# Generated by ktest.pl
35218d1491baSSteven Rostedt#
35220e7a22deSSteven Rostedt
35230e7a22deSSteven Rostedt# PWD is a ktest.pl variable that will result in the process working
35240e7a22deSSteven Rostedt# directory that ktest.pl is executed in.
35250e7a22deSSteven Rostedt
35260e7a22deSSteven Rostedt# THIS_DIR is automatically assigned the PWD of the path that generated
35270e7a22deSSteven Rostedt# the config file. It is best to use this variable when assigning other
35280e7a22deSSteven Rostedt# directory paths within this directory. This allows you to easily
35290e7a22deSSteven Rostedt# move the test cases to other locations or to other machines.
35300e7a22deSSteven Rostedt#
35310e7a22deSSteven RostedtTHIS_DIR := $variable{"PWD"}
35320e7a22deSSteven Rostedt
35338d1491baSSteven Rostedt# Define each test with TEST_START
35348d1491baSSteven Rostedt# The config options below it will override the defaults
35358d1491baSSteven RostedtTEST_START
3536c4261d0fSSteven RostedtTEST_TYPE = $default{"TEST_TYPE"}
35378d1491baSSteven Rostedt
35388d1491baSSteven RostedtDEFAULTS
35398d1491baSSteven RostedtEOF
35408d1491baSSteven Rostedt;
35418d1491baSSteven Rostedt    close(OUT);
35428d1491baSSteven Rostedt}
35438d1491baSSteven Rostedtread_config $ktest_config;
35448d1491baSSteven Rostedt
354523715c3cSSteven Rostedtif (defined($opt{"LOG_FILE"})) {
354623715c3cSSteven Rostedt    $opt{"LOG_FILE"} = eval_option($opt{"LOG_FILE"}, -1);
354723715c3cSSteven Rostedt}
354823715c3cSSteven Rostedt
35498d1491baSSteven Rostedt# Append any configs entered in manually to the config file.
35508d1491baSSteven Rostedtmy @new_configs = keys %entered_configs;
35518d1491baSSteven Rostedtif ($#new_configs >= 0) {
35528d1491baSSteven Rostedt    print "\nAppending entered in configs to $ktest_config\n";
35538d1491baSSteven Rostedt    open(OUT, ">>$ktest_config") or die "Can not append to $ktest_config";
35548d1491baSSteven Rostedt    foreach my $config (@new_configs) {
35558d1491baSSteven Rostedt	print OUT "$config = $entered_configs{$config}\n";
35560e7a22deSSteven Rostedt	$opt{$config} = process_variables($entered_configs{$config});
35578d1491baSSteven Rostedt    }
35588d1491baSSteven Rostedt}
35592545eb61SSteven Rostedt
35602b7d9b21SSteven Rostedtif ($opt{"CLEAR_LOG"} && defined($opt{"LOG_FILE"})) {
35612b7d9b21SSteven Rostedt    unlink $opt{"LOG_FILE"};
35622b7d9b21SSteven Rostedt}
35632545eb61SSteven Rostedt
35642b7d9b21SSteven Rostedtdoprint "\n\nSTARTING AUTOMATED TESTS\n\n";
35652b7d9b21SSteven Rostedt
3566a57419b3SSteven Rostedtfor (my $i = 0, my $repeat = 1; $i <= $opt{"NUM_TESTS"}; $i += $repeat) {
3567a57419b3SSteven Rostedt
3568a57419b3SSteven Rostedt    if (!$i) {
3569a57419b3SSteven Rostedt	doprint "DEFAULT OPTIONS:\n";
3570a57419b3SSteven Rostedt    } else {
3571a57419b3SSteven Rostedt	doprint "\nTEST $i OPTIONS";
3572a57419b3SSteven Rostedt	if (defined($repeat_tests{$i})) {
3573a57419b3SSteven Rostedt	    $repeat = $repeat_tests{$i};
3574a57419b3SSteven Rostedt	    doprint " ITERATE $repeat";
3575a57419b3SSteven Rostedt	}
3576a57419b3SSteven Rostedt	doprint "\n";
3577a57419b3SSteven Rostedt    }
3578a57419b3SSteven Rostedt
35792b7d9b21SSteven Rostedt    foreach my $option (sort keys %opt) {
3580a57419b3SSteven Rostedt
3581a57419b3SSteven Rostedt	if ($option =~ /\[(\d+)\]$/) {
3582a57419b3SSteven Rostedt	    next if ($i != $1);
3583a57419b3SSteven Rostedt	} else {
3584a57419b3SSteven Rostedt	    next if ($i);
3585a57419b3SSteven Rostedt	}
3586a57419b3SSteven Rostedt
35872b7d9b21SSteven Rostedt	doprint "$option = $opt{$option}\n";
35882b7d9b21SSteven Rostedt    }
3589a57419b3SSteven Rostedt}
35902545eb61SSteven Rostedt
35912a62512bSSteven Rostedtsub __set_test_option {
35925a391fbfSSteven Rostedt    my ($name, $i) = @_;
35935a391fbfSSteven Rostedt
35945a391fbfSSteven Rostedt    my $option = "$name\[$i\]";
35955a391fbfSSteven Rostedt
35965a391fbfSSteven Rostedt    if (defined($opt{$option})) {
35975a391fbfSSteven Rostedt	return $opt{$option};
35985a391fbfSSteven Rostedt    }
35995a391fbfSSteven Rostedt
3600a57419b3SSteven Rostedt    foreach my $test (keys %repeat_tests) {
3601a57419b3SSteven Rostedt	if ($i >= $test &&
3602a57419b3SSteven Rostedt	    $i < $test + $repeat_tests{$test}) {
3603a57419b3SSteven Rostedt	    $option = "$name\[$test\]";
3604a57419b3SSteven Rostedt	    if (defined($opt{$option})) {
3605a57419b3SSteven Rostedt		return $opt{$option};
3606a57419b3SSteven Rostedt	    }
3607a57419b3SSteven Rostedt	}
3608a57419b3SSteven Rostedt    }
3609a57419b3SSteven Rostedt
36105a391fbfSSteven Rostedt    if (defined($opt{$name})) {
36115a391fbfSSteven Rostedt	return $opt{$name};
36125a391fbfSSteven Rostedt    }
36135a391fbfSSteven Rostedt
36145a391fbfSSteven Rostedt    return undef;
36155a391fbfSSteven Rostedt}
36165a391fbfSSteven Rostedt
36172a62512bSSteven Rostedtsub set_test_option {
36182a62512bSSteven Rostedt    my ($name, $i) = @_;
36192a62512bSSteven Rostedt
36202a62512bSSteven Rostedt    my $option = __set_test_option($name, $i);
36212a62512bSSteven Rostedt    return $option if (!defined($option));
36222a62512bSSteven Rostedt
362323715c3cSSteven Rostedt    return eval_option($option, $i);
36242a62512bSSteven Rostedt}
36252a62512bSSteven Rostedt
36262545eb61SSteven Rostedt# First we need to do is the builds
3627a75fececSSteven Rostedtfor (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
36282545eb61SSteven Rostedt
36294ab1cce5SSteven Rostedt    # Do not reboot on failing test options
36304ab1cce5SSteven Rostedt    $no_reboot = 1;
3631759a3cc6SSteven Rostedt    $reboot_success = 0;
36324ab1cce5SSteven Rostedt
3633683a3e64SSteven Rostedt    $have_version = 0;
3634683a3e64SSteven Rostedt
3635576f627cSSteven Rostedt    $iteration = $i;
3636576f627cSSteven Rostedt
3637*c1434dccSSteven Rostedt    undef %force_config;
3638*c1434dccSSteven Rostedt
3639a75fececSSteven Rostedt    my $makecmd = set_test_option("MAKE_CMD", $i);
3640a75fececSSteven Rostedt
36419cc9e091SSteven Rostedt    # Load all the options into their mapped variable names
36429cc9e091SSteven Rostedt    foreach my $opt (keys %option_map) {
36439cc9e091SSteven Rostedt	${$option_map{$opt}} = set_test_option($opt, $i);
36449cc9e091SSteven Rostedt    }
3645b5f4aea6SSteven Rostedt
364635ce5952SSteven Rostedt    $start_minconfig_defined = 1;
364735ce5952SSteven Rostedt
3648921ed4c7SSteven Rostedt    # The first test may override the PRE_KTEST option
3649921ed4c7SSteven Rostedt    if (defined($pre_ktest) && $i == 1) {
3650921ed4c7SSteven Rostedt	doprint "\n";
3651921ed4c7SSteven Rostedt	run_command $pre_ktest;
3652921ed4c7SSteven Rostedt    }
3653921ed4c7SSteven Rostedt
3654921ed4c7SSteven Rostedt    # Any test can override the POST_KTEST option
3655921ed4c7SSteven Rostedt    # The last test takes precedence.
3656921ed4c7SSteven Rostedt    if (defined($post_ktest)) {
3657921ed4c7SSteven Rostedt	$final_post_ktest = $post_ktest;
3658921ed4c7SSteven Rostedt    }
3659921ed4c7SSteven Rostedt
36604c4ab120SSteven Rostedt    if (!defined($start_minconfig)) {
366135ce5952SSteven Rostedt	$start_minconfig_defined = 0;
36624c4ab120SSteven Rostedt	$start_minconfig = $minconfig;
36634c4ab120SSteven Rostedt    }
36644c4ab120SSteven Rostedt
3665a75fececSSteven Rostedt    chdir $builddir || die "can't change directory to $builddir";
3666a75fececSSteven Rostedt
3667a908a665SAndrew Jones    foreach my $dir ($tmpdir, $outputdir) {
3668a908a665SAndrew Jones	if (!-d $dir) {
3669a908a665SAndrew Jones	    mkpath($dir) or
3670a908a665SAndrew Jones		die "can't create $dir";
3671a908a665SAndrew Jones	}
3672a75fececSSteven Rostedt    }
3673a75fececSSteven Rostedt
3674e48c5293SSteven Rostedt    $ENV{"SSH_USER"} = $ssh_user;
3675e48c5293SSteven Rostedt    $ENV{"MACHINE"} = $machine;
3676e48c5293SSteven Rostedt
3677a75fececSSteven Rostedt    $buildlog = "$tmpdir/buildlog-$machine";
3678a9dd5d63SRabin Vincent    $testlog = "$tmpdir/testlog-$machine";
3679a75fececSSteven Rostedt    $dmesg = "$tmpdir/dmesg-$machine";
3680a75fececSSteven Rostedt    $make = "$makecmd O=$outputdir";
368151ad1dd1SSteven Rostedt    $output_config = "$outputdir/.config";
3682a75fececSSteven Rostedt
3683bb8474b1SSteven Rostedt    if (!$buildonly) {
3684bb8474b1SSteven Rostedt	$target = "$ssh_user\@$machine";
3685a75fececSSteven Rostedt	if ($reboot_type eq "grub") {
3686576f627cSSteven Rostedt	    dodie "GRUB_MENU not defined" if (!defined($grub_menu));
3687a75fececSSteven Rostedt	}
3688bb8474b1SSteven Rostedt    }
3689a75fececSSteven Rostedt
3690a75fececSSteven Rostedt    my $run_type = $build_type;
3691a75fececSSteven Rostedt    if ($test_type eq "patchcheck") {
3692b5f4aea6SSteven Rostedt	$run_type = $patchcheck_type;
3693a75fececSSteven Rostedt    } elsif ($test_type eq "bisect") {
3694b5f4aea6SSteven Rostedt	$run_type = $bisect_type;
36950a05c769SSteven Rostedt    } elsif ($test_type eq "config_bisect") {
3696b5f4aea6SSteven Rostedt	$run_type = $config_bisect_type;
3697a75fececSSteven Rostedt    }
3698a75fececSSteven Rostedt
36994c4ab120SSteven Rostedt    if ($test_type eq "make_min_config") {
37004c4ab120SSteven Rostedt	$run_type = "";
37014c4ab120SSteven Rostedt    }
37024c4ab120SSteven Rostedt
3703a75fececSSteven Rostedt    # mistake in config file?
3704a75fececSSteven Rostedt    if (!defined($run_type)) {
3705a75fececSSteven Rostedt	$run_type = "ERROR";
3706a75fececSSteven Rostedt    }
37072545eb61SSteven Rostedt
3708e0a8742eSSteven Rostedt    my $installme = "";
3709e0a8742eSSteven Rostedt    $installme = " no_install" if ($no_install);
3710e0a8742eSSteven Rostedt
37112545eb61SSteven Rostedt    doprint "\n\n";
3712e0a8742eSSteven Rostedt    doprint "RUNNING TEST $i of $opt{NUM_TESTS} with option $test_type $run_type$installme\n\n";
37137faafbd6SSteven Rostedt
3714921ed4c7SSteven Rostedt    if (defined($pre_test)) {
3715921ed4c7SSteven Rostedt	run_command $pre_test;
3716921ed4c7SSteven Rostedt    }
3717921ed4c7SSteven Rostedt
37187faafbd6SSteven Rostedt    unlink $dmesg;
37197faafbd6SSteven Rostedt    unlink $buildlog;
3720a9dd5d63SRabin Vincent    unlink $testlog;
37212545eb61SSteven Rostedt
3722250bae8bSSteven Rostedt    if (defined($addconfig)) {
3723250bae8bSSteven Rostedt	my $min = $minconfig;
37242b7d9b21SSteven Rostedt	if (!defined($minconfig)) {
3725250bae8bSSteven Rostedt	    $min = "";
3726250bae8bSSteven Rostedt	}
3727250bae8bSSteven Rostedt	run_command "cat $addconfig $min > $tmpdir/add_config" or
37282b7d9b21SSteven Rostedt	    dodie "Failed to create temp config";
37299be2e6b5SSteven Rostedt	$minconfig = "$tmpdir/add_config";
37302b7d9b21SSteven Rostedt    }
37312b7d9b21SSteven Rostedt
37326c5ee0beSSteven Rostedt    if (defined($checkout)) {
37336c5ee0beSSteven Rostedt	run_command "git checkout $checkout" or
37346c5ee0beSSteven Rostedt	    die "failed to checkout $checkout";
37356c5ee0beSSteven Rostedt    }
37366c5ee0beSSteven Rostedt
3737759a3cc6SSteven Rostedt    $no_reboot = 0;
3738759a3cc6SSteven Rostedt
3739648a182cSSteven Rostedt    # A test may opt to not reboot the box
3740648a182cSSteven Rostedt    if ($reboot_on_success) {
3741759a3cc6SSteven Rostedt	$reboot_success = 1;
3742648a182cSSteven Rostedt    }
37434ab1cce5SSteven Rostedt
3744a75fececSSteven Rostedt    if ($test_type eq "bisect") {
37455f9b6cedSSteven Rostedt	bisect $i;
37465f9b6cedSSteven Rostedt	next;
37470a05c769SSteven Rostedt    } elsif ($test_type eq "config_bisect") {
37480a05c769SSteven Rostedt	config_bisect $i;
37490a05c769SSteven Rostedt	next;
3750a75fececSSteven Rostedt    } elsif ($test_type eq "patchcheck") {
37516c5ee0beSSteven Rostedt	patchcheck $i;
37526c5ee0beSSteven Rostedt	next;
37534c4ab120SSteven Rostedt    } elsif ($test_type eq "make_min_config") {
37544c4ab120SSteven Rostedt	make_min_config $i;
37554c4ab120SSteven Rostedt	next;
37565f9b6cedSSteven Rostedt    }
37575f9b6cedSSteven Rostedt
37587faafbd6SSteven Rostedt    if ($build_type ne "nobuild") {
37597faafbd6SSteven Rostedt	build $build_type or next;
37602545eb61SSteven Rostedt    }
37612545eb61SSteven Rostedt
3762cd8e368fSSteven Rostedt    if ($test_type eq "install") {
3763cd8e368fSSteven Rostedt	get_version;
3764cd8e368fSSteven Rostedt	install;
3765cd8e368fSSteven Rostedt	success $i;
3766cd8e368fSSteven Rostedt	next;
3767cd8e368fSSteven Rostedt    }
3768cd8e368fSSteven Rostedt
3769a75fececSSteven Rostedt    if ($test_type ne "build") {
37707faafbd6SSteven Rostedt	my $failed = 0;
3771ddf607e5SSteven Rostedt	start_monitor_and_boot or $failed = 1;
3772a75fececSSteven Rostedt
3773a75fececSSteven Rostedt	if (!$failed && $test_type ne "boot" && defined($run_test)) {
37747faafbd6SSteven Rostedt	    do_run_test or $failed = 1;
37755a391fbfSSteven Rostedt	}
37767faafbd6SSteven Rostedt	end_monitor;
37777faafbd6SSteven Rostedt	next if ($failed);
3778a75fececSSteven Rostedt    }
37795a391fbfSSteven Rostedt
37805f9b6cedSSteven Rostedt    success $i;
378175c3fda7SSteven Rostedt}
37822545eb61SSteven Rostedt
3783921ed4c7SSteven Rostedtif (defined($final_post_ktest)) {
3784921ed4c7SSteven Rostedt    run_command $final_post_ktest;
3785921ed4c7SSteven Rostedt}
3786921ed4c7SSteven Rostedt
37875c42fc5bSSteven Rostedtif ($opt{"POWEROFF_ON_SUCCESS"}) {
378875c3fda7SSteven Rostedt    halt;
3789759a3cc6SSteven Rostedt} elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot && $reboot_success) {
3790bc7c5803SSteven Rostedt    reboot_to_good;
3791648a182cSSteven Rostedt} elsif (defined($switch_to_good)) {
3792648a182cSSteven Rostedt    # still need to get to the good kernel
3793648a182cSSteven Rostedt    run_command $switch_to_good;
37945c42fc5bSSteven Rostedt}
379575c3fda7SSteven Rostedt
3796648a182cSSteven Rostedt
3797e48c5293SSteven Rostedtdoprint "\n    $successes of $opt{NUM_TESTS} tests were successful\n\n";
3798e48c5293SSteven Rostedt
37992545eb61SSteven Rostedtexit 0;
3800