1use anyhow::Result;
6use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
7use serde::{Deserialize, Serialize};
8use serde_annotate::Annotate;
9use std::io::{Read, Write};
10
11use super::GlobalFlags;
12use super::misc::{TlvHeader, TlvTag};
13use crate::chip::boolean::MultiBitBool4;
14
15#[derive(Debug, Default, Clone, Copy, Serialize, Deserialize, Annotate)]
17pub struct FlashFlags {
18 #[serde(default)]
20 pub read: bool,
21 #[serde(default)]
23 pub program: bool,
24 #[serde(default)]
26 pub erase: bool,
27 #[serde(default)]
29 pub scramble: bool,
30 #[serde(default)]
32 pub ecc: bool,
33 #[serde(default)]
35 pub high_endurance: bool,
36 #[serde(default)]
38 pub protect_when_active: bool,
39 #[serde(default)]
41 pub lock: bool,
42}
43
44impl FlashFlags {
45 const TRUE: u64 = MultiBitBool4::True.0 as u64;
46 const FALSE: u64 = MultiBitBool4::False.0 as u64;
47
48 pub fn basic() -> Self {
50 FlashFlags {
51 read: true,
52 program: true,
53 erase: true,
54 scramble: true,
55 ecc: true,
56 high_endurance: true,
57 ..Default::default()
58 }
59 }
60
61 pub fn rom_ext() -> Self {
63 Self {
64 read: true,
65 program: true,
66 erase: true,
67 protect_when_active: true,
68 ..Default::default()
69 }
70 }
71
72 pub fn firmware() -> Self {
74 Self {
75 read: true,
76 program: true,
77 erase: true,
78 scramble: true,
79 ecc: true,
80 protect_when_active: true,
81 ..Default::default()
82 }
83 }
84
85 pub fn filesystem() -> Self {
87 Self {
88 read: true,
89 program: true,
90 erase: true,
91 high_endurance: true,
92 ..Default::default()
93 }
94 }
95
96 pub fn info_page() -> Self {
98 Self {
99 read: true,
100 program: true,
101 erase: true,
102 scramble: true,
103 ecc: true,
104 ..Default::default()
105 }
106 }
107}
108
109impl From<u64> for FlashFlags {
110 fn from(flags: u64) -> Self {
111 #[rustfmt::skip]
112 let value = Self {
113 read: flags & 0xF == Self::TRUE,
115 program: (flags >> 4) & 0xF == Self::TRUE,
116 erase: (flags >> 8) & 0xF == Self::TRUE,
117 protect_when_active: (flags >> 24) & 0xF == Self::TRUE,
118 lock: (flags >> 28) & 0xF == Self::TRUE,
119
120 scramble: (flags >> 32) & 0xF == Self::TRUE,
122 ecc: (flags >> 36) & 0xF == Self::TRUE,
123 high_endurance: (flags >> 40) & 0xF == Self::TRUE,
124 };
125 value
126 }
127}
128
129impl From<FlashFlags> for u64 {
130 fn from(flags: FlashFlags) -> u64 {
131 #[rustfmt::skip]
132 let value =
133 if flags.read { FlashFlags::TRUE } else { FlashFlags::FALSE } |
135 if flags.program { FlashFlags::TRUE } else { FlashFlags::FALSE } << 4 |
136 if flags.erase { FlashFlags::TRUE } else { FlashFlags::FALSE } << 8 |
137 if flags.protect_when_active { FlashFlags::TRUE } else { FlashFlags::FALSE } << 24 |
138 if flags.lock { FlashFlags::TRUE } else { FlashFlags::FALSE } << 28 |
139
140 if flags.scramble { FlashFlags::TRUE } else { FlashFlags::FALSE } << 32 |
142 if flags.ecc { FlashFlags::TRUE } else { FlashFlags::FALSE } << 36 |
143 if flags.high_endurance { FlashFlags::TRUE } else { FlashFlags::FALSE } << 40 ;
144 value
145 }
146}
147
148#[derive(Debug, Default, Serialize, Deserialize, Annotate)]
150pub struct OwnerFlashRegion {
151 pub start: u16,
153 pub size: u16,
155 #[serde(flatten)]
156 pub flags: FlashFlags,
157}
158
159impl OwnerFlashRegion {
160 const SIZE: usize = 12;
161 pub fn new(start: u16, size: u16, flags: FlashFlags) -> Self {
162 Self { start, size, flags }
163 }
164 pub fn read(src: &mut impl Read, crypt: u64) -> Result<Self> {
165 let start = src.read_u16::<LittleEndian>()?;
166 let size = src.read_u16::<LittleEndian>()?;
167 let flags = FlashFlags::from(src.read_u64::<LittleEndian>()? ^ crypt);
168 Ok(Self { start, size, flags })
169 }
170 pub fn write(&self, dest: &mut impl Write, crypt: u64) -> Result<()> {
171 dest.write_u16::<LittleEndian>(self.start)?;
172 dest.write_u16::<LittleEndian>(self.size)?;
173 dest.write_u64::<LittleEndian>(u64::from(self.flags) ^ crypt)?;
174 Ok(())
175 }
176}
177
178#[derive(Debug, Serialize, Deserialize, Annotate)]
180pub struct OwnerFlashConfig {
181 #[serde(
183 skip_serializing_if = "GlobalFlags::not_debug",
184 default = "OwnerFlashConfig::default_header"
185 )]
186 pub header: TlvHeader,
187 pub config: Vec<OwnerFlashRegion>,
189}
190
191impl Default for OwnerFlashConfig {
192 fn default() -> Self {
193 Self {
194 header: Self::default_header(),
195 config: Vec::new(),
196 }
197 }
198}
199
200impl OwnerFlashConfig {
201 const BASE_SIZE: usize = 8;
202
203 pub fn default_header() -> TlvHeader {
204 TlvHeader::new(TlvTag::FlashConfig, 0, "0.0")
205 }
206 pub fn basic() -> Self {
207 Self {
208 header: TlvHeader::new(TlvTag::FlashConfig, 0, "0.0"),
209 config: vec![
210 OwnerFlashRegion::new(0, 32, FlashFlags::rom_ext()),
211 OwnerFlashRegion::new(32, 192, FlashFlags::firmware()),
212 OwnerFlashRegion::new(224, 32, FlashFlags::filesystem()),
213 OwnerFlashRegion::new(256, 32, FlashFlags::rom_ext()),
214 OwnerFlashRegion::new(256 + 32, 192, FlashFlags::firmware()),
215 OwnerFlashRegion::new(256 + 224, 32, FlashFlags::filesystem()),
216 ],
217 }
218 }
219 pub fn read(src: &mut impl Read, header: TlvHeader) -> Result<Self> {
220 let config_len = (header.length - Self::BASE_SIZE) / OwnerFlashRegion::SIZE;
221 let mut config = Vec::new();
222 for i in 0..config_len {
223 let crypt = 0x1111_1111_1111_1111u64 * (i as u64);
224 config.push(OwnerFlashRegion::read(src, crypt)?)
225 }
226 Ok(Self { header, config })
227 }
228 pub fn write(&self, dest: &mut impl Write) -> Result<()> {
229 let header = TlvHeader::new(
230 TlvTag::FlashConfig,
231 Self::BASE_SIZE + self.config.len() * OwnerFlashRegion::SIZE,
232 "0.0",
233 );
234 header.write(dest)?;
235 for (i, config) in self.config.iter().enumerate() {
236 let crypt = 0x1111_1111_1111_1111u64 * (i as u64);
237 config.write(dest, crypt)?;
238 }
239 Ok(())
240 }
241}
242
243#[cfg(test)]
244mod test {
245 use super::*;
246 use crate::util::hexdump::{hexdump_parse, hexdump_string};
247
248 #[rustfmt::skip]
249 const OWNER_FLASH_CONFIG_BIN: &str =
250r#"00000000: 46 4c 53 48 2c 00 00 00 00 00 00 00 96 09 00 99 FLSH,...........
25100000010: 69 09 00 00 01 00 02 00 77 18 11 88 88 18 11 11 i.......w.......
25200000020: 03 00 05 00 44 24 22 bb 44 24 22 22 ....D$".D$""
253"#;
254
255 const OWNER_FLASH_CONFIG_JSON: &str = r#"{
256 config: [
257 {
258 start: 0,
259 size: 0,
260 read: true,
261 program: false,
262 erase: false,
263 scramble: false,
264 ecc: true,
265 high_endurance: false,
266 protect_when_active: false,
267 lock: false
268 },
269 {
270 start: 1,
271 size: 2,
272 read: true,
273 program: true,
274 erase: false,
275 scramble: false,
276 ecc: false,
277 high_endurance: false,
278 protect_when_active: false,
279 lock: false
280 },
281 {
282 start: 3,
283 size: 5,
284 read: true,
285 program: true,
286 erase: true,
287 scramble: true,
288 ecc: true,
289 high_endurance: true,
290 protect_when_active: false,
291 lock: false
292 }
293 ]
294}"#;
295
296 #[test]
297 fn test_owner_flash_config_write() -> Result<()> {
298 let ofr = OwnerFlashConfig {
299 header: TlvHeader::default(),
300 config: vec![
301 OwnerFlashRegion::new(
302 0,
303 0,
304 FlashFlags {
305 read: true,
306 ecc: true,
307 ..Default::default()
308 },
309 ),
310 OwnerFlashRegion::new(
311 1,
312 2,
313 FlashFlags {
314 read: true,
315 program: true,
316 ..Default::default()
317 },
318 ),
319 OwnerFlashRegion::new(3, 5, FlashFlags::basic()),
320 ],
321 };
322 let mut bin = Vec::new();
323 ofr.write(&mut bin)?;
324 eprintln!("{}", hexdump_string(&bin)?);
325 assert_eq!(hexdump_string(&bin)?, OWNER_FLASH_CONFIG_BIN);
326 Ok(())
327 }
328
329 #[test]
330 fn test_owner_flash_config_read() -> Result<()> {
331 let buf = hexdump_parse(OWNER_FLASH_CONFIG_BIN)?;
332 let mut cur = std::io::Cursor::new(&buf);
333 let header = TlvHeader::read(&mut cur)?;
334 let ofr = OwnerFlashConfig::read(&mut cur, header)?;
335 let doc = serde_annotate::serialize(&ofr)?.to_json5().to_string();
336 assert_eq!(doc, OWNER_FLASH_CONFIG_JSON);
337 Ok(())
338 }
339}