1
0
mirror of https://review.coreboot.org/flashrom.git synced 2025-04-28 07:23:43 +02:00
Evan Benn 1f65e9029b flashrom_tester: Fix cargo check and clippy warnings
Change-Id: I50c5af61e06df1bb6956f347cb6806a7eca6ce0e
Signed-off-by: Evan Benn <evanbenn@chromium.org>
Reviewed-on: https://review.coreboot.org/c/flashrom/+/67472
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Peter Marheine <pmarheine@chromium.org>
Reviewed-by: Angel Pons <th3fanbus@gmail.com>
2022-09-19 07:25:55 +00:00

242 lines
7.8 KiB
Rust

//
// Copyright 2019, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Alternatively, this software may be distributed under the terms of the
// GNU General Public License ("GPL") version 2 as published by the Free
// Software Foundation.
//
use std::io::prelude::*;
use std::process::Command;
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum LayoutNames {
TopQuad,
TopHalf,
BottomHalf,
BottomQuad,
}
impl LayoutNames {
// Return a section that does not overlap
pub fn get_non_overlapping_section(&self) -> LayoutNames {
match self {
LayoutNames::TopQuad => LayoutNames::BottomQuad,
LayoutNames::TopHalf => LayoutNames::BottomHalf,
LayoutNames::BottomHalf => LayoutNames::TopHalf,
LayoutNames::BottomQuad => LayoutNames::TopQuad,
}
}
}
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub struct LayoutSizes {
half_sz: i64,
quad_sz: i64,
rom_top: i64,
bottom_half_top: i64,
bottom_quad_top: i64,
top_quad_bottom: i64,
}
pub fn get_layout_sizes(rom_sz: i64) -> Result<LayoutSizes, String> {
if rom_sz <= 0 {
return Err("invalid rom size provided".into());
}
if rom_sz & (rom_sz - 1) != 0 {
return Err("invalid rom size, not a power of 2".into());
}
Ok(LayoutSizes {
half_sz: rom_sz / 2,
quad_sz: rom_sz / 4,
rom_top: rom_sz - 1,
bottom_half_top: (rom_sz / 2) - 1,
bottom_quad_top: (rom_sz / 4) - 1,
top_quad_bottom: (rom_sz / 4) * 3,
})
}
pub fn layout_section(ls: &LayoutSizes, ln: LayoutNames) -> (&'static str, i64, i64) {
match ln {
LayoutNames::TopQuad => ("TOP_QUAD", ls.top_quad_bottom, ls.quad_sz),
LayoutNames::TopHalf => ("TOP_HALF", ls.half_sz, ls.half_sz),
LayoutNames::BottomHalf => ("BOTTOM_HALF", 0, ls.half_sz),
LayoutNames::BottomQuad => ("BOTTOM_QUAD", 0, ls.quad_sz),
}
}
pub fn construct_layout_file<F: Write>(mut target: F, ls: &LayoutSizes) -> std::io::Result<()> {
writeln!(target, "000000:{:x} BOTTOM_QUAD", ls.bottom_quad_top)?;
writeln!(target, "000000:{:x} BOTTOM_HALF", ls.bottom_half_top)?;
writeln!(target, "{:x}:{:x} TOP_HALF", ls.half_sz, ls.rom_top)?;
writeln!(target, "{:x}:{:x} TOP_QUAD", ls.top_quad_bottom, ls.rom_top)
}
pub fn toggle_hw_wp(dis: bool) -> Result<(), String> {
// The easist way to toggle the hardware write-protect is
// to {dis}connect the battery (and/or open the WP screw).
let s = if dis { "dis" } else { "" };
// Print a failure message, but not on the first try.
let mut fail_msg = None;
while dis == get_hardware_wp()? {
if let Some(msg) = fail_msg {
eprintln!("{msg}");
}
fail_msg = Some(format!("Hardware write protect is still {}!", !dis));
// The following message is read by the tast test. Do not modify.
info!("Prompt for hardware WP {}able", s);
eprintln!(" > {}connect the battery (and/or open the WP screw)", s);
pause();
}
Ok(())
}
pub fn ac_power_warning() {
info!("*****************************");
info!("AC power *must be* connected!");
info!("*****************************");
pause();
}
fn pause() {
// The following message is read by the tast test. Do not modify.
println!("Press enter to continue...");
// Rust stdout is always LineBuffered at time of writing.
// But this is not guaranteed, so flush anyway.
std::io::stdout().flush().unwrap();
// This reads one line, there is no guarantee the line came
// after the above prompt. But it is good enough.
if std::io::stdin().read_line(&mut String::new()).unwrap() == 0 {
panic!("stdin closed");
}
}
pub fn get_hardware_wp() -> std::result::Result<bool, String> {
let wp_s_val = collect_crosssystem(&["wpsw_cur"])?.parse::<u32>();
match wp_s_val {
Ok(v) => {
if v == 1 {
Ok(true)
} else if v == 0 {
Ok(false)
} else {
Err("Unknown write protect value".into())
}
}
Err(_) => Err("Cannot parse write protect value".into()),
}
}
pub fn collect_crosssystem(args: &[&str]) -> Result<String, String> {
let cmd = match Command::new("crossystem").args(args).output() {
Ok(x) => x,
Err(e) => return Err(format!("Failed to run crossystem: {}", e)),
};
if !cmd.status.success() {
return Err(translate_command_error(&cmd).to_string());
};
Ok(String::from_utf8_lossy(&cmd.stdout).into_owned())
}
pub fn translate_command_error(output: &std::process::Output) -> std::io::Error {
use std::io::{Error, ErrorKind};
// There is two cases on failure;
// i. ) A bad exit code,
// ii.) A SIG killed us.
match output.status.code() {
Some(code) => {
let e = format!(
"{}\nExited with error code: {}",
String::from_utf8_lossy(&output.stderr),
code
);
Error::new(ErrorKind::Other, e)
}
None => Error::new(
ErrorKind::Other,
"Process terminated by a signal".to_string(),
),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn construct_layout_file() {
use super::{construct_layout_file, get_layout_sizes};
let mut buf = Vec::new();
construct_layout_file(
&mut buf,
&get_layout_sizes(0x10000).expect("64k is a valid chip size"),
)
.expect("no I/O errors expected");
assert_eq!(
&buf[..],
&b"000000:3fff BOTTOM_QUAD\n\
000000:7fff BOTTOM_HALF\n\
8000:ffff TOP_HALF\n\
c000:ffff TOP_QUAD\n"[..]
);
}
#[test]
fn get_layout_sizes() {
use super::get_layout_sizes;
assert_eq!(
get_layout_sizes(-128).err(),
Some("invalid rom size provided".into())
);
assert_eq!(
get_layout_sizes(3 << 20).err(),
Some("invalid rom size, not a power of 2".into())
);
assert_eq!(
get_layout_sizes(64 << 10).unwrap(),
LayoutSizes {
half_sz: 0x8000,
quad_sz: 0x4000,
rom_top: 0xFFFF,
bottom_half_top: 0x7FFF,
bottom_quad_top: 0x3FFF,
top_quad_bottom: 0xC000,
}
);
}
}