1*0d6140beSAndroid Build Coastguard Worker /*
2*0d6140beSAndroid Build Coastguard Worker * This file is part of the flashrom project.
3*0d6140beSAndroid Build Coastguard Worker *
4*0d6140beSAndroid Build Coastguard Worker * Copyright (C) 2022 The Chromium OS Authors
5*0d6140beSAndroid Build Coastguard Worker *
6*0d6140beSAndroid Build Coastguard Worker * This program is free software; you can redistribute it and/or modify
7*0d6140beSAndroid Build Coastguard Worker * it under the terms of the GNU General Public License as published by
8*0d6140beSAndroid Build Coastguard Worker * the Free Software Foundation; either version 2 of the License, or
9*0d6140beSAndroid Build Coastguard Worker * (at your option) any later version.
10*0d6140beSAndroid Build Coastguard Worker *
11*0d6140beSAndroid Build Coastguard Worker * This program is distributed in the hope that it will be useful,
12*0d6140beSAndroid Build Coastguard Worker * but WITHOUT ANY WARRANTY; without even the implied warranty of
13*0d6140beSAndroid Build Coastguard Worker * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14*0d6140beSAndroid Build Coastguard Worker * GNU General Public License for more details.
15*0d6140beSAndroid Build Coastguard Worker */
16*0d6140beSAndroid Build Coastguard Worker
17*0d6140beSAndroid Build Coastguard Worker //! # libflashrom
18*0d6140beSAndroid Build Coastguard Worker //!
19*0d6140beSAndroid Build Coastguard Worker //! The `libflashrom` library is a rust FFI binding to the flashrom library.
20*0d6140beSAndroid Build Coastguard Worker //! libflashrom can be used to read write and modify some settings of flash chips.
21*0d6140beSAndroid Build Coastguard Worker //! The library closely follows the libflashrom C API, but exports a `safe` interface
22*0d6140beSAndroid Build Coastguard Worker //! including automatic resource management and forced error checking.
23*0d6140beSAndroid Build Coastguard Worker //!
24*0d6140beSAndroid Build Coastguard Worker //! libflashrom does not support threading, all usage of this library must occur on one thread.
25*0d6140beSAndroid Build Coastguard Worker //!
26*0d6140beSAndroid Build Coastguard Worker //! Most of the library functionality is defined on the [`Chip`] type.
27*0d6140beSAndroid Build Coastguard Worker //!
28*0d6140beSAndroid Build Coastguard Worker //! Example:
29*0d6140beSAndroid Build Coastguard Worker //!
30*0d6140beSAndroid Build Coastguard Worker //! ```
31*0d6140beSAndroid Build Coastguard Worker //! use libflashrom::*;
32*0d6140beSAndroid Build Coastguard Worker //! let mut chip = Chip::new(
33*0d6140beSAndroid Build Coastguard Worker //! Programmer::new("dummy", Some("emulate=W25Q128FV")).unwrap(),
34*0d6140beSAndroid Build Coastguard Worker //! Some("W25Q128.V")
35*0d6140beSAndroid Build Coastguard Worker //! ).unwrap();
36*0d6140beSAndroid Build Coastguard Worker //! let mut buf = chip.image_read(None).unwrap();
37*0d6140beSAndroid Build Coastguard Worker //! buf[0] = 0xFE;
38*0d6140beSAndroid Build Coastguard Worker //! chip.image_write(&mut buf, None).unwrap();
39*0d6140beSAndroid Build Coastguard Worker //! ```
40*0d6140beSAndroid Build Coastguard Worker
41*0d6140beSAndroid Build Coastguard Worker use once_cell::sync::Lazy;
42*0d6140beSAndroid Build Coastguard Worker use regex::Regex;
43*0d6140beSAndroid Build Coastguard Worker use std::error;
44*0d6140beSAndroid Build Coastguard Worker use std::ffi::c_void;
45*0d6140beSAndroid Build Coastguard Worker use std::ffi::CStr;
46*0d6140beSAndroid Build Coastguard Worker use std::ffi::CString;
47*0d6140beSAndroid Build Coastguard Worker use std::fmt;
48*0d6140beSAndroid Build Coastguard Worker use std::io::Write;
49*0d6140beSAndroid Build Coastguard Worker use std::ptr::null;
50*0d6140beSAndroid Build Coastguard Worker use std::ptr::null_mut;
51*0d6140beSAndroid Build Coastguard Worker use std::ptr::NonNull;
52*0d6140beSAndroid Build Coastguard Worker use std::sync::Mutex;
53*0d6140beSAndroid Build Coastguard Worker use std::sync::Once;
54*0d6140beSAndroid Build Coastguard Worker
55*0d6140beSAndroid Build Coastguard Worker pub use libflashrom_sys::{
56*0d6140beSAndroid Build Coastguard Worker flashrom_log_level, FLASHROM_MSG_DEBUG, FLASHROM_MSG_DEBUG2, FLASHROM_MSG_ERROR,
57*0d6140beSAndroid Build Coastguard Worker FLASHROM_MSG_INFO, FLASHROM_MSG_SPEW, FLASHROM_MSG_WARN,
58*0d6140beSAndroid Build Coastguard Worker };
59*0d6140beSAndroid Build Coastguard Worker
60*0d6140beSAndroid Build Coastguard Worker pub use libflashrom_sys::flashrom_wp_mode;
61*0d6140beSAndroid Build Coastguard Worker
62*0d6140beSAndroid Build Coastguard Worker // libflashrom uses (start, len) or inclusive [start, end] for ranges.
63*0d6140beSAndroid Build Coastguard Worker // This type exists to rust RangeBounds types to a convenient internal format.
64*0d6140beSAndroid Build Coastguard Worker #[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
65*0d6140beSAndroid Build Coastguard Worker struct RangeInternal {
66*0d6140beSAndroid Build Coastguard Worker start: usize,
67*0d6140beSAndroid Build Coastguard Worker len: usize,
68*0d6140beSAndroid Build Coastguard Worker }
69*0d6140beSAndroid Build Coastguard Worker
70*0d6140beSAndroid Build Coastguard Worker /// The type returned for write protect and layout queries
71*0d6140beSAndroid Build Coastguard Worker pub type Range = std::ops::Range<usize>;
72*0d6140beSAndroid Build Coastguard Worker
73*0d6140beSAndroid Build Coastguard Worker impl<T> From<T> for RangeInternal
74*0d6140beSAndroid Build Coastguard Worker where
75*0d6140beSAndroid Build Coastguard Worker T: std::ops::RangeBounds<usize>,
76*0d6140beSAndroid Build Coastguard Worker {
from(range: T) -> Self77*0d6140beSAndroid Build Coastguard Worker fn from(range: T) -> Self {
78*0d6140beSAndroid Build Coastguard Worker let start = match range.start_bound() {
79*0d6140beSAndroid Build Coastguard Worker std::ops::Bound::Included(start) => *start,
80*0d6140beSAndroid Build Coastguard Worker std::ops::Bound::Excluded(start) => *start + 1,
81*0d6140beSAndroid Build Coastguard Worker std::ops::Bound::Unbounded => 0,
82*0d6140beSAndroid Build Coastguard Worker };
83*0d6140beSAndroid Build Coastguard Worker RangeInternal {
84*0d6140beSAndroid Build Coastguard Worker start,
85*0d6140beSAndroid Build Coastguard Worker len: match range.end_bound() {
86*0d6140beSAndroid Build Coastguard Worker std::ops::Bound::Included(end) => *end - start + 1,
87*0d6140beSAndroid Build Coastguard Worker std::ops::Bound::Excluded(end) => *end - start,
88*0d6140beSAndroid Build Coastguard Worker std::ops::Bound::Unbounded => usize::MAX - start,
89*0d6140beSAndroid Build Coastguard Worker },
90*0d6140beSAndroid Build Coastguard Worker }
91*0d6140beSAndroid Build Coastguard Worker }
92*0d6140beSAndroid Build Coastguard Worker }
93*0d6140beSAndroid Build Coastguard Worker
94*0d6140beSAndroid Build Coastguard Worker impl RangeInternal {
95*0d6140beSAndroid Build Coastguard Worker // inclusive end for libflashrom
end(&self) -> usize96*0d6140beSAndroid Build Coastguard Worker fn end(&self) -> usize {
97*0d6140beSAndroid Build Coastguard Worker self.start + self.len - 1
98*0d6140beSAndroid Build Coastguard Worker }
99*0d6140beSAndroid Build Coastguard Worker }
100*0d6140beSAndroid Build Coastguard Worker
101*0d6140beSAndroid Build Coastguard Worker // log_c is set to be the callback at [`Programmer`] init. It deals with va_list and calls log_rust.
102*0d6140beSAndroid Build Coastguard Worker // log_rust calls a user defined function, or by default log_eprint.
103*0d6140beSAndroid Build Coastguard Worker // log_eprint just writes to stderr.
104*0d6140beSAndroid Build Coastguard Worker extern "C" {
set_log_callback()105*0d6140beSAndroid Build Coastguard Worker fn set_log_callback();
106*0d6140beSAndroid Build Coastguard Worker // Modifying and reading current_level is not thread safe, but neither is
107*0d6140beSAndroid Build Coastguard Worker // the libflashrom implementation, so we shouldnt be using threads anyway.
108*0d6140beSAndroid Build Coastguard Worker static mut current_level: libflashrom_sys::flashrom_log_level;
109*0d6140beSAndroid Build Coastguard Worker }
110*0d6140beSAndroid Build Coastguard Worker
111*0d6140beSAndroid Build Coastguard Worker /// Callers can use this function to log to the [`Logger`] they have set via [`set_log_level`]
112*0d6140beSAndroid Build Coastguard Worker ///
113*0d6140beSAndroid Build Coastguard Worker /// However from rust it is likely easier to call the [`Logger`] directly.
114*0d6140beSAndroid Build Coastguard Worker #[no_mangle]
log_rust( level: libflashrom_sys::flashrom_log_level, format: &std::os::raw::c_char, )115*0d6140beSAndroid Build Coastguard Worker pub extern "C" fn log_rust(
116*0d6140beSAndroid Build Coastguard Worker level: libflashrom_sys::flashrom_log_level,
117*0d6140beSAndroid Build Coastguard Worker format: &std::os::raw::c_char,
118*0d6140beSAndroid Build Coastguard Worker ) {
119*0d6140beSAndroid Build Coastguard Worker // Because this function is called from C, it must not panic.
120*0d6140beSAndroid Build Coastguard Worker // SAFETY: log_c always provides a non null ptr to a null terminated string
121*0d6140beSAndroid Build Coastguard Worker // msg does not outlive format.
122*0d6140beSAndroid Build Coastguard Worker let msg = unsafe { CStr::from_ptr(format) }.to_string_lossy();
123*0d6140beSAndroid Build Coastguard Worker // Locking can fail if a thread panics while holding the lock.
124*0d6140beSAndroid Build Coastguard Worker match LOG_FN.lock() {
125*0d6140beSAndroid Build Coastguard Worker Ok(g) => (*g)(level, msg.as_ref()),
126*0d6140beSAndroid Build Coastguard Worker Err(_) => eprintln!("ERROR: libflashrom log failure to lock function"),
127*0d6140beSAndroid Build Coastguard Worker };
128*0d6140beSAndroid Build Coastguard Worker }
129*0d6140beSAndroid Build Coastguard Worker
log_eprint(_level: libflashrom_sys::flashrom_log_level, msg: &str)130*0d6140beSAndroid Build Coastguard Worker fn log_eprint(_level: libflashrom_sys::flashrom_log_level, msg: &str) {
131*0d6140beSAndroid Build Coastguard Worker // Because this function is called from C, it must not panic.
132*0d6140beSAndroid Build Coastguard Worker // Ignore the error.
133*0d6140beSAndroid Build Coastguard Worker let _ = std::io::stderr().write_all(msg.as_bytes());
134*0d6140beSAndroid Build Coastguard Worker }
135*0d6140beSAndroid Build Coastguard Worker
136*0d6140beSAndroid Build Coastguard Worker // Can't directly atexit(flashrom_shutdown) because it is unsafe
shutdown_wrapper()137*0d6140beSAndroid Build Coastguard Worker extern "C" fn shutdown_wrapper() {
138*0d6140beSAndroid Build Coastguard Worker unsafe {
139*0d6140beSAndroid Build Coastguard Worker libflashrom_sys::flashrom_shutdown();
140*0d6140beSAndroid Build Coastguard Worker }
141*0d6140beSAndroid Build Coastguard Worker }
142*0d6140beSAndroid Build Coastguard Worker
143*0d6140beSAndroid Build Coastguard Worker /// A callback to log flashrom messages. This must not panic.
144*0d6140beSAndroid Build Coastguard Worker pub type Logger = fn(libflashrom_sys::flashrom_log_level, &str);
145*0d6140beSAndroid Build Coastguard Worker
146*0d6140beSAndroid Build Coastguard Worker static LOG_FN: Lazy<Mutex<Logger>> = Lazy::new(|| Mutex::new(log_eprint));
147*0d6140beSAndroid Build Coastguard Worker
148*0d6140beSAndroid Build Coastguard Worker /// Set the maximum log message level that will be passed to [`Logger`]
149*0d6140beSAndroid Build Coastguard Worker ///
150*0d6140beSAndroid Build Coastguard Worker /// log_rust and therefore the provided [`Logger`] will only be called for messages
151*0d6140beSAndroid Build Coastguard Worker /// greater or equal to the provided priority.
152*0d6140beSAndroid Build Coastguard Worker ///
153*0d6140beSAndroid Build Coastguard Worker /// ```
154*0d6140beSAndroid Build Coastguard Worker /// use libflashrom::set_log_level;
155*0d6140beSAndroid Build Coastguard Worker /// use libflashrom::FLASHROM_MSG_SPEW;
156*0d6140beSAndroid Build Coastguard Worker /// // Disable logging.
157*0d6140beSAndroid Build Coastguard Worker /// set_log_level(None);
158*0d6140beSAndroid Build Coastguard Worker /// // Log all messages at priority FLASHROM_MSG_SPEW and above.
159*0d6140beSAndroid Build Coastguard Worker /// set_log_level(Some(FLASHROM_MSG_SPEW));
160*0d6140beSAndroid Build Coastguard Worker /// ```
set_log_level(level: Option<libflashrom_sys::flashrom_log_level>)161*0d6140beSAndroid Build Coastguard Worker pub fn set_log_level(level: Option<libflashrom_sys::flashrom_log_level>) {
162*0d6140beSAndroid Build Coastguard Worker // SAFETY: current_level is only read by log_c, in this thread.
163*0d6140beSAndroid Build Coastguard Worker match level {
164*0d6140beSAndroid Build Coastguard Worker Some(level) => unsafe { current_level = level + 1 },
165*0d6140beSAndroid Build Coastguard Worker None => unsafe { current_level = 0 },
166*0d6140beSAndroid Build Coastguard Worker };
167*0d6140beSAndroid Build Coastguard Worker }
168*0d6140beSAndroid Build Coastguard Worker
169*0d6140beSAndroid Build Coastguard Worker /// Set a [`Logger`] logging callback function
170*0d6140beSAndroid Build Coastguard Worker ///
171*0d6140beSAndroid Build Coastguard Worker /// Provided function must not panic, as it is called from C.
set_log_function(logger: Logger)172*0d6140beSAndroid Build Coastguard Worker pub fn set_log_function(logger: Logger) {
173*0d6140beSAndroid Build Coastguard Worker *LOG_FN.lock().unwrap() = logger;
174*0d6140beSAndroid Build Coastguard Worker }
175*0d6140beSAndroid Build Coastguard Worker
176*0d6140beSAndroid Build Coastguard Worker /// A type holding the error code returned by libflashrom and the function that returned the error.
177*0d6140beSAndroid Build Coastguard Worker ///
178*0d6140beSAndroid Build Coastguard Worker /// The error codes returned from each function differ in meaning, see libflashrom.h
179*0d6140beSAndroid Build Coastguard Worker #[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
180*0d6140beSAndroid Build Coastguard Worker pub struct ErrorCode {
181*0d6140beSAndroid Build Coastguard Worker function: &'static str,
182*0d6140beSAndroid Build Coastguard Worker code: i32,
183*0d6140beSAndroid Build Coastguard Worker }
184*0d6140beSAndroid Build Coastguard Worker
185*0d6140beSAndroid Build Coastguard Worker impl fmt::Display for ErrorCode {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result186*0d6140beSAndroid Build Coastguard Worker fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
187*0d6140beSAndroid Build Coastguard Worker write!(f, "libflashrom: {} returned {}", self.function, self.code)
188*0d6140beSAndroid Build Coastguard Worker }
189*0d6140beSAndroid Build Coastguard Worker }
190*0d6140beSAndroid Build Coastguard Worker
191*0d6140beSAndroid Build Coastguard Worker impl error::Error for ErrorCode {}
192*0d6140beSAndroid Build Coastguard Worker
193*0d6140beSAndroid Build Coastguard Worker impl From<ErrorCode> for String {
from(e: ErrorCode) -> Self194*0d6140beSAndroid Build Coastguard Worker fn from(e: ErrorCode) -> Self {
195*0d6140beSAndroid Build Coastguard Worker format!("{}", e)
196*0d6140beSAndroid Build Coastguard Worker }
197*0d6140beSAndroid Build Coastguard Worker }
198*0d6140beSAndroid Build Coastguard Worker
199*0d6140beSAndroid Build Coastguard Worker /// Errors from initialising libflashrom or a [`Programmer`]
200*0d6140beSAndroid Build Coastguard Worker #[derive(Clone, Debug, Eq, PartialEq)]
201*0d6140beSAndroid Build Coastguard Worker pub enum InitError {
202*0d6140beSAndroid Build Coastguard Worker DuplicateInit,
203*0d6140beSAndroid Build Coastguard Worker FlashromInit(ErrorCode),
204*0d6140beSAndroid Build Coastguard Worker InvalidName(std::ffi::NulError),
205*0d6140beSAndroid Build Coastguard Worker ProgrammerInit(ErrorCode),
206*0d6140beSAndroid Build Coastguard Worker }
207*0d6140beSAndroid Build Coastguard Worker
208*0d6140beSAndroid Build Coastguard Worker impl fmt::Display for InitError {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result209*0d6140beSAndroid Build Coastguard Worker fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
210*0d6140beSAndroid Build Coastguard Worker write!(f, "{:?}", self)
211*0d6140beSAndroid Build Coastguard Worker }
212*0d6140beSAndroid Build Coastguard Worker }
213*0d6140beSAndroid Build Coastguard Worker
214*0d6140beSAndroid Build Coastguard Worker impl error::Error for InitError {}
215*0d6140beSAndroid Build Coastguard Worker
216*0d6140beSAndroid Build Coastguard Worker impl From<InitError> for String {
from(e: InitError) -> Self217*0d6140beSAndroid Build Coastguard Worker fn from(e: InitError) -> Self {
218*0d6140beSAndroid Build Coastguard Worker format!("{:?}", e)
219*0d6140beSAndroid Build Coastguard Worker }
220*0d6140beSAndroid Build Coastguard Worker }
221*0d6140beSAndroid Build Coastguard Worker
222*0d6140beSAndroid Build Coastguard Worker impl From<std::ffi::NulError> for InitError {
from(err: std::ffi::NulError) -> InitError223*0d6140beSAndroid Build Coastguard Worker fn from(err: std::ffi::NulError) -> InitError {
224*0d6140beSAndroid Build Coastguard Worker InitError::InvalidName(err)
225*0d6140beSAndroid Build Coastguard Worker }
226*0d6140beSAndroid Build Coastguard Worker }
227*0d6140beSAndroid Build Coastguard Worker
228*0d6140beSAndroid Build Coastguard Worker /// Errors from probing a [`Chip`]
229*0d6140beSAndroid Build Coastguard Worker #[derive(Clone, Debug, Eq, PartialEq)]
230*0d6140beSAndroid Build Coastguard Worker pub enum ChipInitError {
231*0d6140beSAndroid Build Coastguard Worker InvalidName(std::ffi::NulError),
232*0d6140beSAndroid Build Coastguard Worker NoChipError,
233*0d6140beSAndroid Build Coastguard Worker MultipleChipsError,
234*0d6140beSAndroid Build Coastguard Worker ProbeError,
235*0d6140beSAndroid Build Coastguard Worker }
236*0d6140beSAndroid Build Coastguard Worker
237*0d6140beSAndroid Build Coastguard Worker impl fmt::Display for ChipInitError {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result238*0d6140beSAndroid Build Coastguard Worker fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
239*0d6140beSAndroid Build Coastguard Worker write!(f, "{:?}", self)
240*0d6140beSAndroid Build Coastguard Worker }
241*0d6140beSAndroid Build Coastguard Worker }
242*0d6140beSAndroid Build Coastguard Worker
243*0d6140beSAndroid Build Coastguard Worker impl error::Error for ChipInitError {}
244*0d6140beSAndroid Build Coastguard Worker
245*0d6140beSAndroid Build Coastguard Worker impl From<ChipInitError> for String {
from(e: ChipInitError) -> Self246*0d6140beSAndroid Build Coastguard Worker fn from(e: ChipInitError) -> Self {
247*0d6140beSAndroid Build Coastguard Worker format!("{:?}", e)
248*0d6140beSAndroid Build Coastguard Worker }
249*0d6140beSAndroid Build Coastguard Worker }
250*0d6140beSAndroid Build Coastguard Worker
251*0d6140beSAndroid Build Coastguard Worker impl From<std::ffi::NulError> for ChipInitError {
from(err: std::ffi::NulError) -> ChipInitError252*0d6140beSAndroid Build Coastguard Worker fn from(err: std::ffi::NulError) -> ChipInitError {
253*0d6140beSAndroid Build Coastguard Worker ChipInitError::InvalidName(err)
254*0d6140beSAndroid Build Coastguard Worker }
255*0d6140beSAndroid Build Coastguard Worker }
256*0d6140beSAndroid Build Coastguard Worker
257*0d6140beSAndroid Build Coastguard Worker #[derive(Clone, Debug, Eq, PartialEq)]
258*0d6140beSAndroid Build Coastguard Worker pub enum RegionError {
259*0d6140beSAndroid Build Coastguard Worker ErrorCode(ErrorCode),
260*0d6140beSAndroid Build Coastguard Worker InvalidName(std::ffi::NulError),
261*0d6140beSAndroid Build Coastguard Worker }
262*0d6140beSAndroid Build Coastguard Worker
263*0d6140beSAndroid Build Coastguard Worker impl fmt::Display for RegionError {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result264*0d6140beSAndroid Build Coastguard Worker fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
265*0d6140beSAndroid Build Coastguard Worker write!(f, "{:?}", self)
266*0d6140beSAndroid Build Coastguard Worker }
267*0d6140beSAndroid Build Coastguard Worker }
268*0d6140beSAndroid Build Coastguard Worker
269*0d6140beSAndroid Build Coastguard Worker impl error::Error for RegionError {}
270*0d6140beSAndroid Build Coastguard Worker
271*0d6140beSAndroid Build Coastguard Worker impl From<RegionError> for String {
from(e: RegionError) -> Self272*0d6140beSAndroid Build Coastguard Worker fn from(e: RegionError) -> Self {
273*0d6140beSAndroid Build Coastguard Worker format!("{:?}", e)
274*0d6140beSAndroid Build Coastguard Worker }
275*0d6140beSAndroid Build Coastguard Worker }
276*0d6140beSAndroid Build Coastguard Worker
277*0d6140beSAndroid Build Coastguard Worker impl From<std::ffi::NulError> for RegionError {
from(err: std::ffi::NulError) -> RegionError278*0d6140beSAndroid Build Coastguard Worker fn from(err: std::ffi::NulError) -> RegionError {
279*0d6140beSAndroid Build Coastguard Worker RegionError::InvalidName(err)
280*0d6140beSAndroid Build Coastguard Worker }
281*0d6140beSAndroid Build Coastguard Worker }
282*0d6140beSAndroid Build Coastguard Worker
283*0d6140beSAndroid Build Coastguard Worker #[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
284*0d6140beSAndroid Build Coastguard Worker pub struct ParseLayoutError(String);
285*0d6140beSAndroid Build Coastguard Worker
286*0d6140beSAndroid Build Coastguard Worker impl fmt::Display for ParseLayoutError {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result287*0d6140beSAndroid Build Coastguard Worker fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
288*0d6140beSAndroid Build Coastguard Worker write!(f, "{:?}", self)
289*0d6140beSAndroid Build Coastguard Worker }
290*0d6140beSAndroid Build Coastguard Worker }
291*0d6140beSAndroid Build Coastguard Worker
292*0d6140beSAndroid Build Coastguard Worker impl error::Error for ParseLayoutError {}
293*0d6140beSAndroid Build Coastguard Worker
294*0d6140beSAndroid Build Coastguard Worker impl From<ParseLayoutError> for String {
from(e: ParseLayoutError) -> Self295*0d6140beSAndroid Build Coastguard Worker fn from(e: ParseLayoutError) -> Self {
296*0d6140beSAndroid Build Coastguard Worker format!("{:?}", e)
297*0d6140beSAndroid Build Coastguard Worker }
298*0d6140beSAndroid Build Coastguard Worker }
299*0d6140beSAndroid Build Coastguard Worker
300*0d6140beSAndroid Build Coastguard Worker /// A translation of the flashrom_wp_result type
301*0d6140beSAndroid Build Coastguard Worker ///
302*0d6140beSAndroid Build Coastguard Worker /// WpOK is omitted, as it is not an error.
303*0d6140beSAndroid Build Coastguard Worker /// WpErrUnknown is used for an unknown error type.
304*0d6140beSAndroid Build Coastguard Worker /// Keep this list in sync with libflashrom.h
305*0d6140beSAndroid Build Coastguard Worker #[derive(Clone, Debug, Eq, Hash, PartialEq)]
306*0d6140beSAndroid Build Coastguard Worker pub enum WPError {
307*0d6140beSAndroid Build Coastguard Worker WpErrChipUnsupported,
308*0d6140beSAndroid Build Coastguard Worker WpErrOther,
309*0d6140beSAndroid Build Coastguard Worker WpErrReadFailed,
310*0d6140beSAndroid Build Coastguard Worker WpErrWriteFailed,
311*0d6140beSAndroid Build Coastguard Worker WpErrVerifyFailed,
312*0d6140beSAndroid Build Coastguard Worker WpErrRangeUnsupported,
313*0d6140beSAndroid Build Coastguard Worker WpErrModeUnsupported,
314*0d6140beSAndroid Build Coastguard Worker WpErrRangeListUnavailable,
315*0d6140beSAndroid Build Coastguard Worker WpErrUnsupportedState,
316*0d6140beSAndroid Build Coastguard Worker WpErrUnknown(libflashrom_sys::flashrom_wp_result),
317*0d6140beSAndroid Build Coastguard Worker }
318*0d6140beSAndroid Build Coastguard Worker
319*0d6140beSAndroid Build Coastguard Worker impl From<libflashrom_sys::flashrom_wp_result> for WPError {
from(e: libflashrom_sys::flashrom_wp_result) -> Self320*0d6140beSAndroid Build Coastguard Worker fn from(e: libflashrom_sys::flashrom_wp_result) -> Self {
321*0d6140beSAndroid Build Coastguard Worker assert!(e != libflashrom_sys::flashrom_wp_result::FLASHROM_WP_OK);
322*0d6140beSAndroid Build Coastguard Worker match e {
323*0d6140beSAndroid Build Coastguard Worker libflashrom_sys::flashrom_wp_result::FLASHROM_WP_ERR_CHIP_UNSUPPORTED => {
324*0d6140beSAndroid Build Coastguard Worker WPError::WpErrChipUnsupported
325*0d6140beSAndroid Build Coastguard Worker }
326*0d6140beSAndroid Build Coastguard Worker libflashrom_sys::flashrom_wp_result::FLASHROM_WP_ERR_OTHER => WPError::WpErrOther,
327*0d6140beSAndroid Build Coastguard Worker libflashrom_sys::flashrom_wp_result::FLASHROM_WP_ERR_READ_FAILED => {
328*0d6140beSAndroid Build Coastguard Worker WPError::WpErrReadFailed
329*0d6140beSAndroid Build Coastguard Worker }
330*0d6140beSAndroid Build Coastguard Worker libflashrom_sys::flashrom_wp_result::FLASHROM_WP_ERR_WRITE_FAILED => {
331*0d6140beSAndroid Build Coastguard Worker WPError::WpErrWriteFailed
332*0d6140beSAndroid Build Coastguard Worker }
333*0d6140beSAndroid Build Coastguard Worker libflashrom_sys::flashrom_wp_result::FLASHROM_WP_ERR_VERIFY_FAILED => {
334*0d6140beSAndroid Build Coastguard Worker WPError::WpErrVerifyFailed
335*0d6140beSAndroid Build Coastguard Worker }
336*0d6140beSAndroid Build Coastguard Worker libflashrom_sys::flashrom_wp_result::FLASHROM_WP_ERR_RANGE_UNSUPPORTED => {
337*0d6140beSAndroid Build Coastguard Worker WPError::WpErrRangeUnsupported
338*0d6140beSAndroid Build Coastguard Worker }
339*0d6140beSAndroid Build Coastguard Worker libflashrom_sys::flashrom_wp_result::FLASHROM_WP_ERR_MODE_UNSUPPORTED => {
340*0d6140beSAndroid Build Coastguard Worker WPError::WpErrModeUnsupported
341*0d6140beSAndroid Build Coastguard Worker }
342*0d6140beSAndroid Build Coastguard Worker libflashrom_sys::flashrom_wp_result::FLASHROM_WP_ERR_RANGE_LIST_UNAVAILABLE => {
343*0d6140beSAndroid Build Coastguard Worker WPError::WpErrRangeListUnavailable
344*0d6140beSAndroid Build Coastguard Worker }
345*0d6140beSAndroid Build Coastguard Worker libflashrom_sys::flashrom_wp_result::FLASHROM_WP_ERR_UNSUPPORTED_STATE => {
346*0d6140beSAndroid Build Coastguard Worker WPError::WpErrUnsupportedState
347*0d6140beSAndroid Build Coastguard Worker }
348*0d6140beSAndroid Build Coastguard Worker _ => WPError::WpErrUnknown(e), // this could also be a panic
349*0d6140beSAndroid Build Coastguard Worker }
350*0d6140beSAndroid Build Coastguard Worker }
351*0d6140beSAndroid Build Coastguard Worker }
352*0d6140beSAndroid Build Coastguard Worker
353*0d6140beSAndroid Build Coastguard Worker impl fmt::Display for WPError {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result354*0d6140beSAndroid Build Coastguard Worker fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
355*0d6140beSAndroid Build Coastguard Worker write!(f, "{:?}", self)
356*0d6140beSAndroid Build Coastguard Worker }
357*0d6140beSAndroid Build Coastguard Worker }
358*0d6140beSAndroid Build Coastguard Worker
359*0d6140beSAndroid Build Coastguard Worker impl error::Error for WPError {}
360*0d6140beSAndroid Build Coastguard Worker
361*0d6140beSAndroid Build Coastguard Worker impl From<WPError> for String {
from(e: WPError) -> Self362*0d6140beSAndroid Build Coastguard Worker fn from(e: WPError) -> Self {
363*0d6140beSAndroid Build Coastguard Worker format!("{:?}", e)
364*0d6140beSAndroid Build Coastguard Worker }
365*0d6140beSAndroid Build Coastguard Worker }
366*0d6140beSAndroid Build Coastguard Worker
367*0d6140beSAndroid Build Coastguard Worker /// Return a rust sanitised string derived from flashrom_version_info.
flashrom_version_info() -> Option<String>368*0d6140beSAndroid Build Coastguard Worker pub fn flashrom_version_info() -> Option<String> {
369*0d6140beSAndroid Build Coastguard Worker let p = unsafe { libflashrom_sys::flashrom_version_info() };
370*0d6140beSAndroid Build Coastguard Worker if p.is_null() {
371*0d6140beSAndroid Build Coastguard Worker None
372*0d6140beSAndroid Build Coastguard Worker } else {
373*0d6140beSAndroid Build Coastguard Worker // SAFETY: flashrom_version_info returns a global `const char flashrom_version[]`
374*0d6140beSAndroid Build Coastguard Worker // derived from `-DFLASHROM_VERSION`, this is not guaranteed to be
375*0d6140beSAndroid Build Coastguard Worker // null terminated, but is in a normal build.
376*0d6140beSAndroid Build Coastguard Worker Some(unsafe { CStr::from_ptr(p) }.to_string_lossy().into_owned())
377*0d6140beSAndroid Build Coastguard Worker }
378*0d6140beSAndroid Build Coastguard Worker }
379*0d6140beSAndroid Build Coastguard Worker
380*0d6140beSAndroid Build Coastguard Worker /// Structure for an initialised flashrom_programmer
381*0d6140beSAndroid Build Coastguard Worker // flashrom_programmer_init returns a pointer accepted by flashrom_flash_probe
382*0d6140beSAndroid Build Coastguard Worker // but this is not implemented at time of writing. When implemented the pointer
383*0d6140beSAndroid Build Coastguard Worker // can be stored here.
384*0d6140beSAndroid Build Coastguard Worker #[derive(Debug)]
385*0d6140beSAndroid Build Coastguard Worker pub struct Programmer {}
386*0d6140beSAndroid Build Coastguard Worker
387*0d6140beSAndroid Build Coastguard Worker /// Structure for an initialised flashrom chip, or flashrom_flashctx
388*0d6140beSAndroid Build Coastguard Worker // As returned by flashrom_flash_probe
389*0d6140beSAndroid Build Coastguard Worker // The layout is owned here as the chip only stores a pointer when a layout is set.
390*0d6140beSAndroid Build Coastguard Worker #[derive(Debug)]
391*0d6140beSAndroid Build Coastguard Worker pub struct Chip {
392*0d6140beSAndroid Build Coastguard Worker ctx: NonNull<libflashrom_sys::flashrom_flashctx>,
393*0d6140beSAndroid Build Coastguard Worker _programmer: Programmer,
394*0d6140beSAndroid Build Coastguard Worker layout: Option<Layout>,
395*0d6140beSAndroid Build Coastguard Worker }
396*0d6140beSAndroid Build Coastguard Worker
397*0d6140beSAndroid Build Coastguard Worker impl Programmer {
398*0d6140beSAndroid Build Coastguard Worker /// Initialise libflashrom and a programmer
399*0d6140beSAndroid Build Coastguard Worker ///
400*0d6140beSAndroid Build Coastguard Worker /// See libflashrom.h flashrom_programmer_init for argument documentation.
401*0d6140beSAndroid Build Coastguard Worker ///
402*0d6140beSAndroid Build Coastguard Worker /// Panics:
403*0d6140beSAndroid Build Coastguard Worker ///
404*0d6140beSAndroid Build Coastguard Worker /// If this libflashrom implementation returns a programmer pointer.
new( programmer_name: &str, programmer_options: Option<&str>, ) -> Result<Programmer, InitError>405*0d6140beSAndroid Build Coastguard Worker pub fn new(
406*0d6140beSAndroid Build Coastguard Worker programmer_name: &str,
407*0d6140beSAndroid Build Coastguard Worker programmer_options: Option<&str>,
408*0d6140beSAndroid Build Coastguard Worker ) -> Result<Programmer, InitError> {
409*0d6140beSAndroid Build Coastguard Worker static ONCE: Once = Once::new();
410*0d6140beSAndroid Build Coastguard Worker if ONCE.is_completed() {
411*0d6140beSAndroid Build Coastguard Worker // Flashrom does not currently support concurrent programmers
412*0d6140beSAndroid Build Coastguard Worker // Flashrom also does not currently support initialising a second programmer after a first has been initialised.
413*0d6140beSAndroid Build Coastguard Worker // This is used to warn the user if they try to initialise a second programmer.
414*0d6140beSAndroid Build Coastguard Worker return Err(InitError::DuplicateInit);
415*0d6140beSAndroid Build Coastguard Worker }
416*0d6140beSAndroid Build Coastguard Worker ONCE.call_once(|| {});
417*0d6140beSAndroid Build Coastguard Worker
418*0d6140beSAndroid Build Coastguard Worker static INIT_RES: Lazy<Result<(), InitError>> = Lazy::new(|| {
419*0d6140beSAndroid Build Coastguard Worker unsafe { set_log_callback() };
420*0d6140beSAndroid Build Coastguard Worker // always perform_selfcheck
421*0d6140beSAndroid Build Coastguard Worker let res = unsafe { libflashrom_sys::flashrom_init(1) };
422*0d6140beSAndroid Build Coastguard Worker if res == 0 {
423*0d6140beSAndroid Build Coastguard Worker let res = unsafe { libc::atexit(shutdown_wrapper) };
424*0d6140beSAndroid Build Coastguard Worker if res == 0 {
425*0d6140beSAndroid Build Coastguard Worker Ok(())
426*0d6140beSAndroid Build Coastguard Worker } else {
427*0d6140beSAndroid Build Coastguard Worker unsafe { libflashrom_sys::flashrom_shutdown() };
428*0d6140beSAndroid Build Coastguard Worker Err(InitError::FlashromInit(ErrorCode {
429*0d6140beSAndroid Build Coastguard Worker function: "atexit",
430*0d6140beSAndroid Build Coastguard Worker code: res,
431*0d6140beSAndroid Build Coastguard Worker }))
432*0d6140beSAndroid Build Coastguard Worker }
433*0d6140beSAndroid Build Coastguard Worker } else {
434*0d6140beSAndroid Build Coastguard Worker Err(InitError::FlashromInit(ErrorCode {
435*0d6140beSAndroid Build Coastguard Worker function: "flashrom_init",
436*0d6140beSAndroid Build Coastguard Worker code: res,
437*0d6140beSAndroid Build Coastguard Worker }))
438*0d6140beSAndroid Build Coastguard Worker }
439*0d6140beSAndroid Build Coastguard Worker });
440*0d6140beSAndroid Build Coastguard Worker (*INIT_RES).clone()?;
441*0d6140beSAndroid Build Coastguard Worker
442*0d6140beSAndroid Build Coastguard Worker let mut programmer: *mut libflashrom_sys::flashrom_programmer = null_mut();
443*0d6140beSAndroid Build Coastguard Worker let programmer_name = CString::new(programmer_name)?;
444*0d6140beSAndroid Build Coastguard Worker let programmer_options = match programmer_options {
445*0d6140beSAndroid Build Coastguard Worker Some(programmer_options) => Some(CString::new(programmer_options)?),
446*0d6140beSAndroid Build Coastguard Worker None => None,
447*0d6140beSAndroid Build Coastguard Worker };
448*0d6140beSAndroid Build Coastguard Worker let res = unsafe {
449*0d6140beSAndroid Build Coastguard Worker libflashrom_sys::flashrom_programmer_init(
450*0d6140beSAndroid Build Coastguard Worker &mut programmer,
451*0d6140beSAndroid Build Coastguard Worker programmer_name.as_ptr(),
452*0d6140beSAndroid Build Coastguard Worker programmer_options.as_ref().map_or(null(), |x| x.as_ptr()),
453*0d6140beSAndroid Build Coastguard Worker )
454*0d6140beSAndroid Build Coastguard Worker };
455*0d6140beSAndroid Build Coastguard Worker if res != 0 {
456*0d6140beSAndroid Build Coastguard Worker Err(InitError::ProgrammerInit(ErrorCode {
457*0d6140beSAndroid Build Coastguard Worker function: "flashrom_programmer_init",
458*0d6140beSAndroid Build Coastguard Worker code: res,
459*0d6140beSAndroid Build Coastguard Worker }))
460*0d6140beSAndroid Build Coastguard Worker } else if !programmer.is_null() {
461*0d6140beSAndroid Build Coastguard Worker panic!("flashrom_programmer_init returning a programmer pointer is not supported")
462*0d6140beSAndroid Build Coastguard Worker } else {
463*0d6140beSAndroid Build Coastguard Worker Ok(Programmer {})
464*0d6140beSAndroid Build Coastguard Worker }
465*0d6140beSAndroid Build Coastguard Worker }
466*0d6140beSAndroid Build Coastguard Worker }
467*0d6140beSAndroid Build Coastguard Worker
468*0d6140beSAndroid Build Coastguard Worker impl Drop for Programmer {
drop(&mut self)469*0d6140beSAndroid Build Coastguard Worker fn drop(&mut self) {
470*0d6140beSAndroid Build Coastguard Worker unsafe {
471*0d6140beSAndroid Build Coastguard Worker libflashrom_sys::flashrom_programmer_shutdown(null_mut());
472*0d6140beSAndroid Build Coastguard Worker }
473*0d6140beSAndroid Build Coastguard Worker }
474*0d6140beSAndroid Build Coastguard Worker }
475*0d6140beSAndroid Build Coastguard Worker
476*0d6140beSAndroid Build Coastguard Worker /// A translation of the flashrom_flag type
477*0d6140beSAndroid Build Coastguard Worker ///
478*0d6140beSAndroid Build Coastguard Worker /// Keep this list in sync with libflashrom.h
479*0d6140beSAndroid Build Coastguard Worker #[derive(Clone, Debug, Eq, Hash, PartialEq)]
480*0d6140beSAndroid Build Coastguard Worker pub enum FlashromFlag {
481*0d6140beSAndroid Build Coastguard Worker FlashromFlagForce,
482*0d6140beSAndroid Build Coastguard Worker FlashromFlagForceBoardmismatch,
483*0d6140beSAndroid Build Coastguard Worker FlashromFlagVerifyAfterWrite,
484*0d6140beSAndroid Build Coastguard Worker FlashromFlagVerifyWholeChip,
485*0d6140beSAndroid Build Coastguard Worker FlashromFlagSkipUnreadableRegions,
486*0d6140beSAndroid Build Coastguard Worker FlashromFlagSkipUnwritableRegions,
487*0d6140beSAndroid Build Coastguard Worker }
488*0d6140beSAndroid Build Coastguard Worker
489*0d6140beSAndroid Build Coastguard Worker impl From<FlashromFlag> for libflashrom_sys::flashrom_flag {
from(e: FlashromFlag) -> Self490*0d6140beSAndroid Build Coastguard Worker fn from(e: FlashromFlag) -> Self {
491*0d6140beSAndroid Build Coastguard Worker match e {
492*0d6140beSAndroid Build Coastguard Worker FlashromFlag::FlashromFlagForce => libflashrom_sys::flashrom_flag::FLASHROM_FLAG_FORCE,
493*0d6140beSAndroid Build Coastguard Worker FlashromFlag::FlashromFlagForceBoardmismatch => {
494*0d6140beSAndroid Build Coastguard Worker libflashrom_sys::flashrom_flag::FLASHROM_FLAG_FORCE_BOARDMISMATCH
495*0d6140beSAndroid Build Coastguard Worker }
496*0d6140beSAndroid Build Coastguard Worker FlashromFlag::FlashromFlagVerifyAfterWrite => {
497*0d6140beSAndroid Build Coastguard Worker libflashrom_sys::flashrom_flag::FLASHROM_FLAG_VERIFY_AFTER_WRITE
498*0d6140beSAndroid Build Coastguard Worker }
499*0d6140beSAndroid Build Coastguard Worker FlashromFlag::FlashromFlagVerifyWholeChip => {
500*0d6140beSAndroid Build Coastguard Worker libflashrom_sys::flashrom_flag::FLASHROM_FLAG_VERIFY_WHOLE_CHIP
501*0d6140beSAndroid Build Coastguard Worker }
502*0d6140beSAndroid Build Coastguard Worker FlashromFlag::FlashromFlagSkipUnreadableRegions => {
503*0d6140beSAndroid Build Coastguard Worker libflashrom_sys::flashrom_flag::FLASHROM_FLAG_SKIP_UNREADABLE_REGIONS
504*0d6140beSAndroid Build Coastguard Worker }
505*0d6140beSAndroid Build Coastguard Worker FlashromFlag::FlashromFlagSkipUnwritableRegions => {
506*0d6140beSAndroid Build Coastguard Worker libflashrom_sys::flashrom_flag::FLASHROM_FLAG_SKIP_UNWRITABLE_REGIONS
507*0d6140beSAndroid Build Coastguard Worker }
508*0d6140beSAndroid Build Coastguard Worker e => panic!("Unexpected FlashromFlag: {:?}", e),
509*0d6140beSAndroid Build Coastguard Worker }
510*0d6140beSAndroid Build Coastguard Worker }
511*0d6140beSAndroid Build Coastguard Worker }
512*0d6140beSAndroid Build Coastguard Worker
513*0d6140beSAndroid Build Coastguard Worker /// Various flags of the flashrom context
514*0d6140beSAndroid Build Coastguard Worker ///
515*0d6140beSAndroid Build Coastguard Worker /// Keep the struct in sync with the flags in flash.h
516*0d6140beSAndroid Build Coastguard Worker #[derive(Debug)]
517*0d6140beSAndroid Build Coastguard Worker pub struct FlashromFlags {
518*0d6140beSAndroid Build Coastguard Worker pub force: bool,
519*0d6140beSAndroid Build Coastguard Worker pub force_boardmismatch: bool,
520*0d6140beSAndroid Build Coastguard Worker pub verify_after_write: bool,
521*0d6140beSAndroid Build Coastguard Worker pub verify_whole_chip: bool,
522*0d6140beSAndroid Build Coastguard Worker pub skip_unreadable_regions: bool,
523*0d6140beSAndroid Build Coastguard Worker pub skip_unwritable_regions: bool,
524*0d6140beSAndroid Build Coastguard Worker }
525*0d6140beSAndroid Build Coastguard Worker
526*0d6140beSAndroid Build Coastguard Worker /// Keep the default values in sync with cli_classic.c
527*0d6140beSAndroid Build Coastguard Worker impl Default for FlashromFlags {
default() -> Self528*0d6140beSAndroid Build Coastguard Worker fn default() -> Self {
529*0d6140beSAndroid Build Coastguard Worker Self {
530*0d6140beSAndroid Build Coastguard Worker force: false,
531*0d6140beSAndroid Build Coastguard Worker force_boardmismatch: false,
532*0d6140beSAndroid Build Coastguard Worker verify_after_write: true,
533*0d6140beSAndroid Build Coastguard Worker verify_whole_chip: true,
534*0d6140beSAndroid Build Coastguard Worker // These flags are introduced to address issues related to CSME locking parts. Setting
535*0d6140beSAndroid Build Coastguard Worker // them to true as default values
536*0d6140beSAndroid Build Coastguard Worker skip_unreadable_regions: true,
537*0d6140beSAndroid Build Coastguard Worker skip_unwritable_regions: true,
538*0d6140beSAndroid Build Coastguard Worker }
539*0d6140beSAndroid Build Coastguard Worker }
540*0d6140beSAndroid Build Coastguard Worker }
541*0d6140beSAndroid Build Coastguard Worker
542*0d6140beSAndroid Build Coastguard Worker impl fmt::Display for FlashromFlags {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result543*0d6140beSAndroid Build Coastguard Worker fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
544*0d6140beSAndroid Build Coastguard Worker write!(
545*0d6140beSAndroid Build Coastguard Worker f,
546*0d6140beSAndroid Build Coastguard Worker "FlashromFlags {{ force: {}, force_boardmismatch: {}, verify_after_write: {}, verify_whole_chip: {}, skip_unreadable_regions: {}, skip_unwritable_regions: {} }}",
547*0d6140beSAndroid Build Coastguard Worker self.force,
548*0d6140beSAndroid Build Coastguard Worker self.force_boardmismatch,
549*0d6140beSAndroid Build Coastguard Worker self.verify_after_write,
550*0d6140beSAndroid Build Coastguard Worker self.verify_whole_chip,
551*0d6140beSAndroid Build Coastguard Worker self.skip_unreadable_regions,
552*0d6140beSAndroid Build Coastguard Worker self.skip_unwritable_regions,
553*0d6140beSAndroid Build Coastguard Worker )
554*0d6140beSAndroid Build Coastguard Worker }
555*0d6140beSAndroid Build Coastguard Worker }
556*0d6140beSAndroid Build Coastguard Worker
557*0d6140beSAndroid Build Coastguard Worker impl Chip {
558*0d6140beSAndroid Build Coastguard Worker /// Probe for a chip
559*0d6140beSAndroid Build Coastguard Worker ///
560*0d6140beSAndroid Build Coastguard Worker /// See libflashrom.h flashrom_flash_probe for argument documentation.
new(programmer: Programmer, chip_name: Option<&str>) -> Result<Chip, ChipInitError>561*0d6140beSAndroid Build Coastguard Worker pub fn new(programmer: Programmer, chip_name: Option<&str>) -> Result<Chip, ChipInitError> {
562*0d6140beSAndroid Build Coastguard Worker let mut flash_ctx: *mut libflashrom_sys::flashrom_flashctx = null_mut();
563*0d6140beSAndroid Build Coastguard Worker let chip_name = match chip_name {
564*0d6140beSAndroid Build Coastguard Worker Some(chip_name) => Some(CString::new(chip_name)?),
565*0d6140beSAndroid Build Coastguard Worker None => None,
566*0d6140beSAndroid Build Coastguard Worker };
567*0d6140beSAndroid Build Coastguard Worker match unsafe {
568*0d6140beSAndroid Build Coastguard Worker libflashrom_sys::flashrom_flash_probe(
569*0d6140beSAndroid Build Coastguard Worker &mut flash_ctx,
570*0d6140beSAndroid Build Coastguard Worker null(),
571*0d6140beSAndroid Build Coastguard Worker chip_name.as_ref().map_or(null(), |x| x.as_ptr()),
572*0d6140beSAndroid Build Coastguard Worker )
573*0d6140beSAndroid Build Coastguard Worker } {
574*0d6140beSAndroid Build Coastguard Worker 0 => Ok(Chip {
575*0d6140beSAndroid Build Coastguard Worker ctx: NonNull::new(flash_ctx).expect("flashrom_flash_probe returned null"),
576*0d6140beSAndroid Build Coastguard Worker _programmer: programmer,
577*0d6140beSAndroid Build Coastguard Worker layout: None,
578*0d6140beSAndroid Build Coastguard Worker }),
579*0d6140beSAndroid Build Coastguard Worker 3 => Err(ChipInitError::MultipleChipsError),
580*0d6140beSAndroid Build Coastguard Worker 2 => Err(ChipInitError::NoChipError),
581*0d6140beSAndroid Build Coastguard Worker _ => Err(ChipInitError::ProbeError),
582*0d6140beSAndroid Build Coastguard Worker }
583*0d6140beSAndroid Build Coastguard Worker }
584*0d6140beSAndroid Build Coastguard Worker
get_size(&self) -> usize585*0d6140beSAndroid Build Coastguard Worker pub fn get_size(&self) -> usize {
586*0d6140beSAndroid Build Coastguard Worker unsafe { libflashrom_sys::flashrom_flash_getsize(self.ctx.as_ref()) }
587*0d6140beSAndroid Build Coastguard Worker }
588*0d6140beSAndroid Build Coastguard Worker
589*0d6140beSAndroid Build Coastguard Worker /// Read the write protect config of this [`Chip`]
get_wp(&mut self) -> std::result::Result<WriteProtectCfg, WPError>590*0d6140beSAndroid Build Coastguard Worker pub fn get_wp(&mut self) -> std::result::Result<WriteProtectCfg, WPError> {
591*0d6140beSAndroid Build Coastguard Worker let mut cfg = WriteProtectCfg::new()?;
592*0d6140beSAndroid Build Coastguard Worker let res =
593*0d6140beSAndroid Build Coastguard Worker unsafe { libflashrom_sys::flashrom_wp_read_cfg(cfg.wp.as_mut(), self.ctx.as_mut()) };
594*0d6140beSAndroid Build Coastguard Worker if res != libflashrom_sys::flashrom_wp_result::FLASHROM_WP_OK {
595*0d6140beSAndroid Build Coastguard Worker return Err(res.into());
596*0d6140beSAndroid Build Coastguard Worker }
597*0d6140beSAndroid Build Coastguard Worker Ok(cfg)
598*0d6140beSAndroid Build Coastguard Worker }
599*0d6140beSAndroid Build Coastguard Worker
600*0d6140beSAndroid Build Coastguard Worker /// Set the write protect config of this [`Chip`]
set_wp(&mut self, wp: &WriteProtectCfg) -> std::result::Result<(), WPError>601*0d6140beSAndroid Build Coastguard Worker pub fn set_wp(&mut self, wp: &WriteProtectCfg) -> std::result::Result<(), WPError> {
602*0d6140beSAndroid Build Coastguard Worker let res =
603*0d6140beSAndroid Build Coastguard Worker unsafe { libflashrom_sys::flashrom_wp_write_cfg(self.ctx.as_mut(), wp.wp.as_ref()) };
604*0d6140beSAndroid Build Coastguard Worker if res != libflashrom_sys::flashrom_wp_result::FLASHROM_WP_OK {
605*0d6140beSAndroid Build Coastguard Worker return Err(res.into());
606*0d6140beSAndroid Build Coastguard Worker }
607*0d6140beSAndroid Build Coastguard Worker Ok(())
608*0d6140beSAndroid Build Coastguard Worker }
609*0d6140beSAndroid Build Coastguard Worker
610*0d6140beSAndroid Build Coastguard Worker /// Read the write protect ranges of this [`Chip`]
611*0d6140beSAndroid Build Coastguard Worker ///
612*0d6140beSAndroid Build Coastguard Worker /// # Panics
613*0d6140beSAndroid Build Coastguard Worker ///
614*0d6140beSAndroid Build Coastguard Worker /// Panics if flashrom_wp_get_available_ranges returns FLASHROM_WP_OK and a NULL pointer.
get_wp_ranges(&mut self) -> std::result::Result<Vec<Range>, WPError>615*0d6140beSAndroid Build Coastguard Worker pub fn get_wp_ranges(&mut self) -> std::result::Result<Vec<Range>, WPError> {
616*0d6140beSAndroid Build Coastguard Worker let mut ranges: *mut libflashrom_sys::flashrom_wp_ranges = null_mut();
617*0d6140beSAndroid Build Coastguard Worker let res = unsafe {
618*0d6140beSAndroid Build Coastguard Worker libflashrom_sys::flashrom_wp_get_available_ranges(&mut ranges, self.ctx.as_mut())
619*0d6140beSAndroid Build Coastguard Worker };
620*0d6140beSAndroid Build Coastguard Worker if res != libflashrom_sys::flashrom_wp_result::FLASHROM_WP_OK {
621*0d6140beSAndroid Build Coastguard Worker return Err(res.into());
622*0d6140beSAndroid Build Coastguard Worker }
623*0d6140beSAndroid Build Coastguard Worker let ranges = WriteProtectRanges {
624*0d6140beSAndroid Build Coastguard Worker ranges: NonNull::new(ranges).expect("flashrom_wp_get_available_ranges returned null"),
625*0d6140beSAndroid Build Coastguard Worker };
626*0d6140beSAndroid Build Coastguard Worker
627*0d6140beSAndroid Build Coastguard Worker let count =
628*0d6140beSAndroid Build Coastguard Worker unsafe { libflashrom_sys::flashrom_wp_ranges_get_count(ranges.ranges.as_ref()) };
629*0d6140beSAndroid Build Coastguard Worker let mut ret = Vec::with_capacity(count);
630*0d6140beSAndroid Build Coastguard Worker for index in 0..count {
631*0d6140beSAndroid Build Coastguard Worker let mut start = 0;
632*0d6140beSAndroid Build Coastguard Worker let mut len = 0;
633*0d6140beSAndroid Build Coastguard Worker let res = unsafe {
634*0d6140beSAndroid Build Coastguard Worker libflashrom_sys::flashrom_wp_ranges_get_range(
635*0d6140beSAndroid Build Coastguard Worker &mut start,
636*0d6140beSAndroid Build Coastguard Worker &mut len,
637*0d6140beSAndroid Build Coastguard Worker ranges.ranges.as_ref(),
638*0d6140beSAndroid Build Coastguard Worker // TODO: fix after https://review.coreboot.org/c/flashrom/+/64996
639*0d6140beSAndroid Build Coastguard Worker index
640*0d6140beSAndroid Build Coastguard Worker .try_into()
641*0d6140beSAndroid Build Coastguard Worker .expect("flashrom_wp_ranges_get_count does not fit in a u32"),
642*0d6140beSAndroid Build Coastguard Worker )
643*0d6140beSAndroid Build Coastguard Worker };
644*0d6140beSAndroid Build Coastguard Worker if res != libflashrom_sys::flashrom_wp_result::FLASHROM_WP_OK {
645*0d6140beSAndroid Build Coastguard Worker return Err(res.into());
646*0d6140beSAndroid Build Coastguard Worker }
647*0d6140beSAndroid Build Coastguard Worker ret.push(start..(start + len))
648*0d6140beSAndroid Build Coastguard Worker }
649*0d6140beSAndroid Build Coastguard Worker Ok(ret)
650*0d6140beSAndroid Build Coastguard Worker }
651*0d6140beSAndroid Build Coastguard Worker
652*0d6140beSAndroid Build Coastguard Worker /// Returns the layout read from the fmap of this [`Chip`]
653*0d6140beSAndroid Build Coastguard Worker ///
654*0d6140beSAndroid Build Coastguard Worker /// # Panics
655*0d6140beSAndroid Build Coastguard Worker ///
656*0d6140beSAndroid Build Coastguard Worker /// Panics if flashrom_layout_read_fmap_from_rom returns FLASHROM_WP_OK and a NULL pointer.
layout_read_fmap_from_rom(&mut self) -> std::result::Result<Layout, ErrorCode>657*0d6140beSAndroid Build Coastguard Worker pub fn layout_read_fmap_from_rom(&mut self) -> std::result::Result<Layout, ErrorCode> {
658*0d6140beSAndroid Build Coastguard Worker let mut layout: *mut libflashrom_sys::flashrom_layout = null_mut();
659*0d6140beSAndroid Build Coastguard Worker let err = unsafe {
660*0d6140beSAndroid Build Coastguard Worker libflashrom_sys::flashrom_layout_read_fmap_from_rom(
661*0d6140beSAndroid Build Coastguard Worker &mut layout,
662*0d6140beSAndroid Build Coastguard Worker self.ctx.as_mut(),
663*0d6140beSAndroid Build Coastguard Worker 0,
664*0d6140beSAndroid Build Coastguard Worker self.get_size(),
665*0d6140beSAndroid Build Coastguard Worker )
666*0d6140beSAndroid Build Coastguard Worker };
667*0d6140beSAndroid Build Coastguard Worker if err != 0 {
668*0d6140beSAndroid Build Coastguard Worker return Err(ErrorCode {
669*0d6140beSAndroid Build Coastguard Worker function: "flashrom_layout_read_fmap_from_rom",
670*0d6140beSAndroid Build Coastguard Worker code: err,
671*0d6140beSAndroid Build Coastguard Worker });
672*0d6140beSAndroid Build Coastguard Worker }
673*0d6140beSAndroid Build Coastguard Worker Ok(Layout {
674*0d6140beSAndroid Build Coastguard Worker layout: NonNull::new(layout).expect("flashrom_layout_read_fmap_from_rom returned null"),
675*0d6140beSAndroid Build Coastguard Worker })
676*0d6140beSAndroid Build Coastguard Worker }
677*0d6140beSAndroid Build Coastguard Worker
678*0d6140beSAndroid Build Coastguard Worker /// Sets the layout of this [`Chip`]
679*0d6140beSAndroid Build Coastguard Worker ///
680*0d6140beSAndroid Build Coastguard Worker /// [`Chip`] takes ownership of Layout to ensure it is not released before the [`Chip`].
set_layout(&mut self, layout: Layout)681*0d6140beSAndroid Build Coastguard Worker fn set_layout(&mut self, layout: Layout) {
682*0d6140beSAndroid Build Coastguard Worker unsafe { libflashrom_sys::flashrom_layout_set(self.ctx.as_mut(), layout.layout.as_ref()) };
683*0d6140beSAndroid Build Coastguard Worker self.layout = Some(layout)
684*0d6140beSAndroid Build Coastguard Worker }
685*0d6140beSAndroid Build Coastguard Worker
unset_layout(&mut self) -> Option<Layout>686*0d6140beSAndroid Build Coastguard Worker fn unset_layout(&mut self) -> Option<Layout> {
687*0d6140beSAndroid Build Coastguard Worker unsafe { libflashrom_sys::flashrom_layout_set(self.ctx.as_mut(), null()) };
688*0d6140beSAndroid Build Coastguard Worker self.layout.take()
689*0d6140beSAndroid Build Coastguard Worker }
690*0d6140beSAndroid Build Coastguard Worker
691*0d6140beSAndroid Build Coastguard Worker /// Read the whole [`Chip`], or a portion specified in a Layout
image_read( &mut self, layout: Option<Layout>, ) -> std::result::Result<Vec<u8>, ErrorCode>692*0d6140beSAndroid Build Coastguard Worker pub fn image_read(
693*0d6140beSAndroid Build Coastguard Worker &mut self,
694*0d6140beSAndroid Build Coastguard Worker layout: Option<Layout>,
695*0d6140beSAndroid Build Coastguard Worker ) -> std::result::Result<Vec<u8>, ErrorCode> {
696*0d6140beSAndroid Build Coastguard Worker if let Some(layout) = layout {
697*0d6140beSAndroid Build Coastguard Worker self.set_layout(layout);
698*0d6140beSAndroid Build Coastguard Worker }
699*0d6140beSAndroid Build Coastguard Worker let len = self.get_size();
700*0d6140beSAndroid Build Coastguard Worker let mut buf = vec![0; len];
701*0d6140beSAndroid Build Coastguard Worker let res = unsafe {
702*0d6140beSAndroid Build Coastguard Worker libflashrom_sys::flashrom_image_read(
703*0d6140beSAndroid Build Coastguard Worker self.ctx.as_mut(),
704*0d6140beSAndroid Build Coastguard Worker buf.as_mut_ptr() as *mut c_void,
705*0d6140beSAndroid Build Coastguard Worker len,
706*0d6140beSAndroid Build Coastguard Worker )
707*0d6140beSAndroid Build Coastguard Worker };
708*0d6140beSAndroid Build Coastguard Worker self.unset_layout();
709*0d6140beSAndroid Build Coastguard Worker
710*0d6140beSAndroid Build Coastguard Worker if res == 0 {
711*0d6140beSAndroid Build Coastguard Worker Ok(buf)
712*0d6140beSAndroid Build Coastguard Worker } else {
713*0d6140beSAndroid Build Coastguard Worker Err(ErrorCode {
714*0d6140beSAndroid Build Coastguard Worker function: "flashrom_image_read",
715*0d6140beSAndroid Build Coastguard Worker code: res,
716*0d6140beSAndroid Build Coastguard Worker })
717*0d6140beSAndroid Build Coastguard Worker }
718*0d6140beSAndroid Build Coastguard Worker }
719*0d6140beSAndroid Build Coastguard Worker
720*0d6140beSAndroid Build Coastguard Worker /// Write the whole [`Chip`], or a portion specified in a Layout
image_write( &mut self, buf: &mut [u8], layout: Option<Layout>, ) -> std::result::Result<(), ErrorCode>721*0d6140beSAndroid Build Coastguard Worker pub fn image_write(
722*0d6140beSAndroid Build Coastguard Worker &mut self,
723*0d6140beSAndroid Build Coastguard Worker buf: &mut [u8],
724*0d6140beSAndroid Build Coastguard Worker layout: Option<Layout>,
725*0d6140beSAndroid Build Coastguard Worker ) -> std::result::Result<(), ErrorCode> {
726*0d6140beSAndroid Build Coastguard Worker if let Some(layout) = layout {
727*0d6140beSAndroid Build Coastguard Worker self.set_layout(layout);
728*0d6140beSAndroid Build Coastguard Worker }
729*0d6140beSAndroid Build Coastguard Worker let res = unsafe {
730*0d6140beSAndroid Build Coastguard Worker libflashrom_sys::flashrom_image_write(
731*0d6140beSAndroid Build Coastguard Worker self.ctx.as_mut(),
732*0d6140beSAndroid Build Coastguard Worker buf.as_mut_ptr() as *mut c_void,
733*0d6140beSAndroid Build Coastguard Worker buf.len(),
734*0d6140beSAndroid Build Coastguard Worker null(),
735*0d6140beSAndroid Build Coastguard Worker )
736*0d6140beSAndroid Build Coastguard Worker };
737*0d6140beSAndroid Build Coastguard Worker self.unset_layout();
738*0d6140beSAndroid Build Coastguard Worker
739*0d6140beSAndroid Build Coastguard Worker if res == 0 {
740*0d6140beSAndroid Build Coastguard Worker Ok(())
741*0d6140beSAndroid Build Coastguard Worker } else {
742*0d6140beSAndroid Build Coastguard Worker Err(ErrorCode {
743*0d6140beSAndroid Build Coastguard Worker function: "flashrom_image_write",
744*0d6140beSAndroid Build Coastguard Worker code: res,
745*0d6140beSAndroid Build Coastguard Worker })
746*0d6140beSAndroid Build Coastguard Worker }
747*0d6140beSAndroid Build Coastguard Worker }
748*0d6140beSAndroid Build Coastguard Worker
749*0d6140beSAndroid Build Coastguard Worker /// Verify the whole [`Chip`], or a portion specified in a Layout
image_verify( &mut self, buf: &[u8], layout: Option<Layout>, ) -> std::result::Result<(), ErrorCode>750*0d6140beSAndroid Build Coastguard Worker pub fn image_verify(
751*0d6140beSAndroid Build Coastguard Worker &mut self,
752*0d6140beSAndroid Build Coastguard Worker buf: &[u8],
753*0d6140beSAndroid Build Coastguard Worker layout: Option<Layout>,
754*0d6140beSAndroid Build Coastguard Worker ) -> std::result::Result<(), ErrorCode> {
755*0d6140beSAndroid Build Coastguard Worker if let Some(layout) = layout {
756*0d6140beSAndroid Build Coastguard Worker self.set_layout(layout);
757*0d6140beSAndroid Build Coastguard Worker }
758*0d6140beSAndroid Build Coastguard Worker let res = unsafe {
759*0d6140beSAndroid Build Coastguard Worker libflashrom_sys::flashrom_image_verify(
760*0d6140beSAndroid Build Coastguard Worker self.ctx.as_mut(),
761*0d6140beSAndroid Build Coastguard Worker buf.as_ptr() as *const c_void,
762*0d6140beSAndroid Build Coastguard Worker buf.len(),
763*0d6140beSAndroid Build Coastguard Worker )
764*0d6140beSAndroid Build Coastguard Worker };
765*0d6140beSAndroid Build Coastguard Worker self.unset_layout();
766*0d6140beSAndroid Build Coastguard Worker
767*0d6140beSAndroid Build Coastguard Worker if res == 0 {
768*0d6140beSAndroid Build Coastguard Worker Ok(())
769*0d6140beSAndroid Build Coastguard Worker } else {
770*0d6140beSAndroid Build Coastguard Worker Err(ErrorCode {
771*0d6140beSAndroid Build Coastguard Worker function: "flashrom_image_verify",
772*0d6140beSAndroid Build Coastguard Worker code: res,
773*0d6140beSAndroid Build Coastguard Worker })
774*0d6140beSAndroid Build Coastguard Worker }
775*0d6140beSAndroid Build Coastguard Worker }
776*0d6140beSAndroid Build Coastguard Worker
777*0d6140beSAndroid Build Coastguard Worker /// Erase the whole [`Chip`]
erase(&mut self) -> std::result::Result<(), ErrorCode>778*0d6140beSAndroid Build Coastguard Worker pub fn erase(&mut self) -> std::result::Result<(), ErrorCode> {
779*0d6140beSAndroid Build Coastguard Worker let res = unsafe { libflashrom_sys::flashrom_flash_erase(self.ctx.as_mut()) };
780*0d6140beSAndroid Build Coastguard Worker if res == 0 {
781*0d6140beSAndroid Build Coastguard Worker Ok(())
782*0d6140beSAndroid Build Coastguard Worker } else {
783*0d6140beSAndroid Build Coastguard Worker Err(ErrorCode {
784*0d6140beSAndroid Build Coastguard Worker function: "flashrom_flash_erase",
785*0d6140beSAndroid Build Coastguard Worker code: res,
786*0d6140beSAndroid Build Coastguard Worker })
787*0d6140beSAndroid Build Coastguard Worker }
788*0d6140beSAndroid Build Coastguard Worker }
789*0d6140beSAndroid Build Coastguard Worker
790*0d6140beSAndroid Build Coastguard Worker /// Set a flag in the given flash context
flag_set(&mut self, flag: FlashromFlag, value: bool) -> ()791*0d6140beSAndroid Build Coastguard Worker pub fn flag_set(&mut self, flag: FlashromFlag, value: bool) -> () {
792*0d6140beSAndroid Build Coastguard Worker unsafe { libflashrom_sys::flashrom_flag_set(self.ctx.as_mut(), flag.into(), value) }
793*0d6140beSAndroid Build Coastguard Worker }
794*0d6140beSAndroid Build Coastguard Worker }
795*0d6140beSAndroid Build Coastguard Worker
796*0d6140beSAndroid Build Coastguard Worker impl Drop for Chip {
drop(&mut self)797*0d6140beSAndroid Build Coastguard Worker fn drop(&mut self) {
798*0d6140beSAndroid Build Coastguard Worker unsafe {
799*0d6140beSAndroid Build Coastguard Worker libflashrom_sys::flashrom_flash_release(self.ctx.as_mut());
800*0d6140beSAndroid Build Coastguard Worker }
801*0d6140beSAndroid Build Coastguard Worker }
802*0d6140beSAndroid Build Coastguard Worker }
803*0d6140beSAndroid Build Coastguard Worker
804*0d6140beSAndroid Build Coastguard Worker /// Structure for an initialised flashrom_wp_cfg
805*0d6140beSAndroid Build Coastguard Worker #[derive(Debug)]
806*0d6140beSAndroid Build Coastguard Worker pub struct WriteProtectCfg {
807*0d6140beSAndroid Build Coastguard Worker wp: NonNull<libflashrom_sys::flashrom_wp_cfg>,
808*0d6140beSAndroid Build Coastguard Worker }
809*0d6140beSAndroid Build Coastguard Worker
810*0d6140beSAndroid Build Coastguard Worker impl WriteProtectCfg {
811*0d6140beSAndroid Build Coastguard Worker /// Create an empty [`WriteProtectCfg`]
812*0d6140beSAndroid Build Coastguard Worker ///
813*0d6140beSAndroid Build Coastguard Worker /// # Panics
814*0d6140beSAndroid Build Coastguard Worker ///
815*0d6140beSAndroid Build Coastguard Worker /// Panics if flashrom_wp_cfg_new returns FLASHROM_WP_OK and a NULL pointer.
new() -> std::result::Result<WriteProtectCfg, WPError>816*0d6140beSAndroid Build Coastguard Worker pub fn new() -> std::result::Result<WriteProtectCfg, WPError> {
817*0d6140beSAndroid Build Coastguard Worker let mut cfg: *mut libflashrom_sys::flashrom_wp_cfg = null_mut();
818*0d6140beSAndroid Build Coastguard Worker let res = unsafe { libflashrom_sys::flashrom_wp_cfg_new(&mut cfg) };
819*0d6140beSAndroid Build Coastguard Worker if res != libflashrom_sys::flashrom_wp_result::FLASHROM_WP_OK {
820*0d6140beSAndroid Build Coastguard Worker return Err(res.into());
821*0d6140beSAndroid Build Coastguard Worker }
822*0d6140beSAndroid Build Coastguard Worker Ok(WriteProtectCfg {
823*0d6140beSAndroid Build Coastguard Worker wp: NonNull::new(cfg).expect("flashrom_wp_cfg_new returned null"),
824*0d6140beSAndroid Build Coastguard Worker })
825*0d6140beSAndroid Build Coastguard Worker }
826*0d6140beSAndroid Build Coastguard Worker
get_mode(&self) -> libflashrom_sys::flashrom_wp_mode827*0d6140beSAndroid Build Coastguard Worker pub fn get_mode(&self) -> libflashrom_sys::flashrom_wp_mode {
828*0d6140beSAndroid Build Coastguard Worker unsafe { libflashrom_sys::flashrom_wp_get_mode(self.wp.as_ref()) }
829*0d6140beSAndroid Build Coastguard Worker }
830*0d6140beSAndroid Build Coastguard Worker
set_mode(&mut self, mode: libflashrom_sys::flashrom_wp_mode)831*0d6140beSAndroid Build Coastguard Worker pub fn set_mode(&mut self, mode: libflashrom_sys::flashrom_wp_mode) {
832*0d6140beSAndroid Build Coastguard Worker unsafe { libflashrom_sys::flashrom_wp_set_mode(self.wp.as_mut(), mode) }
833*0d6140beSAndroid Build Coastguard Worker }
834*0d6140beSAndroid Build Coastguard Worker
get_range(&self) -> Range835*0d6140beSAndroid Build Coastguard Worker pub fn get_range(&self) -> Range {
836*0d6140beSAndroid Build Coastguard Worker let mut start = 0;
837*0d6140beSAndroid Build Coastguard Worker let mut len = 0;
838*0d6140beSAndroid Build Coastguard Worker unsafe { libflashrom_sys::flashrom_wp_get_range(&mut start, &mut len, self.wp.as_ref()) };
839*0d6140beSAndroid Build Coastguard Worker start..(start + len)
840*0d6140beSAndroid Build Coastguard Worker }
841*0d6140beSAndroid Build Coastguard Worker
set_range<T>(&mut self, range: T) where T: std::ops::RangeBounds<usize>,842*0d6140beSAndroid Build Coastguard Worker pub fn set_range<T>(&mut self, range: T)
843*0d6140beSAndroid Build Coastguard Worker where
844*0d6140beSAndroid Build Coastguard Worker T: std::ops::RangeBounds<usize>,
845*0d6140beSAndroid Build Coastguard Worker {
846*0d6140beSAndroid Build Coastguard Worker let range: RangeInternal = range.into();
847*0d6140beSAndroid Build Coastguard Worker unsafe { libflashrom_sys::flashrom_wp_set_range(self.wp.as_mut(), range.start, range.len) }
848*0d6140beSAndroid Build Coastguard Worker }
849*0d6140beSAndroid Build Coastguard Worker }
850*0d6140beSAndroid Build Coastguard Worker
851*0d6140beSAndroid Build Coastguard Worker impl Drop for WriteProtectCfg {
drop(&mut self)852*0d6140beSAndroid Build Coastguard Worker fn drop(&mut self) {
853*0d6140beSAndroid Build Coastguard Worker unsafe {
854*0d6140beSAndroid Build Coastguard Worker libflashrom_sys::flashrom_wp_cfg_release(self.wp.as_mut());
855*0d6140beSAndroid Build Coastguard Worker }
856*0d6140beSAndroid Build Coastguard Worker }
857*0d6140beSAndroid Build Coastguard Worker }
858*0d6140beSAndroid Build Coastguard Worker
859*0d6140beSAndroid Build Coastguard Worker impl fmt::Display for WriteProtectCfg {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result860*0d6140beSAndroid Build Coastguard Worker fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
861*0d6140beSAndroid Build Coastguard Worker write!(f, "range:{:?} mode:{:?}", self.get_range(), self.get_mode())
862*0d6140beSAndroid Build Coastguard Worker }
863*0d6140beSAndroid Build Coastguard Worker }
864*0d6140beSAndroid Build Coastguard Worker
865*0d6140beSAndroid Build Coastguard Worker #[derive(Debug)]
866*0d6140beSAndroid Build Coastguard Worker struct WriteProtectRanges {
867*0d6140beSAndroid Build Coastguard Worker ranges: NonNull<libflashrom_sys::flashrom_wp_ranges>,
868*0d6140beSAndroid Build Coastguard Worker }
869*0d6140beSAndroid Build Coastguard Worker
870*0d6140beSAndroid Build Coastguard Worker impl WriteProtectRanges {}
871*0d6140beSAndroid Build Coastguard Worker
872*0d6140beSAndroid Build Coastguard Worker impl Drop for WriteProtectRanges {
drop(&mut self)873*0d6140beSAndroid Build Coastguard Worker fn drop(&mut self) {
874*0d6140beSAndroid Build Coastguard Worker unsafe {
875*0d6140beSAndroid Build Coastguard Worker libflashrom_sys::flashrom_wp_ranges_release(self.ranges.as_mut());
876*0d6140beSAndroid Build Coastguard Worker }
877*0d6140beSAndroid Build Coastguard Worker }
878*0d6140beSAndroid Build Coastguard Worker }
879*0d6140beSAndroid Build Coastguard Worker
880*0d6140beSAndroid Build Coastguard Worker /// Structure for an initialised flashrom_layout
881*0d6140beSAndroid Build Coastguard Worker #[derive(Debug)]
882*0d6140beSAndroid Build Coastguard Worker pub struct Layout {
883*0d6140beSAndroid Build Coastguard Worker layout: NonNull<libflashrom_sys::flashrom_layout>,
884*0d6140beSAndroid Build Coastguard Worker }
885*0d6140beSAndroid Build Coastguard Worker
886*0d6140beSAndroid Build Coastguard Worker impl Layout {
887*0d6140beSAndroid Build Coastguard Worker /// Create an empty [`Layout`]
888*0d6140beSAndroid Build Coastguard Worker ///
889*0d6140beSAndroid Build Coastguard Worker /// # Panics
890*0d6140beSAndroid Build Coastguard Worker ///
891*0d6140beSAndroid Build Coastguard Worker /// Panics if flashrom_layout_new returns 0 and a NULL pointer.
new() -> std::result::Result<Layout, ErrorCode>892*0d6140beSAndroid Build Coastguard Worker pub fn new() -> std::result::Result<Layout, ErrorCode> {
893*0d6140beSAndroid Build Coastguard Worker let mut layout: *mut libflashrom_sys::flashrom_layout = null_mut();
894*0d6140beSAndroid Build Coastguard Worker let err = unsafe { libflashrom_sys::flashrom_layout_new(&mut layout) };
895*0d6140beSAndroid Build Coastguard Worker if err != 0 {
896*0d6140beSAndroid Build Coastguard Worker Err(ErrorCode {
897*0d6140beSAndroid Build Coastguard Worker function: "flashrom_layout_new",
898*0d6140beSAndroid Build Coastguard Worker code: err,
899*0d6140beSAndroid Build Coastguard Worker })
900*0d6140beSAndroid Build Coastguard Worker } else {
901*0d6140beSAndroid Build Coastguard Worker Ok(Layout {
902*0d6140beSAndroid Build Coastguard Worker layout: NonNull::new(layout).expect("flashrom_layout_new returned null"),
903*0d6140beSAndroid Build Coastguard Worker })
904*0d6140beSAndroid Build Coastguard Worker }
905*0d6140beSAndroid Build Coastguard Worker }
906*0d6140beSAndroid Build Coastguard Worker
907*0d6140beSAndroid Build Coastguard Worker /// Add a region to the [`Layout`]
908*0d6140beSAndroid Build Coastguard Worker ///
909*0d6140beSAndroid Build Coastguard Worker /// Not the region will not be 'included', include_region must be called to include the region.
910*0d6140beSAndroid Build Coastguard Worker ///
911*0d6140beSAndroid Build Coastguard Worker /// # Errors
912*0d6140beSAndroid Build Coastguard Worker ///
913*0d6140beSAndroid Build Coastguard Worker /// This function will return an error if the region is not a valid CString,
914*0d6140beSAndroid Build Coastguard Worker /// or if libflashrom returns an error.
add_region<T>(&mut self, region: &str, range: T) -> std::result::Result<(), RegionError> where T: std::ops::RangeBounds<usize>,915*0d6140beSAndroid Build Coastguard Worker pub fn add_region<T>(&mut self, region: &str, range: T) -> std::result::Result<(), RegionError>
916*0d6140beSAndroid Build Coastguard Worker where
917*0d6140beSAndroid Build Coastguard Worker T: std::ops::RangeBounds<usize>,
918*0d6140beSAndroid Build Coastguard Worker {
919*0d6140beSAndroid Build Coastguard Worker let range: RangeInternal = range.into();
920*0d6140beSAndroid Build Coastguard Worker let err = {
921*0d6140beSAndroid Build Coastguard Worker let region = CString::new(region)?;
922*0d6140beSAndroid Build Coastguard Worker unsafe {
923*0d6140beSAndroid Build Coastguard Worker libflashrom_sys::flashrom_layout_add_region(
924*0d6140beSAndroid Build Coastguard Worker self.layout.as_mut(),
925*0d6140beSAndroid Build Coastguard Worker range.start,
926*0d6140beSAndroid Build Coastguard Worker range.end(),
927*0d6140beSAndroid Build Coastguard Worker region.as_ptr(),
928*0d6140beSAndroid Build Coastguard Worker )
929*0d6140beSAndroid Build Coastguard Worker }
930*0d6140beSAndroid Build Coastguard Worker };
931*0d6140beSAndroid Build Coastguard Worker
932*0d6140beSAndroid Build Coastguard Worker if err != 0 {
933*0d6140beSAndroid Build Coastguard Worker Err(RegionError::ErrorCode(ErrorCode {
934*0d6140beSAndroid Build Coastguard Worker function: "flashrom_layout_add_region",
935*0d6140beSAndroid Build Coastguard Worker code: err,
936*0d6140beSAndroid Build Coastguard Worker }))
937*0d6140beSAndroid Build Coastguard Worker } else {
938*0d6140beSAndroid Build Coastguard Worker Ok(())
939*0d6140beSAndroid Build Coastguard Worker }
940*0d6140beSAndroid Build Coastguard Worker }
941*0d6140beSAndroid Build Coastguard Worker
942*0d6140beSAndroid Build Coastguard Worker /// Include a region
943*0d6140beSAndroid Build Coastguard Worker ///
944*0d6140beSAndroid Build Coastguard Worker /// # Errors
945*0d6140beSAndroid Build Coastguard Worker ///
946*0d6140beSAndroid Build Coastguard Worker /// This function will return an error if the region is not a valid CString,
947*0d6140beSAndroid Build Coastguard Worker /// or if libflashrom returns an error.
include_region(&mut self, region: &str) -> std::result::Result<(), RegionError>948*0d6140beSAndroid Build Coastguard Worker pub fn include_region(&mut self, region: &str) -> std::result::Result<(), RegionError> {
949*0d6140beSAndroid Build Coastguard Worker let err = {
950*0d6140beSAndroid Build Coastguard Worker let region = CString::new(region)?;
951*0d6140beSAndroid Build Coastguard Worker unsafe {
952*0d6140beSAndroid Build Coastguard Worker libflashrom_sys::flashrom_layout_include_region(
953*0d6140beSAndroid Build Coastguard Worker self.layout.as_mut(),
954*0d6140beSAndroid Build Coastguard Worker region.as_ptr(),
955*0d6140beSAndroid Build Coastguard Worker )
956*0d6140beSAndroid Build Coastguard Worker }
957*0d6140beSAndroid Build Coastguard Worker };
958*0d6140beSAndroid Build Coastguard Worker if err != 0 {
959*0d6140beSAndroid Build Coastguard Worker Err(RegionError::ErrorCode(ErrorCode {
960*0d6140beSAndroid Build Coastguard Worker function: "flashrom_layout_include_region",
961*0d6140beSAndroid Build Coastguard Worker code: err,
962*0d6140beSAndroid Build Coastguard Worker }))
963*0d6140beSAndroid Build Coastguard Worker } else {
964*0d6140beSAndroid Build Coastguard Worker Ok(())
965*0d6140beSAndroid Build Coastguard Worker }
966*0d6140beSAndroid Build Coastguard Worker }
967*0d6140beSAndroid Build Coastguard Worker
968*0d6140beSAndroid Build Coastguard Worker /// Exclude a region
969*0d6140beSAndroid Build Coastguard Worker ///
970*0d6140beSAndroid Build Coastguard Worker /// # Errors
971*0d6140beSAndroid Build Coastguard Worker ///
972*0d6140beSAndroid Build Coastguard Worker /// This function will return an error if the region is not a valid CString,
973*0d6140beSAndroid Build Coastguard Worker /// or if libflashrom returns an error.
exclude_region(&mut self, region: &str) -> std::result::Result<(), RegionError>974*0d6140beSAndroid Build Coastguard Worker pub fn exclude_region(&mut self, region: &str) -> std::result::Result<(), RegionError> {
975*0d6140beSAndroid Build Coastguard Worker let err = {
976*0d6140beSAndroid Build Coastguard Worker let region = CString::new(region)?;
977*0d6140beSAndroid Build Coastguard Worker unsafe {
978*0d6140beSAndroid Build Coastguard Worker libflashrom_sys::flashrom_layout_exclude_region(
979*0d6140beSAndroid Build Coastguard Worker self.layout.as_mut(),
980*0d6140beSAndroid Build Coastguard Worker region.as_ptr(),
981*0d6140beSAndroid Build Coastguard Worker )
982*0d6140beSAndroid Build Coastguard Worker }
983*0d6140beSAndroid Build Coastguard Worker };
984*0d6140beSAndroid Build Coastguard Worker if err != 0 {
985*0d6140beSAndroid Build Coastguard Worker Err(RegionError::ErrorCode(ErrorCode {
986*0d6140beSAndroid Build Coastguard Worker function: "flashrom_layout_exclude_region",
987*0d6140beSAndroid Build Coastguard Worker code: err,
988*0d6140beSAndroid Build Coastguard Worker }))
989*0d6140beSAndroid Build Coastguard Worker } else {
990*0d6140beSAndroid Build Coastguard Worker Ok(())
991*0d6140beSAndroid Build Coastguard Worker }
992*0d6140beSAndroid Build Coastguard Worker }
993*0d6140beSAndroid Build Coastguard Worker
994*0d6140beSAndroid Build Coastguard Worker /// Get the [`Range`] for the given region
995*0d6140beSAndroid Build Coastguard Worker ///
996*0d6140beSAndroid Build Coastguard Worker /// # Errors
997*0d6140beSAndroid Build Coastguard Worker ///
998*0d6140beSAndroid Build Coastguard Worker /// This function will return an error if the region is not a valid CString,
999*0d6140beSAndroid Build Coastguard Worker /// or if libflashrom returns an error.
get_region_range(&mut self, region: &str) -> std::result::Result<Range, RegionError>1000*0d6140beSAndroid Build Coastguard Worker pub fn get_region_range(&mut self, region: &str) -> std::result::Result<Range, RegionError> {
1001*0d6140beSAndroid Build Coastguard Worker let mut start: std::os::raw::c_uint = 0;
1002*0d6140beSAndroid Build Coastguard Worker let mut len: std::os::raw::c_uint = 0;
1003*0d6140beSAndroid Build Coastguard Worker let err = {
1004*0d6140beSAndroid Build Coastguard Worker let region = CString::new(region)?;
1005*0d6140beSAndroid Build Coastguard Worker unsafe {
1006*0d6140beSAndroid Build Coastguard Worker libflashrom_sys::flashrom_layout_get_region_range(
1007*0d6140beSAndroid Build Coastguard Worker self.layout.as_mut(),
1008*0d6140beSAndroid Build Coastguard Worker region.as_ptr(),
1009*0d6140beSAndroid Build Coastguard Worker &mut start,
1010*0d6140beSAndroid Build Coastguard Worker &mut len,
1011*0d6140beSAndroid Build Coastguard Worker )
1012*0d6140beSAndroid Build Coastguard Worker }
1013*0d6140beSAndroid Build Coastguard Worker };
1014*0d6140beSAndroid Build Coastguard Worker if err != 0 {
1015*0d6140beSAndroid Build Coastguard Worker Err(RegionError::ErrorCode(ErrorCode {
1016*0d6140beSAndroid Build Coastguard Worker function: "flashrom_layout_get_region_range",
1017*0d6140beSAndroid Build Coastguard Worker code: err,
1018*0d6140beSAndroid Build Coastguard Worker }))
1019*0d6140beSAndroid Build Coastguard Worker } else {
1020*0d6140beSAndroid Build Coastguard Worker // should be safe to assume sizeof(size_t) >= sizeof(unsigned int)
1021*0d6140beSAndroid Build Coastguard Worker // TODO: fix after https://review.coreboot.org/c/flashrom/+/65944
1022*0d6140beSAndroid Build Coastguard Worker Ok(start.try_into().unwrap()..(start + len).try_into().unwrap())
1023*0d6140beSAndroid Build Coastguard Worker }
1024*0d6140beSAndroid Build Coastguard Worker }
1025*0d6140beSAndroid Build Coastguard Worker }
1026*0d6140beSAndroid Build Coastguard Worker
1027*0d6140beSAndroid Build Coastguard Worker // TODO this will be replaced with an API implementation: https://review.coreboot.org/c/flashrom/+/65999
1028*0d6140beSAndroid Build Coastguard Worker impl std::str::FromStr for Layout {
1029*0d6140beSAndroid Build Coastguard Worker type Err = Box<dyn error::Error>;
1030*0d6140beSAndroid Build Coastguard Worker
1031*0d6140beSAndroid Build Coastguard Worker /// This will attempt to parse the [`Layout`] file format into a [`Layout`]
1032*0d6140beSAndroid Build Coastguard Worker ///
1033*0d6140beSAndroid Build Coastguard Worker /// The format is documented in the flashrom man page.
from_str(s: &str) -> std::result::Result<Self, Self::Err>1034*0d6140beSAndroid Build Coastguard Worker fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
1035*0d6140beSAndroid Build Coastguard Worker let mut ret = Layout::new()?;
1036*0d6140beSAndroid Build Coastguard Worker
1037*0d6140beSAndroid Build Coastguard Worker // format is hex:hex name
1038*0d6140beSAndroid Build Coastguard Worker // flashrom layout.c seems to allow any characters in the name string
1039*0d6140beSAndroid Build Coastguard Worker // I am restricting here to non whitespace
1040*0d6140beSAndroid Build Coastguard Worker let re = Regex::new(r"^([0-9A-Za-z]+):([0-9A-Za-z]+)\s+(\S+)$").unwrap();
1041*0d6140beSAndroid Build Coastguard Worker
1042*0d6140beSAndroid Build Coastguard Worker // we dont use captures_iter else we would ignore incorrect lines
1043*0d6140beSAndroid Build Coastguard Worker for line in s.lines() {
1044*0d6140beSAndroid Build Coastguard Worker let (start, end, name) = match re.captures(line) {
1045*0d6140beSAndroid Build Coastguard Worker Some(caps) => (
1046*0d6140beSAndroid Build Coastguard Worker caps.get(1).unwrap(),
1047*0d6140beSAndroid Build Coastguard Worker caps.get(2).unwrap(),
1048*0d6140beSAndroid Build Coastguard Worker caps.get(3).unwrap(),
1049*0d6140beSAndroid Build Coastguard Worker ),
1050*0d6140beSAndroid Build Coastguard Worker None => Err(ParseLayoutError(format!("failed to parse: {:?}", line)))?,
1051*0d6140beSAndroid Build Coastguard Worker };
1052*0d6140beSAndroid Build Coastguard Worker let start = usize::from_str_radix(start.as_str(), 16)?;
1053*0d6140beSAndroid Build Coastguard Worker let end = usize::from_str_radix(end.as_str(), 16)?;
1054*0d6140beSAndroid Build Coastguard Worker ret.add_region(name.as_str(), start..=end)?;
1055*0d6140beSAndroid Build Coastguard Worker }
1056*0d6140beSAndroid Build Coastguard Worker
1057*0d6140beSAndroid Build Coastguard Worker Ok(ret)
1058*0d6140beSAndroid Build Coastguard Worker }
1059*0d6140beSAndroid Build Coastguard Worker }
1060*0d6140beSAndroid Build Coastguard Worker
1061*0d6140beSAndroid Build Coastguard Worker impl Drop for Layout {
drop(&mut self)1062*0d6140beSAndroid Build Coastguard Worker fn drop(&mut self) {
1063*0d6140beSAndroid Build Coastguard Worker unsafe {
1064*0d6140beSAndroid Build Coastguard Worker libflashrom_sys::flashrom_layout_release(self.layout.as_mut());
1065*0d6140beSAndroid Build Coastguard Worker }
1066*0d6140beSAndroid Build Coastguard Worker }
1067*0d6140beSAndroid Build Coastguard Worker }
1068*0d6140beSAndroid Build Coastguard Worker
1069*0d6140beSAndroid Build Coastguard Worker #[cfg(test)]
1070*0d6140beSAndroid Build Coastguard Worker mod tests {
1071*0d6140beSAndroid Build Coastguard Worker use gag::BufferRedirect;
1072*0d6140beSAndroid Build Coastguard Worker use std::io::Read;
1073*0d6140beSAndroid Build Coastguard Worker
1074*0d6140beSAndroid Build Coastguard Worker use super::flashrom_version_info;
1075*0d6140beSAndroid Build Coastguard Worker use super::set_log_level;
1076*0d6140beSAndroid Build Coastguard Worker use super::Chip;
1077*0d6140beSAndroid Build Coastguard Worker use super::ChipInitError;
1078*0d6140beSAndroid Build Coastguard Worker use super::InitError;
1079*0d6140beSAndroid Build Coastguard Worker use crate::set_log_function;
1080*0d6140beSAndroid Build Coastguard Worker use crate::Layout;
1081*0d6140beSAndroid Build Coastguard Worker use crate::Programmer;
1082*0d6140beSAndroid Build Coastguard Worker use crate::WriteProtectCfg;
1083*0d6140beSAndroid Build Coastguard Worker
1084*0d6140beSAndroid Build Coastguard Worker // flashrom contains global state, which prevents correct initialisation of
1085*0d6140beSAndroid Build Coastguard Worker // a second programmer or probing of a second chip. Run all unit tests in
1086*0d6140beSAndroid Build Coastguard Worker // forked subprocesses to avoid this issue.
1087*0d6140beSAndroid Build Coastguard Worker use rusty_fork::rusty_fork_test;
1088*0d6140beSAndroid Build Coastguard Worker rusty_fork_test! {
1089*0d6140beSAndroid Build Coastguard Worker
1090*0d6140beSAndroid Build Coastguard Worker #[test]
1091*0d6140beSAndroid Build Coastguard Worker fn version() {
1092*0d6140beSAndroid Build Coastguard Worker // There is no version requirement yet, but for example:
1093*0d6140beSAndroid Build Coastguard Worker // assert!(flashrom_version_info().contains("v1.2"))
1094*0d6140beSAndroid Build Coastguard Worker assert!(!flashrom_version_info().unwrap().is_empty())
1095*0d6140beSAndroid Build Coastguard Worker }
1096*0d6140beSAndroid Build Coastguard Worker
1097*0d6140beSAndroid Build Coastguard Worker #[test]
1098*0d6140beSAndroid Build Coastguard Worker fn only_one_programmer() {
1099*0d6140beSAndroid Build Coastguard Worker {
1100*0d6140beSAndroid Build Coastguard Worker let _1 = Programmer::new("dummy", Some("emulate=W25Q128FV")).unwrap();
1101*0d6140beSAndroid Build Coastguard Worker // Only one programmer can be initialised at a time.
1102*0d6140beSAndroid Build Coastguard Worker assert_eq!(Programmer::new("dummy", Some("emulate=W25Q128FV")).unwrap_err(), InitError::DuplicateInit)
1103*0d6140beSAndroid Build Coastguard Worker }
1104*0d6140beSAndroid Build Coastguard Worker // Only one programmer can ever be initialised
1105*0d6140beSAndroid Build Coastguard Worker assert_eq!(Programmer::new("dummy", Some("emulate=W25Q128FV")).unwrap_err(), InitError::DuplicateInit)
1106*0d6140beSAndroid Build Coastguard Worker }
1107*0d6140beSAndroid Build Coastguard Worker
1108*0d6140beSAndroid Build Coastguard Worker #[test]
1109*0d6140beSAndroid Build Coastguard Worker fn programmer_bad_cstring_name() {
1110*0d6140beSAndroid Build Coastguard Worker assert!(matches!(Programmer::new("dummy\0", None).unwrap_err(), InitError::InvalidName(_)))
1111*0d6140beSAndroid Build Coastguard Worker }
1112*0d6140beSAndroid Build Coastguard Worker
1113*0d6140beSAndroid Build Coastguard Worker #[test]
1114*0d6140beSAndroid Build Coastguard Worker fn chip_none() {
1115*0d6140beSAndroid Build Coastguard Worker // Not specifying a chip will select one if there is one.
1116*0d6140beSAndroid Build Coastguard Worker Chip::new(Programmer::new("dummy", Some("emulate=W25Q128FV")).unwrap(), None).unwrap();
1117*0d6140beSAndroid Build Coastguard Worker }
1118*0d6140beSAndroid Build Coastguard Worker
1119*0d6140beSAndroid Build Coastguard Worker #[test]
1120*0d6140beSAndroid Build Coastguard Worker fn chip_some() {
1121*0d6140beSAndroid Build Coastguard Worker // Specifying a valid chip.
1122*0d6140beSAndroid Build Coastguard Worker Chip::new(Programmer::new("dummy", Some("emulate=W25Q128FV")).unwrap(), Some("W25Q128.V")).unwrap();
1123*0d6140beSAndroid Build Coastguard Worker }
1124*0d6140beSAndroid Build Coastguard Worker
1125*0d6140beSAndroid Build Coastguard Worker #[test]
1126*0d6140beSAndroid Build Coastguard Worker fn chip_nochip() {
1127*0d6140beSAndroid Build Coastguard Worker // Choosing a non existent chip fails.
1128*0d6140beSAndroid Build Coastguard Worker assert_eq!(
1129*0d6140beSAndroid Build Coastguard Worker Chip::new(Programmer::new("dummy", None).unwrap(), Some("W25Q128.V")).unwrap_err(),
1130*0d6140beSAndroid Build Coastguard Worker ChipInitError::NoChipError
1131*0d6140beSAndroid Build Coastguard Worker );
1132*0d6140beSAndroid Build Coastguard Worker }
1133*0d6140beSAndroid Build Coastguard Worker
1134*0d6140beSAndroid Build Coastguard Worker #[test]
1135*0d6140beSAndroid Build Coastguard Worker fn logging_stderr() {
1136*0d6140beSAndroid Build Coastguard Worker let mut buf = BufferRedirect::stderr().unwrap();
1137*0d6140beSAndroid Build Coastguard Worker let mut fc = Chip::new(Programmer::new("dummy", Some("emulate=W25Q128FV")).unwrap(), Some("W25Q128.V")).unwrap();
1138*0d6140beSAndroid Build Coastguard Worker
1139*0d6140beSAndroid Build Coastguard Worker set_log_level(Some(libflashrom_sys::FLASHROM_MSG_INFO));
1140*0d6140beSAndroid Build Coastguard Worker fc.image_read(None).unwrap();
1141*0d6140beSAndroid Build Coastguard Worker let mut stderr = String::new();
1142*0d6140beSAndroid Build Coastguard Worker if buf.read_to_string(&mut stderr).unwrap() == 0 {
1143*0d6140beSAndroid Build Coastguard Worker panic!("stderr empty when it should have some messages");
1144*0d6140beSAndroid Build Coastguard Worker }
1145*0d6140beSAndroid Build Coastguard Worker
1146*0d6140beSAndroid Build Coastguard Worker set_log_level(None);
1147*0d6140beSAndroid Build Coastguard Worker fc.image_read(None).unwrap();
1148*0d6140beSAndroid Build Coastguard Worker if buf.read_to_string(&mut stderr).unwrap() != 0 {
1149*0d6140beSAndroid Build Coastguard Worker panic!("stderr not empty when it should be silent");
1150*0d6140beSAndroid Build Coastguard Worker }
1151*0d6140beSAndroid Build Coastguard Worker }
1152*0d6140beSAndroid Build Coastguard Worker
1153*0d6140beSAndroid Build Coastguard Worker #[test]
1154*0d6140beSAndroid Build Coastguard Worker fn logging_custom() {
1155*0d6140beSAndroid Build Coastguard Worker // Check that a custom logging callback works
1156*0d6140beSAndroid Build Coastguard Worker static mut BUF: String = String::new();
1157*0d6140beSAndroid Build Coastguard Worker fn logger(
1158*0d6140beSAndroid Build Coastguard Worker _: libflashrom_sys::flashrom_log_level,
1159*0d6140beSAndroid Build Coastguard Worker format: &str,
1160*0d6140beSAndroid Build Coastguard Worker ) {
1161*0d6140beSAndroid Build Coastguard Worker unsafe {BUF.push_str(format)}
1162*0d6140beSAndroid Build Coastguard Worker }
1163*0d6140beSAndroid Build Coastguard Worker set_log_function(logger);
1164*0d6140beSAndroid Build Coastguard Worker set_log_level(Some(libflashrom_sys::FLASHROM_MSG_SPEW));
1165*0d6140beSAndroid Build Coastguard Worker Chip::new(Programmer::new("dummy", Some("emulate=W25Q128FV")).unwrap(), Some("W25Q128.V")).unwrap();
1166*0d6140beSAndroid Build Coastguard Worker assert_ne!(unsafe{BUF.len()}, 0);
1167*0d6140beSAndroid Build Coastguard Worker }
1168*0d6140beSAndroid Build Coastguard Worker
1169*0d6140beSAndroid Build Coastguard Worker #[test]
1170*0d6140beSAndroid Build Coastguard Worker fn flashchip() {
1171*0d6140beSAndroid Build Coastguard Worker // basic tests of the flashchip methods
1172*0d6140beSAndroid Build Coastguard Worker let mut fc = Chip::new(Programmer::new("dummy", Some("emulate=W25Q128FV")).unwrap(), Some("W25Q128.V")).unwrap();
1173*0d6140beSAndroid Build Coastguard Worker fc.get_size();
1174*0d6140beSAndroid Build Coastguard Worker
1175*0d6140beSAndroid Build Coastguard Worker let mut wp = fc.get_wp().unwrap();
1176*0d6140beSAndroid Build Coastguard Worker wp.set_mode(libflashrom_sys::flashrom_wp_mode::FLASHROM_WP_MODE_DISABLED);
1177*0d6140beSAndroid Build Coastguard Worker fc.set_wp(&wp).unwrap();
1178*0d6140beSAndroid Build Coastguard Worker fc.get_wp_ranges().unwrap();
1179*0d6140beSAndroid Build Coastguard Worker
1180*0d6140beSAndroid Build Coastguard Worker fn test_layout() -> Layout {
1181*0d6140beSAndroid Build Coastguard Worker let mut layout = Layout::new().unwrap();
1182*0d6140beSAndroid Build Coastguard Worker layout.add_region("xyz", 100..200).unwrap();
1183*0d6140beSAndroid Build Coastguard Worker layout.include_region("xyz").unwrap();
1184*0d6140beSAndroid Build Coastguard Worker layout.add_region("abc", 100..200).unwrap();
1185*0d6140beSAndroid Build Coastguard Worker layout
1186*0d6140beSAndroid Build Coastguard Worker }
1187*0d6140beSAndroid Build Coastguard Worker
1188*0d6140beSAndroid Build Coastguard Worker fc.image_read(None).unwrap();
1189*0d6140beSAndroid Build Coastguard Worker fc.image_read(Some(test_layout())).unwrap();
1190*0d6140beSAndroid Build Coastguard Worker
1191*0d6140beSAndroid Build Coastguard Worker let mut buf = vec![0; fc.get_size()];
1192*0d6140beSAndroid Build Coastguard Worker fc.image_write(&mut buf, None).unwrap();
1193*0d6140beSAndroid Build Coastguard Worker fc.image_write(&mut buf, Some(test_layout())).unwrap();
1194*0d6140beSAndroid Build Coastguard Worker
1195*0d6140beSAndroid Build Coastguard Worker fc.image_verify(&buf, None).unwrap();
1196*0d6140beSAndroid Build Coastguard Worker fc.image_verify(&buf, Some(test_layout())).unwrap();
1197*0d6140beSAndroid Build Coastguard Worker
1198*0d6140beSAndroid Build Coastguard Worker fc.erase().unwrap();
1199*0d6140beSAndroid Build Coastguard Worker }
1200*0d6140beSAndroid Build Coastguard Worker
1201*0d6140beSAndroid Build Coastguard Worker #[test]
1202*0d6140beSAndroid Build Coastguard Worker fn write_protect() {
1203*0d6140beSAndroid Build Coastguard Worker let mut wp = WriteProtectCfg::new().unwrap();
1204*0d6140beSAndroid Build Coastguard Worker wp.set_mode(libflashrom_sys::flashrom_wp_mode::FLASHROM_WP_MODE_DISABLED);
1205*0d6140beSAndroid Build Coastguard Worker wp.set_range(100..200);
1206*0d6140beSAndroid Build Coastguard Worker assert_eq!(wp.get_mode(), libflashrom_sys::flashrom_wp_mode::FLASHROM_WP_MODE_DISABLED);
1207*0d6140beSAndroid Build Coastguard Worker assert_eq!(wp.get_range(), 100..200);
1208*0d6140beSAndroid Build Coastguard Worker }
1209*0d6140beSAndroid Build Coastguard Worker }
1210*0d6140beSAndroid Build Coastguard Worker }
1211