1use crate::protocol;
2use crate::traits::boot::{BootCtl, BootMetaStore, Platform, Storage, Transport};
3use crate::traits::{BootMode, BootState};
4
5pub struct Core<T, S, B, C, const BUF: usize>
8where
9 T: Transport,
10 S: Storage,
11 B: BootMetaStore,
12 C: BootCtl,
13{
14 platform: Platform<T, S, B, C>,
15}
16
17impl<T, S, B, C, const BUF: usize> Core<T, S, B, C, BUF>
18where
19 T: Transport,
20 S: Storage,
21 B: BootMetaStore,
22 C: BootCtl,
23{
24 #[inline(always)]
26 pub fn new(platform: Platform<T, S, B, C>) -> Self {
27 Core { platform }
28 }
29
30 #[inline(always)]
33 pub fn run(mut self) -> ! {
34 match self.check_boot_state() {
35 Ok(BootMode::App) => self.platform.ctl.system_reset(BootMode::App),
36 Ok(BootMode::Bootloader) | Err(_) => self.enter_bootloader(),
37 }
38 }
39
40 fn check_boot_state(&mut self) -> Result<BootMode, B::Error> {
41 if self.platform.ctl.is_boot_requested() {
42 return Ok(BootMode::Bootloader);
43 }
44
45 match self.platform.boot_meta.boot_state() {
46 BootState::Idle => {}
47 BootState::Updating => return Ok(BootMode::Bootloader),
48 BootState::Validating => {
49 if !self.platform.boot_meta.has_trials() {
50 return Ok(BootMode::Bootloader);
51 }
52 self.platform.boot_meta.consume_trial()?;
53 }
54 }
55
56 if !self.validate_app() {
57 return Ok(BootMode::Bootloader);
58 }
59
60 Ok(BootMode::App)
61 }
62
63 fn validate_app(&self) -> bool {
66 let stored = self.platform.boot_meta.app_checksum();
67 if stored != 0xFFFF {
68 use tinyboot_protocol::crc::{CRC_INIT, crc16};
69 let sz = self.platform.boot_meta.app_size() as usize;
70 return crc16(CRC_INIT, unsafe {
73 self.platform.storage.as_slice().get_unchecked(..sz)
74 }) == stored;
75 }
76 let data = self.platform.storage.as_slice();
78 data.len() >= 4
79 && unsafe { core::ptr::read_volatile(data.as_ptr() as *const u32) } != 0xFFFF_FFFF
80 }
81
82 #[inline(always)]
83 fn enter_bootloader(&mut self) -> ! {
84 self.platform.storage.unlock();
85
86 let mut d = protocol::Dispatcher::<_, _, _, _, BUF>::new(&mut self.platform);
87
88 loop {
89 let _ = d.dispatch();
90 }
91 }
92}