aboutsummaryrefslogtreecommitdiff
path: root/embassy-boot/boot/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-boot/boot/src/lib.rs')
-rw-r--r--embassy-boot/boot/src/lib.rs248
1 files changed, 141 insertions, 107 deletions
diff --git a/embassy-boot/boot/src/lib.rs b/embassy-boot/boot/src/lib.rs
index 15d3a4f21..d13eafdd0 100644
--- a/embassy-boot/boot/src/lib.rs
+++ b/embassy-boot/boot/src/lib.rs
@@ -51,10 +51,18 @@ impl<const N: usize> AsMut<[u8]> for AlignedBuffer<N> {
51 51
52#[cfg(test)] 52#[cfg(test)]
53mod tests { 53mod tests {
54 use embedded_storage::nor_flash::{NorFlash, ReadNorFlash};
55 #[cfg(feature = "nightly")]
56 use embedded_storage_async::nor_flash::NorFlash as AsyncNorFlash;
54 use futures::executor::block_on; 57 use futures::executor::block_on;
55 58
56 use super::*; 59 use super::*;
60 use crate::boot_loader::BootLoaderConfig;
61 use crate::firmware_updater::FirmwareUpdaterConfig;
57 use crate::mem_flash::MemFlash; 62 use crate::mem_flash::MemFlash;
63 #[cfg(feature = "nightly")]
64 use crate::test_flash::AsyncTestFlash;
65 use crate::test_flash::BlockingTestFlash;
58 66
59 /* 67 /*
60 #[test] 68 #[test]
@@ -73,147 +81,173 @@ mod tests {
73 81
74 #[test] 82 #[test]
75 fn test_boot_state() { 83 fn test_boot_state() {
76 const STATE: Partition = Partition::new(0, 4096); 84 let flash = BlockingTestFlash::new(BootLoaderConfig {
77 const ACTIVE: Partition = Partition::new(4096, 61440); 85 active: MemFlash::<57344, 4096, 4>::default(),
78 const DFU: Partition = Partition::new(61440, 122880); 86 dfu: MemFlash::<61440, 4096, 4>::default(),
87 state: MemFlash::<4096, 4096, 4>::default(),
88 });
79 89
80 let mut flash = MemFlash::<131072, 4096, 4>::default(); 90 flash.state().write(0, &[BOOT_MAGIC; 4]).unwrap();
81 flash.mem[0..4].copy_from_slice(&[BOOT_MAGIC; 4]);
82 let mut flash = SingleFlashConfig::new(&mut flash);
83 91
84 let mut bootloader: BootLoader = BootLoader::new(ACTIVE, DFU, STATE); 92 let mut bootloader = BootLoader::new(BootLoaderConfig {
93 active: flash.active(),
94 dfu: flash.dfu(),
95 state: flash.state(),
96 });
85 97
86 let mut page = [0; 4096]; 98 let mut page = [0; 4096];
87 assert_eq!(State::Boot, bootloader.prepare_boot(&mut flash, &mut page).unwrap()); 99 assert_eq!(State::Boot, bootloader.prepare_boot(&mut page).unwrap());
88 } 100 }
89 101
90 #[test] 102 #[test]
91 #[cfg(all(feature = "nightly", not(feature = "_verify")))] 103 #[cfg(all(feature = "nightly", not(feature = "_verify")))]
92 fn test_swap_state() { 104 fn test_swap_state() {
93 const STATE: Partition = Partition::new(0, 4096); 105 const FIRMWARE_SIZE: usize = 57344;
94 const ACTIVE: Partition = Partition::new(4096, 61440); 106 let flash = AsyncTestFlash::new(BootLoaderConfig {
95 const DFU: Partition = Partition::new(61440, 122880); 107 active: MemFlash::<FIRMWARE_SIZE, 4096, 4>::default(),
96 let mut flash = MemFlash::<131072, 4096, 4>::random(); 108 dfu: MemFlash::<61440, 4096, 4>::default(),
97 109 state: MemFlash::<4096, 4096, 4>::default(),
98 let original = [rand::random::<u8>(); ACTIVE.size() as usize]; 110 });
99 let update = [rand::random::<u8>(); ACTIVE.size() as usize]; 111
112 const ORIGINAL: [u8; FIRMWARE_SIZE] = [0x55; FIRMWARE_SIZE];
113 const UPDATE: [u8; FIRMWARE_SIZE] = [0xAA; FIRMWARE_SIZE];
100 let mut aligned = [0; 4]; 114 let mut aligned = [0; 4];
101 115
102 flash.program(ACTIVE.from, &original).unwrap(); 116 block_on(flash.active().erase(0, ORIGINAL.len() as u32)).unwrap();
117 block_on(flash.active().write(0, &ORIGINAL)).unwrap();
118
119 let mut updater = FirmwareUpdater::new(FirmwareUpdaterConfig {
120 dfu: flash.dfu(),
121 state: flash.state(),
122 });
123 block_on(updater.write_firmware(0, &UPDATE)).unwrap();
124 block_on(updater.mark_updated(&mut aligned)).unwrap();
103 125
104 let mut bootloader: BootLoader = BootLoader::new(ACTIVE, DFU, STATE); 126 let flash = flash.into_blocking();
105 let mut updater = FirmwareUpdater::new(DFU, STATE); 127 let mut bootloader = BootLoader::new(BootLoaderConfig {
106 block_on(updater.write_firmware(0, &update, &mut flash)).unwrap(); 128 active: flash.active(),
107 block_on(updater.mark_updated(&mut flash, &mut aligned)).unwrap(); 129 dfu: flash.dfu(),
130 state: flash.state(),
131 });
108 132
109 let mut page = [0; 1024]; 133 let mut page = [0; 1024];
110 assert_eq!( 134 assert_eq!(State::Swap, bootloader.prepare_boot(&mut page).unwrap());
111 State::Swap,
112 bootloader
113 .prepare_boot(&mut SingleFlashConfig::new(&mut flash), &mut page)
114 .unwrap()
115 );
116 135
117 flash.assert_eq(ACTIVE.from, &update); 136 let mut read_buf = [0; FIRMWARE_SIZE];
137 flash.active().read(0, &mut read_buf).unwrap();
138 assert_eq!(UPDATE, read_buf);
118 // First DFU page is untouched 139 // First DFU page is untouched
119 flash.assert_eq(DFU.from + 4096, &original); 140 flash.dfu().read(4096, &mut read_buf).unwrap();
141 assert_eq!(ORIGINAL, read_buf);
120 142
121 // Running again should cause a revert 143 // Running again should cause a revert
122 assert_eq!( 144 assert_eq!(State::Swap, bootloader.prepare_boot(&mut page).unwrap());
123 State::Swap,
124 bootloader
125 .prepare_boot(&mut SingleFlashConfig::new(&mut flash), &mut page)
126 .unwrap()
127 );
128 145
129 flash.assert_eq(ACTIVE.from, &original); 146 let mut read_buf = [0; FIRMWARE_SIZE];
130 // Last page is untouched 147 flash.active().read(0, &mut read_buf).unwrap();
131 flash.assert_eq(DFU.from, &update); 148 assert_eq!(ORIGINAL, read_buf);
149 // Last DFU page is untouched
150 flash.dfu().read(0, &mut read_buf).unwrap();
151 assert_eq!(UPDATE, read_buf);
132 152
133 // Mark as booted 153 // Mark as booted
134 block_on(updater.mark_booted(&mut flash, &mut aligned)).unwrap(); 154 let flash = flash.into_async();
135 assert_eq!( 155 let mut updater = FirmwareUpdater::new(FirmwareUpdaterConfig {
136 State::Boot, 156 dfu: flash.dfu(),
137 bootloader 157 state: flash.state(),
138 .prepare_boot(&mut SingleFlashConfig::new(&mut flash), &mut page) 158 });
139 .unwrap() 159 block_on(updater.mark_booted(&mut aligned)).unwrap();
140 ); 160
161 let flash = flash.into_blocking();
162 let mut bootloader = BootLoader::new(BootLoaderConfig {
163 active: flash.active(),
164 dfu: flash.dfu(),
165 state: flash.state(),
166 });
167 assert_eq!(State::Boot, bootloader.prepare_boot(&mut page).unwrap());
141 } 168 }
142 169
143 #[test] 170 #[test]
144 #[cfg(all(feature = "nightly", not(feature = "_verify")))] 171 #[cfg(all(feature = "nightly", not(feature = "_verify")))]
145 fn test_separate_flash_active_page_biggest() { 172 fn test_swap_state_active_page_biggest() {
146 const STATE: Partition = Partition::new(2048, 4096); 173 const FIRMWARE_SIZE: usize = 12288;
147 const ACTIVE: Partition = Partition::new(4096, 16384); 174 let flash = AsyncTestFlash::new(BootLoaderConfig {
148 const DFU: Partition = Partition::new(0, 16384); 175 active: MemFlash::<12288, 4096, 8>::random(),
149 176 dfu: MemFlash::<16384, 2048, 8>::random(),
150 let mut active = MemFlash::<16384, 4096, 8>::random(); 177 state: MemFlash::<2048, 128, 4>::random(),
151 let mut dfu = MemFlash::<16384, 2048, 8>::random(); 178 });
152 let mut state = MemFlash::<4096, 128, 4>::random(); 179
180 const ORIGINAL: [u8; FIRMWARE_SIZE] = [0x55; FIRMWARE_SIZE];
181 const UPDATE: [u8; FIRMWARE_SIZE] = [0xAA; FIRMWARE_SIZE];
153 let mut aligned = [0; 4]; 182 let mut aligned = [0; 4];
154 183
155 let original = [rand::random::<u8>(); ACTIVE.size() as usize]; 184 block_on(flash.active().erase(0, ORIGINAL.len() as u32)).unwrap();
156 let update = [rand::random::<u8>(); ACTIVE.size() as usize]; 185 block_on(flash.active().write(0, &ORIGINAL)).unwrap();
157 186
158 active.program(ACTIVE.from, &original).unwrap(); 187 let mut updater = FirmwareUpdater::new(FirmwareUpdaterConfig {
188 dfu: flash.dfu(),
189 state: flash.state(),
190 });
191 block_on(updater.write_firmware(0, &UPDATE)).unwrap();
192 block_on(updater.mark_updated(&mut aligned)).unwrap();
159 193
160 let mut updater = FirmwareUpdater::new(DFU, STATE); 194 let flash = flash.into_blocking();
195 let mut bootloader = BootLoader::new(BootLoaderConfig {
196 active: flash.active(),
197 dfu: flash.dfu(),
198 state: flash.state(),
199 });
161 200
162 block_on(updater.write_firmware(0, &update, &mut dfu)).unwrap();
163 block_on(updater.mark_updated(&mut state, &mut aligned)).unwrap();
164
165 let mut bootloader: BootLoader = BootLoader::new(ACTIVE, DFU, STATE);
166 let mut page = [0; 4096]; 201 let mut page = [0; 4096];
202 assert_eq!(State::Swap, bootloader.prepare_boot(&mut page).unwrap());
167 203
168 assert_eq!( 204 let mut read_buf = [0; FIRMWARE_SIZE];
169 State::Swap, 205 flash.active().read(0, &mut read_buf).unwrap();
170 bootloader 206 assert_eq!(UPDATE, read_buf);
171 .prepare_boot(&mut MultiFlashConfig::new(&mut active, &mut state, &mut dfu), &mut page)
172 .unwrap()
173 );
174
175 active.assert_eq(ACTIVE.from, &update);
176 // First DFU page is untouched 207 // First DFU page is untouched
177 dfu.assert_eq(DFU.from + 4096, &original); 208 flash.dfu().read(4096, &mut read_buf).unwrap();
209 assert_eq!(ORIGINAL, read_buf);
178 } 210 }
179 211
180 #[test] 212 #[test]
181 #[cfg(all(feature = "nightly", not(feature = "_verify")))] 213 #[cfg(all(feature = "nightly", not(feature = "_verify")))]
182 fn test_separate_flash_dfu_page_biggest() { 214 fn test_swap_state_dfu_page_biggest() {
183 const STATE: Partition = Partition::new(2048, 4096); 215 const FIRMWARE_SIZE: usize = 12288;
184 const ACTIVE: Partition = Partition::new(4096, 16384); 216 let flash = AsyncTestFlash::new(BootLoaderConfig {
185 const DFU: Partition = Partition::new(0, 16384); 217 active: MemFlash::<FIRMWARE_SIZE, 2048, 4>::random(),
186 218 dfu: MemFlash::<16384, 4096, 8>::random(),
219 state: MemFlash::<2048, 128, 4>::random(),
220 });
221
222 const ORIGINAL: [u8; FIRMWARE_SIZE] = [0x55; FIRMWARE_SIZE];
223 const UPDATE: [u8; FIRMWARE_SIZE] = [0xAA; FIRMWARE_SIZE];
187 let mut aligned = [0; 4]; 224 let mut aligned = [0; 4];
188 let mut active = MemFlash::<16384, 2048, 4>::random();
189 let mut dfu = MemFlash::<16384, 4096, 8>::random();
190 let mut state = MemFlash::<4096, 128, 4>::random();
191
192 let original = [rand::random::<u8>(); ACTIVE.size() as usize];
193 let update = [rand::random::<u8>(); ACTIVE.size() as usize];
194
195 active.program(ACTIVE.from, &original).unwrap();
196
197 let mut updater = FirmwareUpdater::new(DFU, STATE);
198 225
199 block_on(updater.write_firmware(0, &update, &mut dfu)).unwrap(); 226 block_on(flash.active().erase(0, ORIGINAL.len() as u32)).unwrap();
200 block_on(updater.mark_updated(&mut state, &mut aligned)).unwrap(); 227 block_on(flash.active().write(0, &ORIGINAL)).unwrap();
201 228
202 let mut bootloader: BootLoader = BootLoader::new(ACTIVE, DFU, STATE); 229 let mut updater = FirmwareUpdater::new(FirmwareUpdaterConfig {
230 dfu: flash.dfu(),
231 state: flash.state(),
232 });
233 block_on(updater.write_firmware(0, &UPDATE)).unwrap();
234 block_on(updater.mark_updated(&mut aligned)).unwrap();
235
236 let flash = flash.into_blocking();
237 let mut bootloader = BootLoader::new(BootLoaderConfig {
238 active: flash.active(),
239 dfu: flash.dfu(),
240 state: flash.state(),
241 });
203 let mut page = [0; 4096]; 242 let mut page = [0; 4096];
204 assert_eq!( 243 assert_eq!(State::Swap, bootloader.prepare_boot(&mut page).unwrap());
205 State::Swap,
206 bootloader
207 .prepare_boot(
208 &mut MultiFlashConfig::new(&mut active, &mut state, &mut dfu,),
209 &mut page
210 )
211 .unwrap()
212 );
213 244
214 active.assert_eq(ACTIVE.from, &update); 245 let mut read_buf = [0; FIRMWARE_SIZE];
246 flash.active().read(0, &mut read_buf).unwrap();
247 assert_eq!(UPDATE, read_buf);
215 // First DFU page is untouched 248 // First DFU page is untouched
216 dfu.assert_eq(DFU.from + 4096, &original); 249 flash.dfu().read(4096, &mut read_buf).unwrap();
250 assert_eq!(ORIGINAL, read_buf);
217 } 251 }
218 252
219 #[test] 253 #[test]
@@ -239,25 +273,25 @@ mod tests {
239 let public_key: PublicKey = keypair.public; 273 let public_key: PublicKey = keypair.public;
240 274
241 // Setup flash 275 // Setup flash
242 276 let flash = BlockingTestFlash::new(BootLoaderConfig {
243 const STATE: Partition = Partition::new(0, 4096); 277 active: MemFlash::<0, 0, 0>::default(),
244 const DFU: Partition = Partition::new(4096, 8192); 278 dfu: MemFlash::<4096, 4096, 4>::default(),
245 let mut flash = MemFlash::<8192, 4096, 4>::default(); 279 state: MemFlash::<4096, 4096, 4>::default(),
280 });
246 281
247 let firmware_len = firmware.len(); 282 let firmware_len = firmware.len();
248 283
249 let mut write_buf = [0; 4096]; 284 let mut write_buf = [0; 4096];
250 write_buf[0..firmware_len].copy_from_slice(firmware); 285 write_buf[0..firmware_len].copy_from_slice(firmware);
251 DFU.write_blocking(&mut flash, 0, &write_buf).unwrap(); 286 flash.dfu().write(0, &write_buf).unwrap();
252 287
253 // On with the test 288 // On with the test
254 289 let flash = flash.into_async();
255 let mut updater = FirmwareUpdater::new(DFU, STATE); 290 let mut updater = FirmwareUpdater::new(flash.dfu(), flash.state());
256 291
257 let mut aligned = [0; 4]; 292 let mut aligned = [0; 4];
258 293
259 assert!(block_on(updater.verify_and_mark_updated( 294 assert!(block_on(updater.verify_and_mark_updated(
260 &mut flash,
261 &public_key.to_bytes(), 295 &public_key.to_bytes(),
262 &signature.to_bytes(), 296 &signature.to_bytes(),
263 firmware_len as u32, 297 firmware_len as u32,