1use crate::chip::Chip;
2use crate::Error;
3use crate::{connection::Connection, elf::RomSegment};
4use indicatif::{HumanBytes, ProgressBar, ProgressStyle};
5use serial::{BaudRate, SerialPort};
6use sha2::{Digest, Sha256};
7use std::{
8 io::{Cursor, Read, Write},
9 time::{Duration, Instant},
10};
11use std::{ops::Range, thread::sleep};
12
13fn get_bar(len: u64) -> ProgressBar {
14 let bar = ProgressBar::new(len);
15 bar.set_style(
16 ProgressStyle::default_bar()
17 .template(" {wide_bar} {bytes}/{total_bytes} {bytes_per_sec} {eta} ")
18 .progress_chars("#>-"),
19 );
20 bar
21}
22
23pub struct Flasher {
24 connection: Connection,
25 boot_info: protocol::BootInfo,
26 chip: Box<dyn Chip>,
27 flash_speed: BaudRate,
28}
29
30impl Flasher {
31 pub fn connect(
32 chip: impl Chip + 'static,
33 serial: impl SerialPort + 'static,
34 initial_speed: BaudRate,
35 flash_speed: BaudRate,
36 ) -> Result<Self, Error> {
37 let mut flasher = Flasher {
38 connection: Connection::new(serial),
39 boot_info: protocol::BootInfo::default(),
40 chip: Box::new(chip),
41 flash_speed,
42 };
43 flasher.connection.set_baud(initial_speed)?;
44 flasher.start_connection()?;
45 flasher.connection.set_timeout(Duration::from_secs(10))?;
46 flasher.boot_info = flasher.boot_rom().get_boot_info()?;
47
48 Ok(flasher)
49 }
50
51 pub fn into_inner(self) -> Connection {
52 self.connection
53 }
54
55 pub fn boot_info(&self) -> &protocol::BootInfo {
56 &self.boot_info
57 }
58
59 pub fn load_segments<'a>(
60 &'a mut self,
61 force: bool,
62 segments: impl Iterator<Item = RomSegment<'a>>,
63 ) -> Result<(), Error> {
64 self.load_eflash_loader()?;
65
66 for segment in segments {
67 let local_hash = Sha256::digest(&segment.data[0..segment.size() as usize]);
68
69 if !force {
71 let sha256 = self
72 .eflash_loader()
73 .sha256_read(segment.addr, segment.size())?;
74 if sha256 == &local_hash[..] {
75 log::info!(
76 "Skip segment addr: {:x} size: {} sha256 matches",
77 segment.addr,
78 segment.size()
79 );
80 continue;
81 }
82 }
83
84 log::info!(
85 "Erase flash addr: {:x} size: {}",
86 segment.addr,
87 segment.size()
88 );
89 self.eflash_loader()
90 .flash_erase(segment.addr, segment.addr + segment.size())?;
91
92 let mut reader = Cursor::new(&segment.data);
93 let mut cur = segment.addr;
94
95 let start = Instant::now();
96 log::info!("Program flash... {:x}", local_hash);
97 let pb = get_bar(segment.size() as u64);
98 loop {
99 let size = self.eflash_loader().flash_program(cur, &mut reader)?;
100 cur += size;
102 pb.inc(size as u64);
103 if size == 0 {
104 break;
105 }
106 }
107 pb.finish_and_clear();
108 let elapsed = start.elapsed();
109 log::info!(
110 "Program done {:?} {}/s",
111 elapsed,
112 HumanBytes((segment.size() as f64 / elapsed.as_millis() as f64 * 1000.0) as u64)
113 );
114
115 let sha256 = self
116 .eflash_loader()
117 .sha256_read(segment.addr, segment.size())?;
118 if sha256 != &local_hash[..] {
119 log::warn!(
120 "sha256 not match: {} != {}",
121 hex::encode(sha256),
122 hex::encode(local_hash)
123 );
124 }
125 }
126 Ok(())
127 }
128
129 pub fn check_segments<'a>(
130 &'a mut self,
131 segments: impl Iterator<Item = RomSegment<'a>>,
132 ) -> Result<(), Error> {
133 self.load_eflash_loader()?;
134
135 for segment in segments {
136 let local_hash = Sha256::digest(&segment.data[0..segment.size() as usize]);
137
138 let sha256 = self
139 .eflash_loader()
140 .sha256_read(segment.addr, segment.size())?;
141 if sha256 != &local_hash[..] {
142 log::warn!(
143 "{:x} sha256 not match: {} != {}",
144 segment.addr,
145 hex::encode(sha256),
146 hex::encode(local_hash)
147 );
148 } else {
149 log::info!("{:x} sha256 match", segment.addr);
150 }
151 }
152 Ok(())
153 }
154
155 pub fn dump_flash(&mut self, range: Range<u32>, mut writer: impl Write) -> Result<(), Error> {
156 self.load_eflash_loader()?;
157
158 const BLOCK_SIZE: usize = 4096;
159 let mut cur = range.start;
160 let pb = get_bar(range.len() as u64);
161 while cur < range.end {
162 let data = self
163 .eflash_loader()
164 .flash_read(cur, (range.end - cur).min(BLOCK_SIZE as u32))?;
165 writer.write_all(&data)?;
166 cur += data.len() as u32;
167 pb.inc(data.len() as u64);
168 }
169 pb.finish_and_clear();
170
171 Ok(())
172 }
173
174 pub fn load_eflash_loader(&mut self) -> Result<(), Error> {
175 let input = self.chip.get_eflash_loader().to_vec();
176 let len = input.len();
177 let mut reader = Cursor::new(input);
178 self.boot_rom().load_boot_header(&mut reader)?;
179 self.boot_rom().load_segment_header(&mut reader)?;
180
181 let start = Instant::now();
182 log::info!("Sending eflash_loader...");
183 let pb = get_bar(len as u64);
184 loop {
185 let size = self.boot_rom().load_segment_data(&mut reader)?;
186 pb.inc(size as u64);
187 if size == 0 {
188 break;
189 }
190 }
191 pb.finish_and_clear();
192 let elapsed = start.elapsed();
193 log::info!(
194 "Finished {:?} {}/s",
195 elapsed,
196 HumanBytes((len as f64 / elapsed.as_millis() as f64 * 1000.0) as u64)
197 );
198
199 self.boot_rom().check_image()?;
200 self.boot_rom().run_image()?;
201 sleep(Duration::from_millis(500));
202 self.connection.set_baud(self.flash_speed)?;
203 self.handshake()?;
204
205 log::info!("Entered eflash_loader");
206
207 Ok(())
208 }
209
210 pub fn reset(&mut self) -> Result<(), Error> {
211 Ok(self.connection.reset()?)
212 }
213
214 fn boot_rom(&mut self) -> BootRom {
215 BootRom(&mut self.connection)
216 }
217
218 fn eflash_loader(&mut self) -> EflashLoader {
219 EflashLoader(&mut self.connection)
220 }
221
222 fn handshake(&mut self) -> Result<(), Error> {
223 self.connection
224 .with_timeout(Duration::from_millis(200), |connection| {
225 let len = connection.calc_duration_length(Duration::from_millis(5));
226 log::trace!("5ms send count {}", len);
227 let data: Vec<u8> = std::iter::repeat(0x55u8).take(len).collect();
228 let start = Instant::now();
229 connection.write_all(&data)?;
230 connection.flush()?;
231 log::trace!("handshake sent elapsed {:?}", start.elapsed());
232 sleep(Duration::from_millis(200));
233
234 for _ in 0..5 {
235 if connection.read_response(0).is_ok() {
236 return Ok(());
237 }
238 }
239
240 Err(Error::Timeout)
241 })
242 }
243
244 fn start_connection(&mut self) -> Result<(), Error> {
245 log::info!("Start connection...");
246 self.connection.reset_to_flash()?;
247 for i in 1..=10 {
248 self.connection.flush()?;
249 if self.handshake().is_ok() {
250 log::info!("Connection Succeed");
251 return Ok(());
252 } else {
253 log::debug!("Retry {}", i);
254 }
255 }
256 Err(Error::ConnectionFailed)
257 }
258}
259
260pub struct BootRom<'a>(&'a mut Connection);
261
262impl<'a> BootRom<'a> {
263 pub fn run_image(&mut self) -> Result<(), Error> {
264 self.0.command(protocol::RunImage {})?;
265 Ok(())
266 }
267
268 pub fn check_image(&mut self) -> Result<(), Error> {
269 self.0.command(protocol::CheckImage {})?;
270 Ok(())
271 }
272
273 pub fn load_boot_header(&mut self, reader: &mut impl Read) -> Result<(), Error> {
274 let mut boot_header = vec![0u8; protocol::LOAD_BOOT_HEADER_LEN];
275 reader.read_exact(&mut boot_header)?;
276 self.0.command(protocol::LoadBootHeader { boot_header })?;
277 Ok(())
278 }
279
280 pub fn load_segment_header(&mut self, reader: &mut impl Read) -> Result<(), Error> {
281 let mut segment_header = vec![0u8; protocol::LOAD_SEGMENT_HEADER_LEN];
282 reader.read_exact(&mut segment_header)?;
283
284 let resp = self.0.command(protocol::LoadSegmentHeaderReq {
285 segment_header: segment_header.clone(),
286 })?;
287
288 if resp.data != segment_header {
289 log::warn!(
290 "Segment header not match req:{:x?} != resp:{:x?}",
291 segment_header,
292 resp.data
293 )
294 }
295
296 Ok(())
297 }
298
299 pub fn load_segment_data(&mut self, reader: &mut impl Read) -> Result<u32, Error> {
300 let mut segment_data = vec![0u8; 4000];
301 let size = reader.read(&mut segment_data)?;
302 if size == 0 {
303 return Ok(0);
304 }
305 segment_data.truncate(size);
306
307 self.0.command(protocol::LoadSegmentData { segment_data })?;
308
309 Ok(size as u32)
310 }
311
312 pub fn get_boot_info(&mut self) -> Result<protocol::BootInfo, Error> {
313 self.0.command(protocol::BootInfoReq {})
314 }
315}
316
317pub struct EflashLoader<'a>(&'a mut Connection);
318
319impl<'a> EflashLoader<'a> {
320 pub fn sha256_read(&mut self, addr: u32, len: u32) -> Result<[u8; 32], Error> {
321 Ok(self.0.command(protocol::Sha256Read { addr, len })?.digest)
322 }
323
324 pub fn flash_read(&mut self, addr: u32, size: u32) -> Result<Vec<u8>, Error> {
325 Ok(self.0.command(protocol::FlashRead { addr, size })?.data)
326 }
327
328 pub fn flash_program(&mut self, addr: u32, reader: &mut impl Read) -> Result<u32, Error> {
329 let mut data = vec![0u8; 4000];
330 let size = reader.read(&mut data)?;
331 if size == 0 {
332 return Ok(0);
333 }
334 data.truncate(size);
335
336 self.0.command(protocol::FlashProgram { addr, data })?;
337
338 Ok(size as u32)
339 }
340
341 pub fn flash_erase(&mut self, start: u32, end: u32) -> Result<(), Error> {
342 self.0.command(protocol::FlashErase { start, end })?;
343
344 Ok(())
345 }
346}
347
348mod protocol {
349 use crate::connection::{Command, Response};
350 use deku::prelude::*;
351
352 pub const LOAD_BOOT_HEADER_LEN: usize = 176;
353 pub const LOAD_SEGMENT_HEADER_LEN: usize = 16;
354
355 #[derive(Debug, DekuWrite, Default)]
356 pub struct CheckImage {}
357 impl_command!(0x19, CheckImage);
358
359 #[derive(Debug, DekuWrite, Default)]
360 pub struct RunImage {}
361 impl_command!(0x1a, RunImage);
362
363 #[derive(Debug, DekuWrite, Default)]
364 pub struct BootInfoReq {}
365 #[derive(Debug, DekuRead, Default)]
366 pub struct BootInfo {
367 pub len: u16,
368 pub bootrom_version: u32,
369 pub otp_info: [u8; 16],
370 }
371 impl_command!(0x10, BootInfoReq, BootInfo);
372
373 #[derive(Debug, DekuWrite, Default)]
374 pub struct LoadBootHeader {
375 pub boot_header: Vec<u8>,
377 }
378 impl_command!(0x11, LoadBootHeader);
379
380 #[derive(Debug, DekuWrite, Default)]
381 pub struct LoadSegmentHeaderReq {
382 pub segment_header: Vec<u8>,
384 }
385 #[derive(Debug, DekuRead)]
386 pub struct LoadSegmentHeader {
387 pub len: u16,
388 #[deku(count = "len")]
389 pub data: Vec<u8>,
390 }
391 impl_command!(0x17, LoadSegmentHeaderReq, LoadSegmentHeader);
392
393 #[derive(Debug, DekuWrite, Default)]
394 pub struct LoadSegmentData {
395 pub segment_data: Vec<u8>,
396 }
397 impl_command!(0x18, LoadSegmentData);
398
399 #[derive(Debug, DekuWrite, Default)]
400 pub struct FlashErase {
401 pub start: u32,
402 pub end: u32,
403 }
404 impl_command!(0x30, FlashErase);
405
406 #[derive(Debug, DekuWrite, Default)]
407 pub struct FlashProgram {
408 pub addr: u32,
409 pub data: Vec<u8>,
410 }
411 impl_command!(0x31, FlashProgram);
412
413 #[derive(Debug, DekuWrite, Default)]
414 pub struct FlashRead {
415 pub addr: u32,
416 pub size: u32,
417 }
418 #[derive(Debug, DekuRead)]
419 pub struct FlashReadResp {
420 pub len: u16,
421 #[deku(count = "len")]
422 pub data: Vec<u8>,
423 }
424 impl_command!(0x32, FlashRead, FlashReadResp);
425
426 #[derive(Debug, DekuWrite, Default)]
427 pub struct Sha256Read {
428 pub addr: u32,
429 pub len: u32,
430 }
431
432 #[derive(Debug, DekuRead)]
433 #[deku(magic = b"\x20\x00")]
434 pub struct Sha256ReadResp {
435 pub digest: [u8; 32],
436 }
437 impl_command!(0x3d, Sha256Read, Sha256ReadResp);
438}