mirror of
https://review.coreboot.org/flashrom.git
synced 2025-04-27 23:22:37 +02:00
flashrom_tester: Add an implementation using libflashrom
flashrom_tester 'flashrom' crate was implemented using the flashrom commandline. Add a second implementation using the libflashrom interface via the libflashrom and libflashrom-sys rust bindings. BUG=b:230545739 BRANCH=None TEST=cargo test TEST=on grunt (AMD) TEST=/usr/bin/flashrom_tester --libflashrom host TEST=/usr/bin/flashrom_tester --flashrom_binary /usr/sbin/flashrom host Change-Id: Ic4db6c829d7e8dc707a10c10e1ca0d9b8abccdec Signed-off-by: Evan Benn <evanbenn@chromium.org> Reviewed-on: https://review.coreboot.org/c/flashrom/+/65282 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Edward O'Callaghan <quasisec@chromium.org>
This commit is contained in:
parent
b41bb5622c
commit
f6d9a2847e
@ -6,4 +6,5 @@ authors = ["Edward O'Callaghan <quasisec@chromium.org>",
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
log = "0.4"
|
||||
log = "0.4"
|
||||
libflashrom = { path = "../../../bindings/rust/libflashrom" }
|
||||
|
160
util/flashrom_tester/flashrom/src/flashromlib.rs
Normal file
160
util/flashrom_tester/flashrom/src/flashromlib.rs
Normal file
@ -0,0 +1,160 @@
|
||||
// Copyright 2022, 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 libflashrom::{Chip, Programmer};
|
||||
|
||||
use std::{cell::RefCell, convert::TryFrom, fs};
|
||||
|
||||
use crate::{FlashChip, FlashromError, ROMWriteSpecifics};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct FlashromLib {
|
||||
// RefCell required here to keep Flashrom trait immutable.
|
||||
// Cant make Flashrom methods mut because WriteProtectState
|
||||
// and TestEnv both keep a reference.
|
||||
pub flashrom: RefCell<Chip>,
|
||||
pub fc: FlashChip,
|
||||
}
|
||||
|
||||
impl FlashromLib {
|
||||
pub fn new(fc: FlashChip, log_level: libflashrom::flashrom_log_level) -> FlashromLib {
|
||||
libflashrom::set_log_level(Some(log_level));
|
||||
let (programmer, options) = FlashChip::to_split(fc);
|
||||
let flashrom = Chip::new(Programmer::new(programmer, options).unwrap(), None).unwrap();
|
||||
FlashromLib {
|
||||
flashrom: RefCell::new(flashrom),
|
||||
fc,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::Flashrom for FlashromLib {
|
||||
fn get_size(&self) -> Result<i64, FlashromError> {
|
||||
Ok(self.flashrom.borrow().get_size() as i64)
|
||||
}
|
||||
|
||||
fn name(&self) -> Result<(String, String), FlashromError> {
|
||||
Ok(("not".to_string(), "implemented".to_string()))
|
||||
}
|
||||
|
||||
fn wp_range(&self, range: (i64, i64), wp_enable: bool) -> Result<bool, FlashromError> {
|
||||
let mut cfg = libflashrom::WriteProtectCfg::new()?;
|
||||
let start = usize::try_from(range.0).unwrap();
|
||||
let len = usize::try_from(range.1).unwrap();
|
||||
cfg.set_range::<std::ops::Range<usize>>(start..(start + len));
|
||||
cfg.set_mode(if wp_enable {
|
||||
libflashrom::flashrom_wp_mode::FLASHROM_WP_MODE_HARDWARE
|
||||
} else {
|
||||
libflashrom::flashrom_wp_mode::FLASHROM_WP_MODE_DISABLED
|
||||
});
|
||||
self.flashrom.borrow_mut().set_wp(&cfg)?;
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
fn wp_list(&self) -> Result<String, FlashromError> {
|
||||
let ranges = self.flashrom.borrow_mut().get_wp_ranges()?;
|
||||
Ok(format!("{:?}", ranges))
|
||||
}
|
||||
|
||||
fn wp_status(&self, en: bool) -> Result<bool, FlashromError> {
|
||||
let ret = self
|
||||
.flashrom
|
||||
.borrow_mut()
|
||||
.get_wp()
|
||||
.map_err(|e| format!("{:?}", e))?
|
||||
.get_mode();
|
||||
if en {
|
||||
Ok(ret != libflashrom::flashrom_wp_mode::FLASHROM_WP_MODE_DISABLED)
|
||||
} else {
|
||||
Ok(ret == libflashrom::flashrom_wp_mode::FLASHROM_WP_MODE_DISABLED)
|
||||
}
|
||||
}
|
||||
|
||||
fn wp_toggle(&self, en: bool) -> Result<bool, FlashromError> {
|
||||
// TODO why does the cmd impl not do this?
|
||||
// for cmd, range is only set for enable
|
||||
// and disable is not sent for the wp_range command
|
||||
self.wp_range((0, self.get_size()?), en)
|
||||
}
|
||||
|
||||
fn read_into_file(&self, path: &str) -> Result<(), FlashromError> {
|
||||
let buf = self.flashrom.borrow_mut().image_read(None)?;
|
||||
fs::write(path, buf).map_err(|error| error.to_string())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn read_region_into_file(&self, path: &str, region: &str) -> Result<(), FlashromError> {
|
||||
let mut layout = self.flashrom.borrow_mut().layout_read_fmap_from_rom()?;
|
||||
layout.include_region(region)?;
|
||||
let range = layout.get_region_range(region)?;
|
||||
let buf = self.flashrom.borrow_mut().image_read(None)?;
|
||||
fs::write(path, &buf[range]).map_err(|error| error.to_string())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_from_file(&self, path: &str) -> Result<(), FlashromError> {
|
||||
let mut buf = fs::read(path).map_err(|error| error.to_string())?;
|
||||
self.flashrom.borrow_mut().image_write(&mut buf, None)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_file_with_layout(&self, rws: &ROMWriteSpecifics) -> Result<bool, FlashromError> {
|
||||
let buf = fs::read(rws.layout_file.unwrap()).map_err(|error| error.to_string())?;
|
||||
let buf = String::from_utf8(buf).unwrap();
|
||||
let mut layout: libflashrom::Layout = buf
|
||||
.parse()
|
||||
.map_err(|e: Box<dyn std::error::Error>| e.to_string())?;
|
||||
layout.include_region(rws.name_file.unwrap())?;
|
||||
let mut buf = fs::read(rws.write_file.unwrap()).map_err(|error| error.to_string())?;
|
||||
self.flashrom
|
||||
.borrow_mut()
|
||||
.image_write(&mut buf, Some(layout))?;
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
fn verify_from_file(&self, path: &str) -> Result<(), FlashromError> {
|
||||
let buf = fs::read(path).map_err(|error| error.to_string())?;
|
||||
self.flashrom.borrow_mut().image_verify(&buf, None)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn erase(&self) -> Result<(), FlashromError> {
|
||||
self.flashrom.borrow_mut().erase()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn can_control_hw_wp(&self) -> bool {
|
||||
self.fc.can_control_hw_wp()
|
||||
}
|
||||
}
|
@ -37,10 +37,17 @@
|
||||
extern crate log;
|
||||
|
||||
mod cmd;
|
||||
mod flashromlib;
|
||||
|
||||
use std::{error, fmt};
|
||||
|
||||
pub use cmd::{dut_ctrl_toggle_wp, FlashromCmd};
|
||||
pub use flashromlib::FlashromLib;
|
||||
|
||||
pub use libflashrom::{
|
||||
flashrom_log_level, FLASHROM_MSG_DEBUG, FLASHROM_MSG_DEBUG2, FLASHROM_MSG_ERROR,
|
||||
FLASHROM_MSG_INFO, FLASHROM_MSG_SPEW, FLASHROM_MSG_WARN,
|
||||
};
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||
pub enum FlashChip {
|
||||
@ -71,6 +78,13 @@ impl FlashChip {
|
||||
return r;
|
||||
}
|
||||
|
||||
/// Return the programmer string and optional programmer options
|
||||
pub fn to_split(fc: FlashChip) -> (&'static str, Option<&'static str>) {
|
||||
let programmer = FlashChip::to(fc);
|
||||
let mut bits = programmer.splitn(2, ':');
|
||||
(bits.next().unwrap(), bits.next())
|
||||
}
|
||||
|
||||
/// Return whether the hardware write protect signal can be controlled.
|
||||
///
|
||||
/// Servo and dediprog adapters are assumed to always have hardware write protect
|
||||
|
@ -39,7 +39,7 @@ extern crate log;
|
||||
mod logger;
|
||||
|
||||
use clap::{App, Arg};
|
||||
use flashrom::{FlashChip, Flashrom, FlashromCmd};
|
||||
use flashrom::{FlashChip, Flashrom, FlashromCmd, FlashromLib};
|
||||
use flashrom_tester::{tester, tests};
|
||||
use std::path::PathBuf;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
@ -65,7 +65,21 @@ fn main() {
|
||||
built_info::BUILT_TIME_UTC,
|
||||
built_info::RUSTC_VERSION,
|
||||
))
|
||||
.arg(Arg::with_name("flashrom_binary").required(true))
|
||||
.arg(
|
||||
Arg::with_name("libflashrom")
|
||||
.long("libflashrom")
|
||||
.takes_value(false)
|
||||
.help("Test the flashrom library instead of a binary"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("flashrom_binary")
|
||||
.long("flashrom_binary")
|
||||
.short("b")
|
||||
.takes_value(true)
|
||||
.required_unless("libflashrom")
|
||||
.conflicts_with("libflashrom")
|
||||
.help("Path to flashrom binary to test"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("ccd_target_type")
|
||||
.required(true)
|
||||
@ -117,9 +131,6 @@ fn main() {
|
||||
let crossystem =
|
||||
flashrom_tester::utils::collect_crosssystem(&[]).expect("could not run crossystem");
|
||||
|
||||
let flashrom_path = matches
|
||||
.value_of("flashrom_binary")
|
||||
.expect("flashrom_binary should be required");
|
||||
let ccd_type = FlashChip::from(
|
||||
matches
|
||||
.value_of("ccd_target_type")
|
||||
@ -127,10 +138,24 @@ fn main() {
|
||||
)
|
||||
.expect("ccd_target_type should admit only known types");
|
||||
|
||||
let cmd: Box<dyn Flashrom> = Box::new(FlashromCmd {
|
||||
path: flashrom_path.to_string(),
|
||||
fc: ccd_type,
|
||||
});
|
||||
let cmd: Box<dyn Flashrom> = if matches.is_present("libflashrom") {
|
||||
Box::new(FlashromLib::new(
|
||||
ccd_type,
|
||||
if matches.is_present("log_debug") {
|
||||
flashrom::FLASHROM_MSG_DEBUG
|
||||
} else {
|
||||
flashrom::FLASHROM_MSG_WARN
|
||||
},
|
||||
))
|
||||
} else {
|
||||
Box::new(FlashromCmd {
|
||||
path: matches
|
||||
.value_of("flashrom_binary")
|
||||
.expect("flashrom_binary is required")
|
||||
.to_string(),
|
||||
fc: ccd_type,
|
||||
})
|
||||
};
|
||||
|
||||
let print_layout = matches.is_present("print-layout");
|
||||
let output_format = matches
|
||||
|
Loading…
x
Reference in New Issue
Block a user