xref: /aosp_15_r20/external/flashrom/util/flashrom_tester/flashrom/src/flashromlib.rs (revision 0d6140be3aa665ecc836e8907834fcd3e3b018fc)
1 // Copyright 2022, Google Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 //    * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 //    * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 //    * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 //
30 // Alternatively, this software may be distributed under the terms of the
31 // GNU General Public License ("GPL") version 2 as published by the Free
32 // Software Foundation.
33 //
34 
35 use libflashrom::{Chip, FlashromFlag, FlashromFlags, Programmer};
36 
37 use std::{cell::RefCell, convert::TryFrom, fs, path::Path};
38 
39 use crate::{FlashChip, FlashromError};
40 
41 #[derive(Debug)]
42 pub struct FlashromLib {
43     // RefCell required here to keep Flashrom trait immutable.
44     // Cant make Flashrom methods mut because WriteProtectState
45     // and TestEnv both keep a reference.
46     pub flashrom: RefCell<Chip>,
47     pub fc: FlashChip,
48 }
49 
50 impl FlashromLib {
new(fc: FlashChip, log_level: libflashrom::flashrom_log_level) -> FlashromLib51     pub fn new(fc: FlashChip, log_level: libflashrom::flashrom_log_level) -> FlashromLib {
52         libflashrom::set_log_level(Some(log_level));
53         let (programmer, options) = FlashChip::to_split(fc);
54         let flashrom = Chip::new(Programmer::new(programmer, options).unwrap(), None).unwrap();
55         FlashromLib {
56             flashrom: RefCell::new(flashrom),
57             fc,
58         }
59     }
60 }
61 
62 impl crate::Flashrom for FlashromLib {
get_size(&self) -> Result<i64, FlashromError>63     fn get_size(&self) -> Result<i64, FlashromError> {
64         Ok(self.flashrom.borrow().get_size() as i64)
65     }
66 
name(&self) -> Result<(String, String), FlashromError>67     fn name(&self) -> Result<(String, String), FlashromError> {
68         Ok(("not".to_string(), "implemented".to_string()))
69     }
70 
wp_range(&self, range: (i64, i64), wp_enable: bool) -> Result<bool, FlashromError>71     fn wp_range(&self, range: (i64, i64), wp_enable: bool) -> Result<bool, FlashromError> {
72         let mut cfg = libflashrom::WriteProtectCfg::new()?;
73         let start = usize::try_from(range.0).unwrap();
74         let len = usize::try_from(range.1).unwrap();
75         cfg.set_range::<std::ops::Range<usize>>(start..(start + len));
76         cfg.set_mode(if wp_enable {
77             libflashrom::flashrom_wp_mode::FLASHROM_WP_MODE_HARDWARE
78         } else {
79             libflashrom::flashrom_wp_mode::FLASHROM_WP_MODE_DISABLED
80         });
81         self.flashrom.borrow_mut().set_wp(&cfg)?;
82         Ok(true)
83     }
84 
wp_list(&self) -> Result<String, FlashromError>85     fn wp_list(&self) -> Result<String, FlashromError> {
86         let ranges = self.flashrom.borrow_mut().get_wp_ranges()?;
87         Ok(format!("{:?}", ranges))
88     }
89 
wp_status(&self, en: bool) -> Result<bool, FlashromError>90     fn wp_status(&self, en: bool) -> Result<bool, FlashromError> {
91         let ret = self
92             .flashrom
93             .borrow_mut()
94             .get_wp()
95             .map_err(|e| format!("{:?}", e))?
96             .get_mode();
97         if en {
98             Ok(ret != libflashrom::flashrom_wp_mode::FLASHROM_WP_MODE_DISABLED)
99         } else {
100             Ok(ret == libflashrom::flashrom_wp_mode::FLASHROM_WP_MODE_DISABLED)
101         }
102     }
103 
wp_toggle(&self, en: bool) -> Result<bool, FlashromError>104     fn wp_toggle(&self, en: bool) -> Result<bool, FlashromError> {
105         let range = if en { (0, self.get_size()?) } else { (0, 0) };
106         self.wp_range(range, en)
107     }
108 
read_into_file(&self, path: &Path) -> Result<(), FlashromError>109     fn read_into_file(&self, path: &Path) -> Result<(), FlashromError> {
110         let buf = self.flashrom.borrow_mut().image_read(None)?;
111         fs::write(path, buf).map_err(|error| error.to_string())?;
112         Ok(())
113     }
114 
read_region_into_file(&self, path: &Path, region: &str) -> Result<(), FlashromError>115     fn read_region_into_file(&self, path: &Path, region: &str) -> Result<(), FlashromError> {
116         let mut layout = self.flashrom.borrow_mut().layout_read_fmap_from_rom()?;
117         layout.include_region(region)?;
118         let range = layout.get_region_range(region)?;
119         let buf = self.flashrom.borrow_mut().image_read(None)?;
120         fs::write(path, &buf[range]).map_err(|error| error.to_string())?;
121         Ok(())
122     }
123 
write_from_file(&self, path: &Path) -> Result<(), FlashromError>124     fn write_from_file(&self, path: &Path) -> Result<(), FlashromError> {
125         let mut buf = fs::read(path).map_err(|error| error.to_string())?;
126         self.flashrom.borrow_mut().image_write(&mut buf, None)?;
127         Ok(())
128     }
129 
write_from_file_region( &self, path: &Path, region: &str, layout: &Path, ) -> Result<bool, FlashromError>130     fn write_from_file_region(
131         &self,
132         path: &Path,
133         region: &str,
134         layout: &Path,
135     ) -> Result<bool, FlashromError> {
136         let buf = fs::read(layout).map_err(|error| error.to_string())?;
137         let buf = String::from_utf8(buf).unwrap();
138         let mut layout: libflashrom::Layout = buf
139             .parse()
140             .map_err(|e: Box<dyn std::error::Error>| e.to_string())?;
141         layout.include_region(region)?;
142         let mut buf = fs::read(path).map_err(|error| error.to_string())?;
143         self.flashrom
144             .borrow_mut()
145             .image_write(&mut buf, Some(layout))?;
146         Ok(true)
147     }
148 
verify_from_file(&self, path: &Path) -> Result<(), FlashromError>149     fn verify_from_file(&self, path: &Path) -> Result<(), FlashromError> {
150         let buf = fs::read(path).map_err(|error| error.to_string())?;
151         self.flashrom.borrow_mut().image_verify(&buf, None)?;
152         Ok(())
153     }
154 
verify_region_from_file(&self, path: &Path, region: &str) -> Result<(), FlashromError>155     fn verify_region_from_file(&self, path: &Path, region: &str) -> Result<(), FlashromError> {
156         let mut layout = self.flashrom.borrow_mut().layout_read_fmap_from_rom()?;
157         layout.include_region(region)?;
158         let range = layout.get_region_range(region)?;
159         let region_data = fs::read(path).map_err(|error| error.to_string())?;
160         if region_data.len() != range.len() {
161             return Err(format!(
162                 "verify region range ({}) does not match provided file size ({})",
163                 range.len(),
164                 region_data.len()
165             )
166             .into());
167         }
168         let mut buf = vec![0; self.get_size()? as usize];
169         buf[range].copy_from_slice(&region_data);
170         self.flashrom
171             .borrow_mut()
172             .image_verify(&buf, Some(layout))?;
173         Ok(())
174     }
175 
erase(&self) -> Result<(), FlashromError>176     fn erase(&self) -> Result<(), FlashromError> {
177         self.flashrom.borrow_mut().erase()?;
178         Ok(())
179     }
180 
can_control_hw_wp(&self) -> bool181     fn can_control_hw_wp(&self) -> bool {
182         self.fc.can_control_hw_wp()
183     }
184 
set_flags(&self, flags: &FlashromFlags) -> ()185     fn set_flags(&self, flags: &FlashromFlags) -> () {
186         self.flashrom
187             .borrow_mut()
188             .flag_set(FlashromFlag::FlashromFlagForce, flags.force);
189         self.flashrom
190             .borrow_mut()
191             .flag_set(FlashromFlag::FlashromFlagForceBoardmismatch, flags.force_boardmismatch);
192         self.flashrom
193             .borrow_mut()
194             .flag_set(FlashromFlag::FlashromFlagVerifyAfterWrite, flags.verify_after_write);
195         self.flashrom
196             .borrow_mut()
197             .flag_set(FlashromFlag::FlashromFlagVerifyWholeChip, flags.verify_whole_chip);
198         self.flashrom
199             .borrow_mut()
200             .flag_set(FlashromFlag::FlashromFlagSkipUnreadableRegions, flags.skip_unreadable_regions);
201         self.flashrom
202             .borrow_mut()
203             .flag_set(FlashromFlag::FlashromFlagSkipUnwritableRegions, flags.skip_unwritable_regions);
204     }
205 }
206