aboutsummaryrefslogtreecommitdiff
path: root/embassy-boot/boot/src/lib.rs
diff options
context:
space:
mode:
authorRasmus Melchior Jacobsen <[email protected]>2023-04-04 19:06:14 +0200
committerRasmus Melchior Jacobsen <[email protected]>2023-04-04 19:06:14 +0200
commit54b82d99666c35e63dc402955068557ef0bb1cf0 (patch)
treea5f0202eb0616a432ecb0e5f9570aebd46b51e67 /embassy-boot/boot/src/lib.rs
parent7c6936a2e398e43ea3dc89736dc385402822933f (diff)
parent5923e143e35547b1972f2e48082e93dfbe1dadac (diff)
Merge remote-tracking branch 'upstream/master' into incremental-hash
Diffstat (limited to 'embassy-boot/boot/src/lib.rs')
-rw-r--r--embassy-boot/boot/src/lib.rs159
1 files changed, 24 insertions, 135 deletions
diff --git a/embassy-boot/boot/src/lib.rs b/embassy-boot/boot/src/lib.rs
index da9055476..d4078f1cb 100644
--- a/embassy-boot/boot/src/lib.rs
+++ b/embassy-boot/boot/src/lib.rs
@@ -8,6 +8,7 @@ mod fmt;
8mod boot_loader; 8mod boot_loader;
9mod digest_adapters; 9mod digest_adapters;
10mod firmware_updater; 10mod firmware_updater;
11mod mem_flash;
11mod partition; 12mod partition;
12 13
13pub use boot_loader::{BootError, BootFlash, BootLoader, Flash, FlashConfig, MultiFlashConfig, SingleFlashConfig}; 14pub use boot_loader::{BootError, BootFlash, BootLoader, Flash, FlashConfig, MultiFlashConfig, SingleFlashConfig};
@@ -45,13 +46,10 @@ impl<const N: usize> AsMut<[u8]> for AlignedBuffer<N> {
45 46
46#[cfg(test)] 47#[cfg(test)]
47mod tests { 48mod tests {
48 use core::convert::Infallible;
49
50 use embedded_storage::nor_flash::{ErrorType, NorFlash, ReadNorFlash};
51 use embedded_storage_async::nor_flash::{NorFlash as AsyncNorFlash, ReadNorFlash as AsyncReadNorFlash};
52 use futures::executor::block_on; 49 use futures::executor::block_on;
53 50
54 use super::*; 51 use super::*;
52 use crate::mem_flash::MemFlash;
55 53
56 /* 54 /*
57 #[test] 55 #[test]
@@ -74,8 +72,8 @@ mod tests {
74 const ACTIVE: Partition = Partition::new(4096, 61440); 72 const ACTIVE: Partition = Partition::new(4096, 61440);
75 const DFU: Partition = Partition::new(61440, 122880); 73 const DFU: Partition = Partition::new(61440, 122880);
76 74
77 let mut flash = MemFlash::<131072, 4096, 4>([0xff; 131072]); 75 let mut flash = MemFlash::<131072, 4096, 4>::default();
78 flash.0[0..4].copy_from_slice(&[BOOT_MAGIC; 4]); 76 flash.mem[0..4].copy_from_slice(&[BOOT_MAGIC; 4]);
79 let mut flash = SingleFlashConfig::new(&mut flash); 77 let mut flash = SingleFlashConfig::new(&mut flash);
80 78
81 let mut bootloader: BootLoader = BootLoader::new(ACTIVE, DFU, STATE); 79 let mut bootloader: BootLoader = BootLoader::new(ACTIVE, DFU, STATE);
@@ -94,14 +92,14 @@ mod tests {
94 const STATE: Partition = Partition::new(0, 4096); 92 const STATE: Partition = Partition::new(0, 4096);
95 const ACTIVE: Partition = Partition::new(4096, 61440); 93 const ACTIVE: Partition = Partition::new(4096, 61440);
96 const DFU: Partition = Partition::new(61440, 122880); 94 const DFU: Partition = Partition::new(61440, 122880);
97 let mut flash = MemFlash::<131072, 4096, 4>([0xff; 131072]); 95 let mut flash = MemFlash::<131072, 4096, 4>::random();
98 96
99 let original: [u8; ACTIVE.len()] = [rand::random::<u8>(); ACTIVE.len()]; 97 let original: [u8; ACTIVE.len()] = [rand::random::<u8>(); ACTIVE.len()];
100 let update: [u8; DFU.len()] = [rand::random::<u8>(); DFU.len()]; 98 let update: [u8; DFU.len()] = [rand::random::<u8>(); DFU.len()];
101 let mut aligned = [0; 4]; 99 let mut aligned = [0; 4];
102 100
103 for i in ACTIVE.from..ACTIVE.to { 101 for i in ACTIVE.from..ACTIVE.to {
104 flash.0[i] = original[i - ACTIVE.from]; 102 flash.mem[i] = original[i - ACTIVE.from];
105 } 103 }
106 104
107 let mut bootloader: BootLoader = BootLoader::new(ACTIVE, DFU, STATE); 105 let mut bootloader: BootLoader = BootLoader::new(ACTIVE, DFU, STATE);
@@ -123,12 +121,12 @@ mod tests {
123 ); 121 );
124 122
125 for i in ACTIVE.from..ACTIVE.to { 123 for i in ACTIVE.from..ACTIVE.to {
126 assert_eq!(flash.0[i], update[i - ACTIVE.from], "Index {}", i); 124 assert_eq!(flash.mem[i], update[i - ACTIVE.from], "Index {}", i);
127 } 125 }
128 126
129 // First DFU page is untouched 127 // First DFU page is untouched
130 for i in DFU.from + 4096..DFU.to { 128 for i in DFU.from + 4096..DFU.to {
131 assert_eq!(flash.0[i], original[i - DFU.from - 4096], "Index {}", i); 129 assert_eq!(flash.mem[i], original[i - DFU.from - 4096], "Index {}", i);
132 } 130 }
133 131
134 // Running again should cause a revert 132 // Running again should cause a revert
@@ -140,12 +138,12 @@ mod tests {
140 ); 138 );
141 139
142 for i in ACTIVE.from..ACTIVE.to { 140 for i in ACTIVE.from..ACTIVE.to {
143 assert_eq!(flash.0[i], original[i - ACTIVE.from], "Index {}", i); 141 assert_eq!(flash.mem[i], original[i - ACTIVE.from], "Index {}", i);
144 } 142 }
145 143
146 // Last page is untouched 144 // Last page is untouched
147 for i in DFU.from..DFU.to - 4096 { 145 for i in DFU.from..DFU.to - 4096 {
148 assert_eq!(flash.0[i], update[i - DFU.from], "Index {}", i); 146 assert_eq!(flash.mem[i], update[i - DFU.from], "Index {}", i);
149 } 147 }
150 148
151 // Mark as booted 149 // Mark as booted
@@ -165,16 +163,16 @@ mod tests {
165 const ACTIVE: Partition = Partition::new(4096, 16384); 163 const ACTIVE: Partition = Partition::new(4096, 16384);
166 const DFU: Partition = Partition::new(0, 16384); 164 const DFU: Partition = Partition::new(0, 16384);
167 165
168 let mut active = MemFlash::<16384, 4096, 8>([0xff; 16384]); 166 let mut active = MemFlash::<16384, 4096, 8>::random();
169 let mut dfu = MemFlash::<16384, 2048, 8>([0xff; 16384]); 167 let mut dfu = MemFlash::<16384, 2048, 8>::random();
170 let mut state = MemFlash::<4096, 128, 4>([0xff; 4096]); 168 let mut state = MemFlash::<4096, 128, 4>::random();
171 let mut aligned = [0; 4]; 169 let mut aligned = [0; 4];
172 170
173 let original: [u8; ACTIVE.len()] = [rand::random::<u8>(); ACTIVE.len()]; 171 let original: [u8; ACTIVE.len()] = [rand::random::<u8>(); ACTIVE.len()];
174 let update: [u8; DFU.len()] = [rand::random::<u8>(); DFU.len()]; 172 let update: [u8; DFU.len()] = [rand::random::<u8>(); DFU.len()];
175 173
176 for i in ACTIVE.from..ACTIVE.to { 174 for i in ACTIVE.from..ACTIVE.to {
177 active.0[i] = original[i - ACTIVE.from]; 175 active.mem[i] = original[i - ACTIVE.from];
178 } 176 }
179 177
180 let mut updater = FirmwareUpdater::new(DFU, STATE); 178 let mut updater = FirmwareUpdater::new(DFU, STATE);
@@ -202,12 +200,12 @@ mod tests {
202 ); 200 );
203 201
204 for i in ACTIVE.from..ACTIVE.to { 202 for i in ACTIVE.from..ACTIVE.to {
205 assert_eq!(active.0[i], update[i - ACTIVE.from], "Index {}", i); 203 assert_eq!(active.mem[i], update[i - ACTIVE.from], "Index {}", i);
206 } 204 }
207 205
208 // First DFU page is untouched 206 // First DFU page is untouched
209 for i in DFU.from + 4096..DFU.to { 207 for i in DFU.from + 4096..DFU.to {
210 assert_eq!(dfu.0[i], original[i - DFU.from - 4096], "Index {}", i); 208 assert_eq!(dfu.mem[i], original[i - DFU.from - 4096], "Index {}", i);
211 } 209 }
212 } 210 }
213 211
@@ -219,15 +217,15 @@ mod tests {
219 const DFU: Partition = Partition::new(0, 16384); 217 const DFU: Partition = Partition::new(0, 16384);
220 218
221 let mut aligned = [0; 4]; 219 let mut aligned = [0; 4];
222 let mut active = MemFlash::<16384, 2048, 4>([0xff; 16384]); 220 let mut active = MemFlash::<16384, 2048, 4>::random();
223 let mut dfu = MemFlash::<16384, 4096, 8>([0xff; 16384]); 221 let mut dfu = MemFlash::<16384, 4096, 8>::random();
224 let mut state = MemFlash::<4096, 128, 4>([0xff; 4096]); 222 let mut state = MemFlash::<4096, 128, 4>::random();
225 223
226 let original: [u8; ACTIVE.len()] = [rand::random::<u8>(); ACTIVE.len()]; 224 let original: [u8; ACTIVE.len()] = [rand::random::<u8>(); ACTIVE.len()];
227 let update: [u8; DFU.len()] = [rand::random::<u8>(); DFU.len()]; 225 let update: [u8; DFU.len()] = [rand::random::<u8>(); DFU.len()];
228 226
229 for i in ACTIVE.from..ACTIVE.to { 227 for i in ACTIVE.from..ACTIVE.to {
230 active.0[i] = original[i - ACTIVE.from]; 228 active.mem[i] = original[i - ACTIVE.from];
231 } 229 }
232 230
233 let mut updater = FirmwareUpdater::new(DFU, STATE); 231 let mut updater = FirmwareUpdater::new(DFU, STATE);
@@ -254,12 +252,12 @@ mod tests {
254 ); 252 );
255 253
256 for i in ACTIVE.from..ACTIVE.to { 254 for i in ACTIVE.from..ACTIVE.to {
257 assert_eq!(active.0[i], update[i - ACTIVE.from], "Index {}", i); 255 assert_eq!(active.mem[i], update[i - ACTIVE.from], "Index {}", i);
258 } 256 }
259 257
260 // First DFU page is untouched 258 // First DFU page is untouched
261 for i in DFU.from + 4096..DFU.to { 259 for i in DFU.from + 4096..DFU.to {
262 assert_eq!(dfu.0[i], original[i - DFU.from - 4096], "Index {}", i); 260 assert_eq!(dfu.mem[i], original[i - DFU.from - 4096], "Index {}", i);
263 } 261 }
264 } 262 }
265 263
@@ -289,13 +287,13 @@ mod tests {
289 287
290 const STATE: Partition = Partition::new(0, 4096); 288 const STATE: Partition = Partition::new(0, 4096);
291 const DFU: Partition = Partition::new(4096, 8192); 289 const DFU: Partition = Partition::new(4096, 8192);
292 let mut flash = MemFlash::<8192, 4096, 4>([0xff; 8192]); 290 let mut flash = MemFlash::<8192, 4096, 4>::default();
293 291
294 let firmware_len = firmware.len(); 292 let firmware_len = firmware.len();
295 293
296 let mut write_buf = [0; 4096]; 294 let mut write_buf = [0; 4096];
297 write_buf[0..firmware_len].copy_from_slice(firmware); 295 write_buf[0..firmware_len].copy_from_slice(firmware);
298 NorFlash::write(&mut flash, DFU.from as u32, &write_buf).unwrap(); 296 DFU.write_blocking(&mut flash, 0, &write_buf).unwrap();
299 297
300 // On with the test 298 // On with the test
301 299
@@ -312,113 +310,4 @@ mod tests {
312 )) 310 ))
313 .is_ok()); 311 .is_ok());
314 } 312 }
315
316 pub struct MemFlash<const SIZE: usize, const ERASE_SIZE: usize, const WRITE_SIZE: usize>(pub [u8; SIZE]);
317
318 impl<const SIZE: usize, const ERASE_SIZE: usize, const WRITE_SIZE: usize> NorFlash
319 for MemFlash<SIZE, ERASE_SIZE, WRITE_SIZE>
320 {
321 const WRITE_SIZE: usize = WRITE_SIZE;
322 const ERASE_SIZE: usize = ERASE_SIZE;
323 fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> {
324 let from = from as usize;
325 let to = to as usize;
326 assert!(from % ERASE_SIZE == 0);
327 assert!(to % ERASE_SIZE == 0, "To: {}, erase size: {}", to, ERASE_SIZE);
328 for i in from..to {
329 self.0[i] = 0xFF;
330 }
331 Ok(())
332 }
333
334 fn write(&mut self, offset: u32, data: &[u8]) -> Result<(), Self::Error> {
335 assert!(data.len() % WRITE_SIZE == 0);
336 assert!(offset as usize % WRITE_SIZE == 0);
337 assert!(offset as usize + data.len() <= SIZE);
338
339 self.0[offset as usize..offset as usize + data.len()].copy_from_slice(data);
340
341 Ok(())
342 }
343 }
344
345 impl<const SIZE: usize, const ERASE_SIZE: usize, const WRITE_SIZE: usize> ErrorType
346 for MemFlash<SIZE, ERASE_SIZE, WRITE_SIZE>
347 {
348 type Error = Infallible;
349 }
350
351 impl<const SIZE: usize, const ERASE_SIZE: usize, const WRITE_SIZE: usize> ReadNorFlash
352 for MemFlash<SIZE, ERASE_SIZE, WRITE_SIZE>
353 {
354 const READ_SIZE: usize = 1;
355
356 fn read(&mut self, offset: u32, buf: &mut [u8]) -> Result<(), Self::Error> {
357 let len = buf.len();
358 buf[..].copy_from_slice(&self.0[offset as usize..offset as usize + len]);
359 Ok(())
360 }
361
362 fn capacity(&self) -> usize {
363 SIZE
364 }
365 }
366
367 impl<const SIZE: usize, const ERASE_SIZE: usize, const WRITE_SIZE: usize> super::Flash
368 for MemFlash<SIZE, ERASE_SIZE, WRITE_SIZE>
369 {
370 const BLOCK_SIZE: usize = ERASE_SIZE;
371 const ERASE_VALUE: u8 = 0xFF;
372 }
373
374 impl<const SIZE: usize, const ERASE_SIZE: usize, const WRITE_SIZE: usize> AsyncReadNorFlash
375 for MemFlash<SIZE, ERASE_SIZE, WRITE_SIZE>
376 {
377 const READ_SIZE: usize = 1;
378
379 async fn read(&mut self, offset: u32, buf: &mut [u8]) -> Result<(), Self::Error> {
380 let len = buf.len();
381 buf[..].copy_from_slice(&self.0[offset as usize..offset as usize + len]);
382 Ok(())
383 }
384
385 fn capacity(&self) -> usize {
386 SIZE
387 }
388 }
389
390 impl<const SIZE: usize, const ERASE_SIZE: usize, const WRITE_SIZE: usize> AsyncNorFlash
391 for MemFlash<SIZE, ERASE_SIZE, WRITE_SIZE>
392 {
393 const WRITE_SIZE: usize = WRITE_SIZE;
394 const ERASE_SIZE: usize = ERASE_SIZE;
395
396 async fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> {
397 let from = from as usize;
398 let to = to as usize;
399 assert!(from % ERASE_SIZE == 0);
400 assert!(to % ERASE_SIZE == 0);
401 for i in from..to {
402 self.0[i] = 0xFF;
403 }
404 Ok(())
405 }
406
407 async fn write(&mut self, offset: u32, data: &[u8]) -> Result<(), Self::Error> {
408 info!("Writing {} bytes to 0x{:x}", data.len(), offset);
409 assert!(data.len() % WRITE_SIZE == 0);
410 assert!(offset as usize % WRITE_SIZE == 0);
411 assert!(
412 offset as usize + data.len() <= SIZE,
413 "OFFSET: {}, LEN: {}, FLASH SIZE: {}",
414 offset,
415 data.len(),
416 SIZE
417 );
418
419 self.0[offset as usize..offset as usize + data.len()].copy_from_slice(data);
420
421 Ok(())
422 }
423 }
424} 313}