aboutsummaryrefslogtreecommitdiff
path: root/embassy-boot/boot/src/lib.rs
diff options
context:
space:
mode:
authorRasmus Melchior Jacobsen <[email protected]>2023-04-04 23:16:01 +0200
committerRasmus Melchior Jacobsen <[email protected]>2023-04-04 23:16:01 +0200
commit3deb65bc87b53d686694f0abcbbf96ff976d1f93 (patch)
tree44f9c33e5d4a2377ad6305bca2d619ef80ce16dd /embassy-boot/boot/src/lib.rs
parentbfebf7a43648e06b313234a2ddc7496eb526bc69 (diff)
parent5923e143e35547b1972f2e48082e93dfbe1dadac (diff)
Merge branch 'master' into flash-regions
Diffstat (limited to 'embassy-boot/boot/src/lib.rs')
-rw-r--r--embassy-boot/boot/src/lib.rs166
1 files changed, 27 insertions, 139 deletions
diff --git a/embassy-boot/boot/src/lib.rs b/embassy-boot/boot/src/lib.rs
index a2259411f..d53c613a3 100644
--- a/embassy-boot/boot/src/lib.rs
+++ b/embassy-boot/boot/src/lib.rs
@@ -7,12 +7,11 @@ mod fmt;
7 7
8mod boot_loader; 8mod boot_loader;
9mod firmware_updater; 9mod firmware_updater;
10mod firmware_writer; 10mod mem_flash;
11mod partition; 11mod partition;
12 12
13pub use boot_loader::{BootError, BootFlash, BootLoader, Flash, FlashConfig, MultiFlashConfig, SingleFlashConfig}; 13pub use boot_loader::{BootError, BootFlash, BootLoader, Flash, FlashConfig, MultiFlashConfig, SingleFlashConfig};
14pub use firmware_updater::{FirmwareUpdater, FirmwareUpdaterError}; 14pub use firmware_updater::{FirmwareUpdater, FirmwareUpdaterError};
15pub use firmware_writer::FirmwareWriter;
16pub use partition::Partition; 15pub use partition::Partition;
17 16
18pub(crate) const BOOT_MAGIC: u8 = 0xD0; 17pub(crate) const BOOT_MAGIC: u8 = 0xD0;
@@ -46,13 +45,10 @@ impl<const N: usize> AsMut<[u8]> for AlignedBuffer<N> {
46 45
47#[cfg(test)] 46#[cfg(test)]
48mod tests { 47mod tests {
49 use core::convert::Infallible;
50
51 use embedded_storage::nor_flash::{ErrorType, NorFlash, ReadNorFlash};
52 use embedded_storage_async::nor_flash::{NorFlash as AsyncNorFlash, ReadNorFlash as AsyncReadNorFlash};
53 use futures::executor::block_on; 48 use futures::executor::block_on;
54 49
55 use super::*; 50 use super::*;
51 use crate::mem_flash::MemFlash;
56 52
57 /* 53 /*
58 #[test] 54 #[test]
@@ -75,8 +71,8 @@ mod tests {
75 const ACTIVE: Partition = Partition::new(4096, 61440); 71 const ACTIVE: Partition = Partition::new(4096, 61440);
76 const DFU: Partition = Partition::new(61440, 122880); 72 const DFU: Partition = Partition::new(61440, 122880);
77 73
78 let mut flash = MemFlash::<131072, 4096, 4>([0xff; 131072]); 74 let mut flash = MemFlash::<131072, 4096, 4>::default();
79 flash.0[0..4].copy_from_slice(&[BOOT_MAGIC; 4]); 75 flash.mem[0..4].copy_from_slice(&[BOOT_MAGIC; 4]);
80 let mut flash = SingleFlashConfig::new(&mut flash); 76 let mut flash = SingleFlashConfig::new(&mut flash);
81 77
82 let mut bootloader: BootLoader = BootLoader::new(ACTIVE, DFU, STATE); 78 let mut bootloader: BootLoader = BootLoader::new(ACTIVE, DFU, STATE);
@@ -95,21 +91,21 @@ mod tests {
95 const STATE: Partition = Partition::new(0, 4096); 91 const STATE: Partition = Partition::new(0, 4096);
96 const ACTIVE: Partition = Partition::new(4096, 61440); 92 const ACTIVE: Partition = Partition::new(4096, 61440);
97 const DFU: Partition = Partition::new(61440, 122880); 93 const DFU: Partition = Partition::new(61440, 122880);
98 let mut flash = MemFlash::<131072, 4096, 4>([0xff; 131072]); 94 let mut flash = MemFlash::<131072, 4096, 4>::random();
99 95
100 let original: [u8; ACTIVE.len()] = [rand::random::<u8>(); ACTIVE.len()]; 96 let original: [u8; ACTIVE.len()] = [rand::random::<u8>(); ACTIVE.len()];
101 let update: [u8; DFU.len()] = [rand::random::<u8>(); DFU.len()]; 97 let update: [u8; DFU.len()] = [rand::random::<u8>(); DFU.len()];
102 let mut aligned = [0; 4]; 98 let mut aligned = [0; 4];
103 99
104 for i in ACTIVE.from..ACTIVE.to { 100 for i in ACTIVE.from..ACTIVE.to {
105 flash.0[i] = original[i - ACTIVE.from]; 101 flash.mem[i] = original[i - ACTIVE.from];
106 } 102 }
107 103
108 let mut bootloader: BootLoader = BootLoader::new(ACTIVE, DFU, STATE); 104 let mut bootloader: BootLoader = BootLoader::new(ACTIVE, DFU, STATE);
109 let mut updater = FirmwareUpdater::new(DFU, STATE); 105 let mut updater = FirmwareUpdater::new(DFU, STATE);
110 let mut offset = 0; 106 let mut offset = 0;
111 for chunk in update.chunks(4096) { 107 for chunk in update.chunks(4096) {
112 block_on(updater.write_firmware(offset, chunk, &mut flash, 4096)).unwrap(); 108 block_on(updater.write_firmware(offset, chunk, &mut flash)).unwrap();
113 offset += chunk.len(); 109 offset += chunk.len();
114 } 110 }
115 block_on(updater.mark_updated(&mut flash, &mut aligned)).unwrap(); 111 block_on(updater.mark_updated(&mut flash, &mut aligned)).unwrap();
@@ -124,12 +120,12 @@ mod tests {
124 ); 120 );
125 121
126 for i in ACTIVE.from..ACTIVE.to { 122 for i in ACTIVE.from..ACTIVE.to {
127 assert_eq!(flash.0[i], update[i - ACTIVE.from], "Index {}", i); 123 assert_eq!(flash.mem[i], update[i - ACTIVE.from], "Index {}", i);
128 } 124 }
129 125
130 // First DFU page is untouched 126 // First DFU page is untouched
131 for i in DFU.from + 4096..DFU.to { 127 for i in DFU.from + 4096..DFU.to {
132 assert_eq!(flash.0[i], original[i - DFU.from - 4096], "Index {}", i); 128 assert_eq!(flash.mem[i], original[i - DFU.from - 4096], "Index {}", i);
133 } 129 }
134 130
135 // Running again should cause a revert 131 // Running again should cause a revert
@@ -141,12 +137,12 @@ mod tests {
141 ); 137 );
142 138
143 for i in ACTIVE.from..ACTIVE.to { 139 for i in ACTIVE.from..ACTIVE.to {
144 assert_eq!(flash.0[i], original[i - ACTIVE.from], "Index {}", i); 140 assert_eq!(flash.mem[i], original[i - ACTIVE.from], "Index {}", i);
145 } 141 }
146 142
147 // Last page is untouched 143 // Last page is untouched
148 for i in DFU.from..DFU.to - 4096 { 144 for i in DFU.from..DFU.to - 4096 {
149 assert_eq!(flash.0[i], update[i - DFU.from], "Index {}", i); 145 assert_eq!(flash.mem[i], update[i - DFU.from], "Index {}", i);
150 } 146 }
151 147
152 // Mark as booted 148 // Mark as booted
@@ -166,23 +162,23 @@ mod tests {
166 const ACTIVE: Partition = Partition::new(4096, 16384); 162 const ACTIVE: Partition = Partition::new(4096, 16384);
167 const DFU: Partition = Partition::new(0, 16384); 163 const DFU: Partition = Partition::new(0, 16384);
168 164
169 let mut active = MemFlash::<16384, 4096, 8>([0xff; 16384]); 165 let mut active = MemFlash::<16384, 4096, 8>::random();
170 let mut dfu = MemFlash::<16384, 2048, 8>([0xff; 16384]); 166 let mut dfu = MemFlash::<16384, 2048, 8>::random();
171 let mut state = MemFlash::<4096, 128, 4>([0xff; 4096]); 167 let mut state = MemFlash::<4096, 128, 4>::random();
172 let mut aligned = [0; 4]; 168 let mut aligned = [0; 4];
173 169
174 let original: [u8; ACTIVE.len()] = [rand::random::<u8>(); ACTIVE.len()]; 170 let original: [u8; ACTIVE.len()] = [rand::random::<u8>(); ACTIVE.len()];
175 let update: [u8; DFU.len()] = [rand::random::<u8>(); DFU.len()]; 171 let update: [u8; DFU.len()] = [rand::random::<u8>(); DFU.len()];
176 172
177 for i in ACTIVE.from..ACTIVE.to { 173 for i in ACTIVE.from..ACTIVE.to {
178 active.0[i] = original[i - ACTIVE.from]; 174 active.mem[i] = original[i - ACTIVE.from];
179 } 175 }
180 176
181 let mut updater = FirmwareUpdater::new(DFU, STATE); 177 let mut updater = FirmwareUpdater::new(DFU, STATE);
182 178
183 let mut offset = 0; 179 let mut offset = 0;
184 for chunk in update.chunks(2048) { 180 for chunk in update.chunks(2048) {
185 block_on(updater.write_firmware(offset, chunk, &mut dfu, chunk.len())).unwrap(); 181 block_on(updater.write_firmware(offset, chunk, &mut dfu)).unwrap();
186 offset += chunk.len(); 182 offset += chunk.len();
187 } 183 }
188 block_on(updater.mark_updated(&mut state, &mut aligned)).unwrap(); 184 block_on(updater.mark_updated(&mut state, &mut aligned)).unwrap();
@@ -203,12 +199,12 @@ mod tests {
203 ); 199 );
204 200
205 for i in ACTIVE.from..ACTIVE.to { 201 for i in ACTIVE.from..ACTIVE.to {
206 assert_eq!(active.0[i], update[i - ACTIVE.from], "Index {}", i); 202 assert_eq!(active.mem[i], update[i - ACTIVE.from], "Index {}", i);
207 } 203 }
208 204
209 // First DFU page is untouched 205 // First DFU page is untouched
210 for i in DFU.from + 4096..DFU.to { 206 for i in DFU.from + 4096..DFU.to {
211 assert_eq!(dfu.0[i], original[i - DFU.from - 4096], "Index {}", i); 207 assert_eq!(dfu.mem[i], original[i - DFU.from - 4096], "Index {}", i);
212 } 208 }
213 } 209 }
214 210
@@ -220,22 +216,22 @@ mod tests {
220 const DFU: Partition = Partition::new(0, 16384); 216 const DFU: Partition = Partition::new(0, 16384);
221 217
222 let mut aligned = [0; 4]; 218 let mut aligned = [0; 4];
223 let mut active = MemFlash::<16384, 2048, 4>([0xff; 16384]); 219 let mut active = MemFlash::<16384, 2048, 4>::random();
224 let mut dfu = MemFlash::<16384, 4096, 8>([0xff; 16384]); 220 let mut dfu = MemFlash::<16384, 4096, 8>::random();
225 let mut state = MemFlash::<4096, 128, 4>([0xff; 4096]); 221 let mut state = MemFlash::<4096, 128, 4>::random();
226 222
227 let original: [u8; ACTIVE.len()] = [rand::random::<u8>(); ACTIVE.len()]; 223 let original: [u8; ACTIVE.len()] = [rand::random::<u8>(); ACTIVE.len()];
228 let update: [u8; DFU.len()] = [rand::random::<u8>(); DFU.len()]; 224 let update: [u8; DFU.len()] = [rand::random::<u8>(); DFU.len()];
229 225
230 for i in ACTIVE.from..ACTIVE.to { 226 for i in ACTIVE.from..ACTIVE.to {
231 active.0[i] = original[i - ACTIVE.from]; 227 active.mem[i] = original[i - ACTIVE.from];
232 } 228 }
233 229
234 let mut updater = FirmwareUpdater::new(DFU, STATE); 230 let mut updater = FirmwareUpdater::new(DFU, STATE);
235 231
236 let mut offset = 0; 232 let mut offset = 0;
237 for chunk in update.chunks(4096) { 233 for chunk in update.chunks(4096) {
238 block_on(updater.write_firmware(offset, chunk, &mut dfu, chunk.len())).unwrap(); 234 block_on(updater.write_firmware(offset, chunk, &mut dfu)).unwrap();
239 offset += chunk.len(); 235 offset += chunk.len();
240 } 236 }
241 block_on(updater.mark_updated(&mut state, &mut aligned)).unwrap(); 237 block_on(updater.mark_updated(&mut state, &mut aligned)).unwrap();
@@ -255,12 +251,12 @@ mod tests {
255 ); 251 );
256 252
257 for i in ACTIVE.from..ACTIVE.to { 253 for i in ACTIVE.from..ACTIVE.to {
258 assert_eq!(active.0[i], update[i - ACTIVE.from], "Index {}", i); 254 assert_eq!(active.mem[i], update[i - ACTIVE.from], "Index {}", i);
259 } 255 }
260 256
261 // First DFU page is untouched 257 // First DFU page is untouched
262 for i in DFU.from + 4096..DFU.to { 258 for i in DFU.from + 4096..DFU.to {
263 assert_eq!(dfu.0[i], original[i - DFU.from - 4096], "Index {}", i); 259 assert_eq!(dfu.mem[i], original[i - DFU.from - 4096], "Index {}", i);
264 } 260 }
265 } 261 }
266 262
@@ -290,13 +286,13 @@ mod tests {
290 286
291 const STATE: Partition = Partition::new(0, 4096); 287 const STATE: Partition = Partition::new(0, 4096);
292 const DFU: Partition = Partition::new(4096, 8192); 288 const DFU: Partition = Partition::new(4096, 8192);
293 let mut flash = MemFlash::<8192, 4096, 4>([0xff; 8192]); 289 let mut flash = MemFlash::<8192, 4096, 4>::default();
294 290
295 let firmware_len = firmware.len(); 291 let firmware_len = firmware.len();
296 292
297 let mut write_buf = [0; 4096]; 293 let mut write_buf = [0; 4096];
298 write_buf[0..firmware_len].copy_from_slice(firmware); 294 write_buf[0..firmware_len].copy_from_slice(firmware);
299 NorFlash::write(&mut flash, DFU.from as u32, &write_buf).unwrap(); 295 DFU.write_blocking(&mut flash, 0, &write_buf).unwrap();
300 296
301 // On with the test 297 // On with the test
302 298
@@ -313,112 +309,4 @@ mod tests {
313 )) 309 ))
314 .is_ok()); 310 .is_ok());
315 } 311 }
316 struct MemFlash<const SIZE: usize, const ERASE_SIZE: usize, const WRITE_SIZE: usize>([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} 312}