summaryrefslogtreecommitdiffstats
path: root/util
diff options
context:
space:
mode:
authorEvan Benn <evanbenn@chromium.org>2022-06-01 12:45:01 +1000
committerEdward O'Callaghan <quasisec@chromium.org>2022-08-26 05:07:09 +0000
commitf6d9a2847e6b66a8f1415e04dc2bd13cc1d7e555 (patch)
tree857f5cd26ecdd05007114228d95284031fca4bd4 /util
parentb41bb5622c08edb33cd83aa05973513db3869af0 (diff)
downloadflashrom-f6d9a2847e6b66a8f1415e04dc2bd13cc1d7e555.tar.gz
flashrom-f6d9a2847e6b66a8f1415e04dc2bd13cc1d7e555.tar.bz2
flashrom-f6d9a2847e6b66a8f1415e04dc2bd13cc1d7e555.zip
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>
Diffstat (limited to 'util')
-rw-r--r--util/flashrom_tester/flashrom/Cargo.toml3
-rw-r--r--util/flashrom_tester/flashrom/src/flashromlib.rs160
-rw-r--r--util/flashrom_tester/flashrom/src/lib.rs14
-rw-r--r--util/flashrom_tester/src/main.rs43
4 files changed, 210 insertions, 10 deletions
diff --git a/util/flashrom_tester/flashrom/Cargo.toml b/util/flashrom_tester/flashrom/Cargo.toml
index 27216cbde..a2447d04f 100644
--- a/util/flashrom_tester/flashrom/Cargo.toml
+++ b/util/flashrom_tester/flashrom/Cargo.toml
@@ -6,4 +6,5 @@ authors = ["Edward O'Callaghan <quasisec@chromium.org>",
edition = "2018"
[dependencies]
-log = "0.4" \ No newline at end of file
+log = "0.4"
+libflashrom = { path = "../../../bindings/rust/libflashrom" }
diff --git a/util/flashrom_tester/flashrom/src/flashromlib.rs b/util/flashrom_tester/flashrom/src/flashromlib.rs
new file mode 100644
index 000000000..d20dbb228
--- /dev/null
+++ b/util/flashrom_tester/flashrom/src/flashromlib.rs
@@ -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()
+ }
+}
diff --git a/util/flashrom_tester/flashrom/src/lib.rs b/util/flashrom_tester/flashrom/src/lib.rs
index 5f168b529..7326391e1 100644
--- a/util/flashrom_tester/flashrom/src/lib.rs
+++ b/util/flashrom_tester/flashrom/src/lib.rs
@@ -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
diff --git a/util/flashrom_tester/src/main.rs b/util/flashrom_tester/src/main.rs
index dd09f9a30..129d1a9b7 100644
--- a/util/flashrom_tester/src/main.rs
+++ b/util/flashrom_tester/src/main.rs
@@ -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