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::flash::FlashFlags;
13use super::misc::{TlvHeader, TlvTag};
14
15#[derive(Debug, Default, Deserialize, Serialize, Annotate)]
17pub struct OwnerInfoPage {
18 pub bank: u8,
20 pub page: u8,
22 #[serde(default)]
23 #[annotate(format=hex)]
24 pub pad: u16,
25 #[serde(flatten)]
26 pub flags: FlashFlags,
27}
28impl OwnerInfoPage {
29 const SIZE: usize = 12;
30 pub fn new(bank: u8, page: u8, flags: FlashFlags) -> Self {
31 Self {
32 bank,
33 page,
34 flags,
35 ..Default::default()
36 }
37 }
38 pub fn read(src: &mut impl Read, crypt: u64) -> Result<Self> {
39 let bank = src.read_u8()?;
40 let page = src.read_u8()?;
41 let pad = src.read_u16::<LittleEndian>()?;
42 let flags = FlashFlags::from(src.read_u64::<LittleEndian>()? ^ crypt);
43 Ok(Self {
44 bank,
45 page,
46 pad,
47 flags,
48 })
49 }
50 pub fn write(&self, dest: &mut impl Write, crypt: u64) -> Result<()> {
51 dest.write_u8(self.bank)?;
52 dest.write_u8(self.page)?;
53 dest.write_u16::<LittleEndian>(self.pad)?;
54 dest.write_u64::<LittleEndian>(u64::from(self.flags) ^ crypt)?;
55 Ok(())
56 }
57}
58
59#[derive(Debug, Serialize, Deserialize, Annotate)]
61pub struct OwnerFlashInfoConfig {
62 #[serde(
64 skip_serializing_if = "GlobalFlags::not_debug",
65 default = "OwnerFlashInfoConfig::default_header"
66 )]
67 pub header: TlvHeader,
68 pub config: Vec<OwnerInfoPage>,
70}
71
72impl Default for OwnerFlashInfoConfig {
73 fn default() -> Self {
74 Self {
75 header: Self::default_header(),
76 config: Vec::new(),
77 }
78 }
79}
80
81impl OwnerFlashInfoConfig {
82 const BASE_SIZE: usize = 8;
83
84 pub fn default_header() -> TlvHeader {
85 TlvHeader::new(TlvTag::FlashInfoConfig, 0, "0.0")
86 }
87
88 pub fn basic() -> Self {
89 Self {
90 header: TlvHeader::new(TlvTag::FlashInfoConfig, 0, "0.0"),
91 config: vec![
92 OwnerInfoPage::new(0, 6, FlashFlags::info_page()),
93 OwnerInfoPage::new(0, 7, FlashFlags::info_page()),
94 OwnerInfoPage::new(0, 8, FlashFlags::info_page()),
95 OwnerInfoPage::new(0, 9, FlashFlags::info_page()),
96 ],
97 }
98 }
99
100 pub fn read(src: &mut impl Read, header: TlvHeader) -> Result<Self> {
101 let config_len = (header.length - Self::BASE_SIZE) / OwnerInfoPage::SIZE;
102 let mut config = Vec::new();
103 for i in 0..config_len {
104 let crypt = 0x1111_1111_1111_1111u64 * (i as u64);
105 config.push(OwnerInfoPage::read(src, crypt)?)
106 }
107 Ok(Self { header, config })
108 }
109 pub fn write(&self, dest: &mut impl Write) -> Result<()> {
110 let header = TlvHeader::new(
111 TlvTag::FlashInfoConfig,
112 Self::BASE_SIZE + self.config.len() * OwnerInfoPage::SIZE,
113 "0.0",
114 );
115 header.write(dest)?;
116 for (i, config) in self.config.iter().enumerate() {
117 let crypt = 0x1111_1111_1111_1111u64 * (i as u64);
118 config.write(dest, crypt)?;
119 }
120 Ok(())
121 }
122}
123
124#[cfg(test)]
125mod test {
126 use super::*;
127 use crate::util::hexdump::{hexdump_parse, hexdump_string};
128
129 #[rustfmt::skip]
130 const OWNER_FLASH_INFO_CONFIG_BIN: &str =
131r#"00000000: 49 4e 46 4f 2c 00 00 00 00 00 00 00 96 09 00 99 INFO,...........
13200000010: 69 09 00 00 01 02 00 00 77 18 11 88 88 18 11 11 i.......w.......
13300000020: 01 05 00 00 44 24 22 bb 44 24 22 22 ....D$".D$""
134"#;
135
136 const OWNER_FLASH_INFO_CONFIG_JSON: &str = r#"{
137 config: [
138 {
139 bank: 0,
140 page: 0,
141 pad: 0,
142 read: true,
143 program: false,
144 erase: false,
145 scramble: false,
146 ecc: true,
147 high_endurance: false,
148 protect_when_active: false,
149 lock: false
150 },
151 {
152 bank: 1,
153 page: 2,
154 pad: 0,
155 read: true,
156 program: true,
157 erase: false,
158 scramble: false,
159 ecc: false,
160 high_endurance: false,
161 protect_when_active: false,
162 lock: false
163 },
164 {
165 bank: 1,
166 page: 5,
167 pad: 0,
168 read: true,
169 program: true,
170 erase: true,
171 scramble: true,
172 ecc: true,
173 high_endurance: true,
174 protect_when_active: false,
175 lock: false
176 }
177 ]
178}"#;
179
180 #[test]
181 fn test_owner_flash_info_config_write() -> Result<()> {
182 let ofic = OwnerFlashInfoConfig {
183 header: TlvHeader::default(),
184 config: vec![
185 OwnerInfoPage::new(
186 0,
187 0,
188 FlashFlags {
189 read: true,
190 ecc: true,
191 ..Default::default()
192 },
193 ),
194 OwnerInfoPage::new(
195 1,
196 2,
197 FlashFlags {
198 read: true,
199 program: true,
200 ..Default::default()
201 },
202 ),
203 OwnerInfoPage::new(1, 5, FlashFlags::basic()),
204 ],
205 };
206 let mut bin = Vec::new();
207 ofic.write(&mut bin)?;
208 eprintln!("{}", hexdump_string(&bin)?);
209 assert_eq!(hexdump_string(&bin)?, OWNER_FLASH_INFO_CONFIG_BIN);
210 Ok(())
211 }
212
213 #[test]
214 fn test_owner_flash_info_confg_read() -> Result<()> {
215 let buf = hexdump_parse(OWNER_FLASH_INFO_CONFIG_BIN)?;
216 let mut cur = std::io::Cursor::new(&buf);
217 let header = TlvHeader::read(&mut cur)?;
218 let orc = OwnerFlashInfoConfig::read(&mut cur, header)?;
219 let doc = serde_annotate::serialize(&orc)?.to_json5().to_string();
220 assert_eq!(doc, OWNER_FLASH_INFO_CONFIG_JSON);
221 Ok(())
222 }
223}