mirror of
				https://review.coreboot.org/flashrom.git
				synced 2025-10-31 05:10:41 +01:00 
			
		
		
		
	flashrom_tester: Remove subprocess from elog_sanity_test
Make elog_sanity_test read the elog region itself, instead of calling out to elogtool. This avoids the need to subprocess and resolves a deadlock when elogtool attempts to obtain a flash reading lock. TEST=/usr/bin/flashrom_tester host Coreboot_ELOG_sanity TEST=flashrom --image RW_ELOG -p host -r /tmp/file.tmp2 # comparison TEST=hexdump the file and check magic signature == 0x474f4c45 Change-Id: I8ac63e15e063f9c0928e3e185154bb083b367ba9 Signed-off-by: Evan Benn <evanbenn@chromium.org> Reviewed-on: https://review.coreboot.org/c/flashrom/+/65119 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Peter Marheine <pmarheine@chromium.org> Reviewed-by: Edward O'Callaghan <quasisec@chromium.org>
This commit is contained in:
		 Evan Benn
					Evan Benn
				
			
				
					committed by
					
						 Edward O'Callaghan
						Edward O'Callaghan
					
				
			
			
				
	
			
			
			 Edward O'Callaghan
						Edward O'Callaghan
					
				
			
						parent
						
							b9e7d20d19
						
					
				
				
					commit
					4342cc0f14
				
			| @@ -64,6 +64,7 @@ pub struct IOOpt<'a> { | |||||||
|     pub write: Option<&'a str>,  // -w <file> |     pub write: Option<&'a str>,  // -w <file> | ||||||
|     pub verify: Option<&'a str>, // -v <file> |     pub verify: Option<&'a str>, // -v <file> | ||||||
|     pub erase: bool,             // -E |     pub erase: bool,             // -E | ||||||
|  |     pub region: Option<&'a str>, // --image | ||||||
| } | } | ||||||
|  |  | ||||||
| #[derive(PartialEq, Debug)] | #[derive(PartialEq, Debug)] | ||||||
| @@ -264,6 +265,22 @@ impl crate::Flashrom for FlashromCmd { | |||||||
|         Ok(()) |         Ok(()) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     fn read_region(&self, path: &str, region: &str) -> Result<(), FlashromError> { | ||||||
|  |         let opts = FlashromOpt { | ||||||
|  |             io_opt: IOOpt { | ||||||
|  |                 read: Some(path), | ||||||
|  |                 region: Some(region), | ||||||
|  |                 ..Default::default() | ||||||
|  |             }, | ||||||
|  |             ..Default::default() | ||||||
|  |         }; | ||||||
|  |  | ||||||
|  |         let (stdout, _) = self.dispatch(opts)?; | ||||||
|  |         let output = String::from_utf8_lossy(stdout.as_slice()); | ||||||
|  |         debug!("read():\n{}", output); | ||||||
|  |         Ok(()) | ||||||
|  |     } | ||||||
|  |  | ||||||
|     fn write(&self, path: &str) -> Result<(), FlashromError> { |     fn write(&self, path: &str) -> Result<(), FlashromError> { | ||||||
|         let opts = FlashromOpt { |         let opts = FlashromOpt { | ||||||
|             io_opt: IOOpt { |             io_opt: IOOpt { | ||||||
| @@ -338,6 +355,10 @@ fn flashrom_decode_opts(opts: FlashromOpt) -> Vec<String> { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     // io_opt |     // io_opt | ||||||
|  |     if let Some(region) = opts.io_opt.region { | ||||||
|  |         params.push("--image".to_string()); | ||||||
|  |         params.push(region.to_string()); | ||||||
|  |     } | ||||||
|     if opts.io_opt.read.is_some() { |     if opts.io_opt.read.is_some() { | ||||||
|         params.push("-r".to_string()); |         params.push("-r".to_string()); | ||||||
|         params.push(opts.io_opt.read.unwrap().to_string()); |         params.push(opts.io_opt.read.unwrap().to_string()); | ||||||
|   | |||||||
| @@ -114,6 +114,9 @@ pub trait Flashrom { | |||||||
|     /// Read the whole flash to the file specified by `path`. |     /// Read the whole flash to the file specified by `path`. | ||||||
|     fn read(&self, path: &str) -> Result<(), FlashromError>; |     fn read(&self, path: &str) -> Result<(), FlashromError>; | ||||||
|  |  | ||||||
|  |     /// Read only a region of the flash. | ||||||
|  |     fn read_region(&self, path: &str, region: &str) -> Result<(), FlashromError>; | ||||||
|  |  | ||||||
|     /// Write the whole flash to the file specified by `path`. |     /// Write the whole flash to the file specified by `path`. | ||||||
|     fn write(&self, path: &str) -> Result<(), FlashromError>; |     fn write(&self, path: &str) -> Result<(), FlashromError>; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -59,22 +59,3 @@ pub fn system_info() -> IoResult<String> { | |||||||
| pub fn bios_info() -> IoResult<String> { | pub fn bios_info() -> IoResult<String> { | ||||||
|     dmidecode_dispatch(&["-q", "-t0"]) |     dmidecode_dispatch(&["-q", "-t0"]) | ||||||
| } | } | ||||||
|  |  | ||||||
| pub fn eventlog_list() -> Result<String, std::io::Error> { |  | ||||||
|     elogtool_dispatch(&["list"]) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| fn elogtool_dispatch<S: AsRef<OsStr> + Debug>(args: &[S]) -> IoResult<String> { |  | ||||||
|     info!("elogtool_dispatch() running: /usr/bin/elogtool {:?}", args); |  | ||||||
|  |  | ||||||
|     let output = Command::new("/usr/bin/elogtool") |  | ||||||
|         .args(args) |  | ||||||
|         .stdin(Stdio::null()) |  | ||||||
|         .output()?; |  | ||||||
|     if !output.status.success() { |  | ||||||
|         return Err(utils::translate_command_error(&output)); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     let stdout = String::from_utf8_lossy(&output.stdout).into_owned(); |  | ||||||
|     Ok(stdout) |  | ||||||
| } |  | ||||||
|   | |||||||
| @@ -38,11 +38,13 @@ use super::tester::{self, OutputFormat, TestCase, TestEnv, TestResult}; | |||||||
| use super::utils::{self, LayoutNames}; | use super::utils::{self, LayoutNames}; | ||||||
| use flashrom::{FlashChip, Flashrom}; | use flashrom::{FlashChip, Flashrom}; | ||||||
| use std::collections::{HashMap, HashSet}; | use std::collections::{HashMap, HashSet}; | ||||||
| use std::fs::File; | use std::convert::TryInto; | ||||||
|  | use std::fs::{self, File}; | ||||||
| use std::io::{BufRead, Write}; | use std::io::{BufRead, Write}; | ||||||
| use std::sync::atomic::AtomicBool; | use std::sync::atomic::AtomicBool; | ||||||
|  |  | ||||||
| const LAYOUT_FILE: &'static str = "/tmp/layout.file"; | const LAYOUT_FILE: &'static str = "/tmp/layout.file"; | ||||||
|  | const ELOG_FILE: &'static str = "/tmp/elog.file"; | ||||||
|  |  | ||||||
| /// Iterate over tests, yielding only those tests with names matching filter_names. | /// Iterate over tests, yielding only those tests with names matching filter_names. | ||||||
| /// | /// | ||||||
| @@ -233,25 +235,28 @@ fn lock_test(env: &mut TestEnv) -> TestResult { | |||||||
|  |  | ||||||
| fn elog_sanity_test(env: &mut TestEnv) -> TestResult { | fn elog_sanity_test(env: &mut TestEnv) -> TestResult { | ||||||
|     // Check that the elog contains *something*, as an indication that Coreboot |     // Check that the elog contains *something*, as an indication that Coreboot | ||||||
|     // is actually able to write to the Flash. Because this invokes elogtool on |     // is actually able to write to the Flash. This only makes sense for chips | ||||||
|     // the host, it doesn't make sense to run for other chips. |     // running Coreboot, which we assume is just host. | ||||||
|     if env.chip_type() != FlashChip::HOST { |     if env.chip_type() != FlashChip::HOST { | ||||||
|         info!("Skipping ELOG sanity check for non-host chip"); |         info!("Skipping ELOG sanity check for non-host chip"); | ||||||
|         return Ok(()); |         return Ok(()); | ||||||
|     } |     } | ||||||
|     // elogtool reads the flash, it should be back in the golden state |     // flash should be back in the golden state | ||||||
|     env.ensure_golden()?; |     env.ensure_golden()?; | ||||||
|     // Output is one event per line, drop empty lines in the interest of being defensive. |  | ||||||
|     let event_count = cros_sysinfo::eventlog_list()? |  | ||||||
|         .lines() |  | ||||||
|         .filter(|l| !l.is_empty()) |  | ||||||
|         .count(); |  | ||||||
|  |  | ||||||
|     if event_count == 0 { |     const ELOG_RW_REGION_NAME: &str = "RW_ELOG"; | ||||||
|         Err("ELOG contained no events".into()) |     env.cmd.read_region(ELOG_FILE, ELOG_RW_REGION_NAME)?; | ||||||
|     } else { |  | ||||||
|         Ok(()) |     // Just checking for the magic numer | ||||||
|  |     // TODO: improve this test to read the events | ||||||
|  |     if fs::metadata(ELOG_FILE)?.len() < 4 { | ||||||
|  |         return Err("ELOG contained no data".into()); | ||||||
|     } |     } | ||||||
|  |     let data = fs::read(ELOG_FILE)?; | ||||||
|  |     if u32::from_be_bytes(data[0..4].try_into()?) != 0x474f4c45 { | ||||||
|  |         return Err("ELOG had bad magic number".into()); | ||||||
|  |     } | ||||||
|  |     Ok(()) | ||||||
| } | } | ||||||
|  |  | ||||||
| fn host_is_chrome_test(_env: &mut TestEnv) -> TestResult { | fn host_is_chrome_test(_env: &mut TestEnv) -> TestResult { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user