1*0d6140beSAndroid Build Coastguard Worker //
2*0d6140beSAndroid Build Coastguard Worker // Copyright 2019, Google Inc.
3*0d6140beSAndroid Build Coastguard Worker // All rights reserved.
4*0d6140beSAndroid Build Coastguard Worker //
5*0d6140beSAndroid Build Coastguard Worker // Redistribution and use in source and binary forms, with or without
6*0d6140beSAndroid Build Coastguard Worker // modification, are permitted provided that the following conditions are
7*0d6140beSAndroid Build Coastguard Worker // met:
8*0d6140beSAndroid Build Coastguard Worker //
9*0d6140beSAndroid Build Coastguard Worker // * Redistributions of source code must retain the above copyright
10*0d6140beSAndroid Build Coastguard Worker // notice, this list of conditions and the following disclaimer.
11*0d6140beSAndroid Build Coastguard Worker // * Redistributions in binary form must reproduce the above
12*0d6140beSAndroid Build Coastguard Worker // copyright notice, this list of conditions and the following disclaimer
13*0d6140beSAndroid Build Coastguard Worker // in the documentation and/or other materials provided with the
14*0d6140beSAndroid Build Coastguard Worker // distribution.
15*0d6140beSAndroid Build Coastguard Worker // * Neither the name of Google Inc. nor the names of its
16*0d6140beSAndroid Build Coastguard Worker // contributors may be used to endorse or promote products derived from
17*0d6140beSAndroid Build Coastguard Worker // this software without specific prior written permission.
18*0d6140beSAndroid Build Coastguard Worker //
19*0d6140beSAndroid Build Coastguard Worker // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20*0d6140beSAndroid Build Coastguard Worker // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21*0d6140beSAndroid Build Coastguard Worker // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22*0d6140beSAndroid Build Coastguard Worker // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23*0d6140beSAndroid Build Coastguard Worker // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24*0d6140beSAndroid Build Coastguard Worker // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25*0d6140beSAndroid Build Coastguard Worker // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26*0d6140beSAndroid Build Coastguard Worker // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27*0d6140beSAndroid Build Coastguard Worker // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28*0d6140beSAndroid Build Coastguard Worker // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29*0d6140beSAndroid Build Coastguard Worker // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30*0d6140beSAndroid Build Coastguard Worker //
31*0d6140beSAndroid Build Coastguard Worker // Alternatively, this software may be distributed under the terms of the
32*0d6140beSAndroid Build Coastguard Worker // GNU General Public License ("GPL") version 2 as published by the Free
33*0d6140beSAndroid Build Coastguard Worker // Software Foundation.
34*0d6140beSAndroid Build Coastguard Worker //
35*0d6140beSAndroid Build Coastguard Worker
36*0d6140beSAndroid Build Coastguard Worker #[macro_use]
37*0d6140beSAndroid Build Coastguard Worker extern crate log;
38*0d6140beSAndroid Build Coastguard Worker
39*0d6140beSAndroid Build Coastguard Worker mod logger;
40*0d6140beSAndroid Build Coastguard Worker
41*0d6140beSAndroid Build Coastguard Worker use clap::{App, Arg};
42*0d6140beSAndroid Build Coastguard Worker use flashrom::{FlashChip, Flashrom, FlashromCmd, FlashromLib};
43*0d6140beSAndroid Build Coastguard Worker use flashrom_tester::{tester, tests};
44*0d6140beSAndroid Build Coastguard Worker use std::sync::atomic::AtomicBool;
45*0d6140beSAndroid Build Coastguard Worker
46*0d6140beSAndroid Build Coastguard Worker pub mod built_info {
47*0d6140beSAndroid Build Coastguard Worker include!(concat!(env!("OUT_DIR"), "/built.rs"));
48*0d6140beSAndroid Build Coastguard Worker }
49*0d6140beSAndroid Build Coastguard Worker
main()50*0d6140beSAndroid Build Coastguard Worker fn main() {
51*0d6140beSAndroid Build Coastguard Worker let matches = App::new("flashrom_tester")
52*0d6140beSAndroid Build Coastguard Worker .long_version(&*format!(
53*0d6140beSAndroid Build Coastguard Worker "{}-{}\n\
54*0d6140beSAndroid Build Coastguard Worker Target: {}\n\
55*0d6140beSAndroid Build Coastguard Worker Profile: {}\n\
56*0d6140beSAndroid Build Coastguard Worker Features: {:?}\n\
57*0d6140beSAndroid Build Coastguard Worker Build time: {}\n\
58*0d6140beSAndroid Build Coastguard Worker Compiler: {}",
59*0d6140beSAndroid Build Coastguard Worker built_info::PKG_VERSION,
60*0d6140beSAndroid Build Coastguard Worker option_env!("VCSID").unwrap_or("<unknown>"),
61*0d6140beSAndroid Build Coastguard Worker built_info::TARGET,
62*0d6140beSAndroid Build Coastguard Worker built_info::PROFILE,
63*0d6140beSAndroid Build Coastguard Worker built_info::FEATURES,
64*0d6140beSAndroid Build Coastguard Worker built_info::BUILT_TIME_UTC,
65*0d6140beSAndroid Build Coastguard Worker built_info::RUSTC_VERSION,
66*0d6140beSAndroid Build Coastguard Worker ))
67*0d6140beSAndroid Build Coastguard Worker .arg(
68*0d6140beSAndroid Build Coastguard Worker Arg::with_name("libflashrom")
69*0d6140beSAndroid Build Coastguard Worker .long("libflashrom")
70*0d6140beSAndroid Build Coastguard Worker .takes_value(false)
71*0d6140beSAndroid Build Coastguard Worker .help("Test the flashrom library instead of a binary"),
72*0d6140beSAndroid Build Coastguard Worker )
73*0d6140beSAndroid Build Coastguard Worker .arg(
74*0d6140beSAndroid Build Coastguard Worker Arg::with_name("flashrom_binary")
75*0d6140beSAndroid Build Coastguard Worker .long("flashrom_binary")
76*0d6140beSAndroid Build Coastguard Worker .short("b")
77*0d6140beSAndroid Build Coastguard Worker .takes_value(true)
78*0d6140beSAndroid Build Coastguard Worker .required_unless("libflashrom")
79*0d6140beSAndroid Build Coastguard Worker .conflicts_with("libflashrom")
80*0d6140beSAndroid Build Coastguard Worker .help("Path to flashrom binary to test"),
81*0d6140beSAndroid Build Coastguard Worker )
82*0d6140beSAndroid Build Coastguard Worker .arg(
83*0d6140beSAndroid Build Coastguard Worker Arg::with_name("ccd_target_type")
84*0d6140beSAndroid Build Coastguard Worker .required(true)
85*0d6140beSAndroid Build Coastguard Worker .possible_values(&["internal"]),
86*0d6140beSAndroid Build Coastguard Worker )
87*0d6140beSAndroid Build Coastguard Worker .arg(
88*0d6140beSAndroid Build Coastguard Worker Arg::with_name("print-layout")
89*0d6140beSAndroid Build Coastguard Worker .short("l")
90*0d6140beSAndroid Build Coastguard Worker .long("print-layout")
91*0d6140beSAndroid Build Coastguard Worker .help("Print the layout file's contents before running tests"),
92*0d6140beSAndroid Build Coastguard Worker )
93*0d6140beSAndroid Build Coastguard Worker .arg(
94*0d6140beSAndroid Build Coastguard Worker Arg::with_name("log_debug")
95*0d6140beSAndroid Build Coastguard Worker .short("d")
96*0d6140beSAndroid Build Coastguard Worker .long("debug")
97*0d6140beSAndroid Build Coastguard Worker .help("Write detailed logs, for debugging"),
98*0d6140beSAndroid Build Coastguard Worker )
99*0d6140beSAndroid Build Coastguard Worker .arg(
100*0d6140beSAndroid Build Coastguard Worker Arg::with_name("output-format")
101*0d6140beSAndroid Build Coastguard Worker .short("f")
102*0d6140beSAndroid Build Coastguard Worker .long("output-format")
103*0d6140beSAndroid Build Coastguard Worker .help("Set the test report format")
104*0d6140beSAndroid Build Coastguard Worker .takes_value(true)
105*0d6140beSAndroid Build Coastguard Worker .case_insensitive(true)
106*0d6140beSAndroid Build Coastguard Worker .possible_values(&["pretty", "json"])
107*0d6140beSAndroid Build Coastguard Worker .default_value("pretty"),
108*0d6140beSAndroid Build Coastguard Worker )
109*0d6140beSAndroid Build Coastguard Worker .arg(
110*0d6140beSAndroid Build Coastguard Worker Arg::with_name("test_name")
111*0d6140beSAndroid Build Coastguard Worker .multiple(true)
112*0d6140beSAndroid Build Coastguard Worker .help("Names of individual tests to run (run all if unspecified)"),
113*0d6140beSAndroid Build Coastguard Worker )
114*0d6140beSAndroid Build Coastguard Worker .get_matches();
115*0d6140beSAndroid Build Coastguard Worker
116*0d6140beSAndroid Build Coastguard Worker logger::init(matches.is_present("log_debug"));
117*0d6140beSAndroid Build Coastguard Worker debug!("Args parsed and logging initialized OK");
118*0d6140beSAndroid Build Coastguard Worker
119*0d6140beSAndroid Build Coastguard Worker debug!("Collecting crossystem info");
120*0d6140beSAndroid Build Coastguard Worker let crossystem =
121*0d6140beSAndroid Build Coastguard Worker flashrom_tester::utils::collect_crosssystem(&[]).expect("could not run crossystem");
122*0d6140beSAndroid Build Coastguard Worker
123*0d6140beSAndroid Build Coastguard Worker let ccd_type = FlashChip::from(
124*0d6140beSAndroid Build Coastguard Worker matches
125*0d6140beSAndroid Build Coastguard Worker .value_of("ccd_target_type")
126*0d6140beSAndroid Build Coastguard Worker .expect("ccd_target_type should be required"),
127*0d6140beSAndroid Build Coastguard Worker )
128*0d6140beSAndroid Build Coastguard Worker .expect("ccd_target_type should admit only known types");
129*0d6140beSAndroid Build Coastguard Worker
130*0d6140beSAndroid Build Coastguard Worker let cmd: Box<dyn Flashrom> = if matches.is_present("libflashrom") {
131*0d6140beSAndroid Build Coastguard Worker Box::new(FlashromLib::new(
132*0d6140beSAndroid Build Coastguard Worker ccd_type,
133*0d6140beSAndroid Build Coastguard Worker if matches.is_present("log_debug") {
134*0d6140beSAndroid Build Coastguard Worker flashrom::FLASHROM_MSG_DEBUG
135*0d6140beSAndroid Build Coastguard Worker } else {
136*0d6140beSAndroid Build Coastguard Worker flashrom::FLASHROM_MSG_WARN
137*0d6140beSAndroid Build Coastguard Worker },
138*0d6140beSAndroid Build Coastguard Worker ))
139*0d6140beSAndroid Build Coastguard Worker } else {
140*0d6140beSAndroid Build Coastguard Worker Box::new(FlashromCmd {
141*0d6140beSAndroid Build Coastguard Worker path: matches
142*0d6140beSAndroid Build Coastguard Worker .value_of("flashrom_binary")
143*0d6140beSAndroid Build Coastguard Worker .expect("flashrom_binary is required")
144*0d6140beSAndroid Build Coastguard Worker .to_string(),
145*0d6140beSAndroid Build Coastguard Worker fc: ccd_type,
146*0d6140beSAndroid Build Coastguard Worker })
147*0d6140beSAndroid Build Coastguard Worker };
148*0d6140beSAndroid Build Coastguard Worker
149*0d6140beSAndroid Build Coastguard Worker let print_layout = matches.is_present("print-layout");
150*0d6140beSAndroid Build Coastguard Worker let output_format = matches
151*0d6140beSAndroid Build Coastguard Worker .value_of("output-format")
152*0d6140beSAndroid Build Coastguard Worker .expect("output-format should have a default value")
153*0d6140beSAndroid Build Coastguard Worker .parse::<tester::OutputFormat>()
154*0d6140beSAndroid Build Coastguard Worker .expect("output-format is not a parseable OutputFormat");
155*0d6140beSAndroid Build Coastguard Worker let test_names = matches.values_of("test_name");
156*0d6140beSAndroid Build Coastguard Worker
157*0d6140beSAndroid Build Coastguard Worker if let Err(e) = tests::generic(
158*0d6140beSAndroid Build Coastguard Worker cmd.as_ref(),
159*0d6140beSAndroid Build Coastguard Worker ccd_type,
160*0d6140beSAndroid Build Coastguard Worker print_layout,
161*0d6140beSAndroid Build Coastguard Worker output_format,
162*0d6140beSAndroid Build Coastguard Worker test_names,
163*0d6140beSAndroid Build Coastguard Worker Some(handle_sigint()),
164*0d6140beSAndroid Build Coastguard Worker crossystem,
165*0d6140beSAndroid Build Coastguard Worker ) {
166*0d6140beSAndroid Build Coastguard Worker eprintln!("Failed to run tests: {:?}", e);
167*0d6140beSAndroid Build Coastguard Worker std::process::exit(1);
168*0d6140beSAndroid Build Coastguard Worker }
169*0d6140beSAndroid Build Coastguard Worker }
170*0d6140beSAndroid Build Coastguard Worker
171*0d6140beSAndroid Build Coastguard Worker /// Catch exactly one SIGINT, printing a message in response and setting a flag.
172*0d6140beSAndroid Build Coastguard Worker ///
173*0d6140beSAndroid Build Coastguard Worker /// The returned value is false by default, becoming true after a SIGINT is
174*0d6140beSAndroid Build Coastguard Worker /// trapped.
175*0d6140beSAndroid Build Coastguard Worker ///
176*0d6140beSAndroid Build Coastguard Worker /// Once a signal is trapped, the default behavior is restored (terminating
177*0d6140beSAndroid Build Coastguard Worker /// the process) for future signals.
handle_sigint() -> &'static AtomicBool178*0d6140beSAndroid Build Coastguard Worker fn handle_sigint() -> &'static AtomicBool {
179*0d6140beSAndroid Build Coastguard Worker use libc::c_int;
180*0d6140beSAndroid Build Coastguard Worker use std::sync::atomic::Ordering;
181*0d6140beSAndroid Build Coastguard Worker
182*0d6140beSAndroid Build Coastguard Worker unsafe {
183*0d6140beSAndroid Build Coastguard Worker let _ = libc::signal(libc::SIGINT, sigint_handler as libc::sighandler_t);
184*0d6140beSAndroid Build Coastguard Worker }
185*0d6140beSAndroid Build Coastguard Worker static TERMINATE_FLAG: AtomicBool = AtomicBool::new(false);
186*0d6140beSAndroid Build Coastguard Worker
187*0d6140beSAndroid Build Coastguard Worker extern "C" fn sigint_handler(_: c_int) {
188*0d6140beSAndroid Build Coastguard Worker const STDERR_FILENO: c_int = 2;
189*0d6140beSAndroid Build Coastguard Worker static MESSAGE: &[u8] = b"
190*0d6140beSAndroid Build Coastguard Worker WARNING: terminating tests prematurely may leave Flash in an inconsistent state,
191*0d6140beSAndroid Build Coastguard Worker rendering your machine unbootable. Testing will end on completion of the current
192*0d6140beSAndroid Build Coastguard Worker test, or press ^C again to exit immediately (possibly bricking your machine).
193*0d6140beSAndroid Build Coastguard Worker ";
194*0d6140beSAndroid Build Coastguard Worker
195*0d6140beSAndroid Build Coastguard Worker // Use raw write() because signal-safety is a very hard problem. Safe because this doesn't
196*0d6140beSAndroid Build Coastguard Worker // modify any memory.
197*0d6140beSAndroid Build Coastguard Worker let _ = unsafe {
198*0d6140beSAndroid Build Coastguard Worker libc::write(
199*0d6140beSAndroid Build Coastguard Worker STDERR_FILENO,
200*0d6140beSAndroid Build Coastguard Worker MESSAGE.as_ptr() as *const libc::c_void,
201*0d6140beSAndroid Build Coastguard Worker MESSAGE.len() as libc::size_t,
202*0d6140beSAndroid Build Coastguard Worker )
203*0d6140beSAndroid Build Coastguard Worker };
204*0d6140beSAndroid Build Coastguard Worker unsafe {
205*0d6140beSAndroid Build Coastguard Worker let _ = libc::signal(libc::SIGINT, libc::SIG_DFL);
206*0d6140beSAndroid Build Coastguard Worker }
207*0d6140beSAndroid Build Coastguard Worker TERMINATE_FLAG.store(true, Ordering::Release);
208*0d6140beSAndroid Build Coastguard Worker }
209*0d6140beSAndroid Build Coastguard Worker
210*0d6140beSAndroid Build Coastguard Worker &TERMINATE_FLAG
211*0d6140beSAndroid Build Coastguard Worker }
212