aboutsummaryrefslogtreecommitdiff
path: root/embassy-boot/boot/src/lib.rs
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2023-05-30 20:08:01 +0000
committerGitHub <[email protected]>2023-05-30 20:08:01 +0000
commitf5d0d28ac3cfcb74eaa59bbe984b7969a0743724 (patch)
tree9b156e69b39cd79f4b977dbd59f6ae1d5cbfc902 /embassy-boot/boot/src/lib.rs
parent05688934a131b023e147e7c4c24afd1d7b01582a (diff)
parentc22d2b5b5bbc5e3c7d3a039e90b50d39809a10f2 (diff)
Merge pull request #1498 from rmja/remove-bootloader-partitions
Remove bootloader partitions
Diffstat (limited to 'embassy-boot/boot/src/lib.rs')
-rw-r--r--embassy-boot/boot/src/lib.rs265
1 files changed, 154 insertions, 111 deletions
diff --git a/embassy-boot/boot/src/lib.rs b/embassy-boot/boot/src/lib.rs
index 4521fecb0..45a87bd0e 100644
--- a/embassy-boot/boot/src/lib.rs
+++ b/embassy-boot/boot/src/lib.rs
@@ -7,12 +7,18 @@ mod fmt;
7mod boot_loader; 7mod boot_loader;
8mod digest_adapters; 8mod digest_adapters;
9mod firmware_updater; 9mod firmware_updater;
10#[cfg(test)]
10mod mem_flash; 11mod mem_flash;
11mod partition; 12#[cfg(test)]
13mod test_flash;
12 14
13pub use boot_loader::{BootError, BootFlash, BootLoader, FlashConfig, MultiFlashConfig, SingleFlashConfig}; 15// The expected value of the flash after an erase
14pub use firmware_updater::{FirmwareUpdater, FirmwareUpdaterError}; 16// TODO: Use the value provided by NorFlash when available
15pub use partition::Partition; 17pub(crate) const STATE_ERASE_VALUE: u8 = 0xFF;
18pub use boot_loader::{BootError, BootLoader, BootLoaderConfig};
19#[cfg(feature = "nightly")]
20pub use firmware_updater::FirmwareUpdater;
21pub use firmware_updater::{BlockingFirmwareUpdater, FirmwareUpdaterConfig, FirmwareUpdaterError};
16 22
17pub(crate) const BOOT_MAGIC: u8 = 0xD0; 23pub(crate) const BOOT_MAGIC: u8 = 0xD0;
18pub(crate) const SWAP_MAGIC: u8 = 0xF0; 24pub(crate) const SWAP_MAGIC: u8 = 0xF0;
@@ -45,10 +51,18 @@ impl<const N: usize> AsMut<[u8]> for AlignedBuffer<N> {
45 51
46#[cfg(test)] 52#[cfg(test)]
47mod 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;
48 use futures::executor::block_on; 57 use futures::executor::block_on;
49 58
50 use super::*; 59 use super::*;
60 use crate::boot_loader::BootLoaderConfig;
61 use crate::firmware_updater::FirmwareUpdaterConfig;
51 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;
52 66
53 /* 67 /*
54 #[test] 68 #[test]
@@ -67,147 +81,173 @@ mod tests {
67 81
68 #[test] 82 #[test]
69 fn test_boot_state() { 83 fn test_boot_state() {
70 const STATE: Partition = Partition::new(0, 4096); 84 let flash = BlockingTestFlash::new(BootLoaderConfig {
71 const ACTIVE: Partition = Partition::new(4096, 61440); 85 active: MemFlash::<57344, 4096, 4>::default(),
72 const DFU: Partition = Partition::new(61440, 122880); 86 dfu: MemFlash::<61440, 4096, 4>::default(),
87 state: MemFlash::<4096, 4096, 4>::default(),
88 });
73 89
74 let mut flash = MemFlash::<131072, 4096, 4>::default(); 90 flash.state().write(0, &[BOOT_MAGIC; 4]).unwrap();
75 flash.mem[0..4].copy_from_slice(&[BOOT_MAGIC; 4]);
76 let mut flash = SingleFlashConfig::new(&mut flash);
77 91
78 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 });
79 97
80 let mut page = [0; 4096]; 98 let mut page = [0; 4096];
81 assert_eq!(State::Boot, bootloader.prepare_boot(&mut flash, &mut page).unwrap()); 99 assert_eq!(State::Boot, bootloader.prepare_boot(&mut page).unwrap());
82 } 100 }
83 101
84 #[test] 102 #[test]
85 #[cfg(all(feature = "nightly", not(feature = "_verify")))] 103 #[cfg(all(feature = "nightly", not(feature = "_verify")))]
86 fn test_swap_state() { 104 fn test_swap_state() {
87 const STATE: Partition = Partition::new(0, 4096); 105 const FIRMWARE_SIZE: usize = 57344;
88 const ACTIVE: Partition = Partition::new(4096, 61440); 106 let flash = AsyncTestFlash::new(BootLoaderConfig {
89 const DFU: Partition = Partition::new(61440, 122880); 107 active: MemFlash::<FIRMWARE_SIZE, 4096, 4>::default(),
90 let mut flash = MemFlash::<131072, 4096, 4>::random(); 108 dfu: MemFlash::<61440, 4096, 4>::default(),
91 109 state: MemFlash::<4096, 4096, 4>::default(),
92 let original = [rand::random::<u8>(); ACTIVE.size() as usize]; 110 });
93 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];
94 let mut aligned = [0; 4]; 114 let mut aligned = [0; 4];
95 115
96 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();
97 125
98 let mut bootloader: BootLoader = BootLoader::new(ACTIVE, DFU, STATE); 126 let flash = flash.into_blocking();
99 let mut updater = FirmwareUpdater::new(DFU, STATE); 127 let mut bootloader = BootLoader::new(BootLoaderConfig {
100 block_on(updater.write_firmware(0, &update, &mut flash)).unwrap(); 128 active: flash.active(),
101 block_on(updater.mark_updated(&mut flash, &mut aligned)).unwrap(); 129 dfu: flash.dfu(),
130 state: flash.state(),
131 });
102 132
103 let mut page = [0; 1024]; 133 let mut page = [0; 1024];
104 assert_eq!( 134 assert_eq!(State::Swap, bootloader.prepare_boot(&mut page).unwrap());
105 State::Swap,
106 bootloader
107 .prepare_boot(&mut SingleFlashConfig::new(&mut flash), &mut page)
108 .unwrap()
109 );
110 135
111 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);
112 // First DFU page is untouched 139 // First DFU page is untouched
113 flash.assert_eq(DFU.from + 4096, &original); 140 flash.dfu().read(4096, &mut read_buf).unwrap();
141 assert_eq!(ORIGINAL, read_buf);
114 142
115 // Running again should cause a revert 143 // Running again should cause a revert
116 assert_eq!( 144 assert_eq!(State::Swap, bootloader.prepare_boot(&mut page).unwrap());
117 State::Swap,
118 bootloader
119 .prepare_boot(&mut SingleFlashConfig::new(&mut flash), &mut page)
120 .unwrap()
121 );
122 145
123 flash.assert_eq(ACTIVE.from, &original); 146 let mut read_buf = [0; FIRMWARE_SIZE];
124 // Last page is untouched 147 flash.active().read(0, &mut read_buf).unwrap();
125 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);
126 152
127 // Mark as booted 153 // Mark as booted
128 block_on(updater.mark_booted(&mut flash, &mut aligned)).unwrap(); 154 let flash = flash.into_async();
129 assert_eq!( 155 let mut updater = FirmwareUpdater::new(FirmwareUpdaterConfig {
130 State::Boot, 156 dfu: flash.dfu(),
131 bootloader 157 state: flash.state(),
132 .prepare_boot(&mut SingleFlashConfig::new(&mut flash), &mut page) 158 });
133 .unwrap() 159 block_on(updater.mark_booted(&mut aligned)).unwrap();
134 ); 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());
135 } 168 }
136 169
137 #[test] 170 #[test]
138 #[cfg(all(feature = "nightly", not(feature = "_verify")))] 171 #[cfg(all(feature = "nightly", not(feature = "_verify")))]
139 fn test_separate_flash_active_page_biggest() { 172 fn test_swap_state_active_page_biggest() {
140 const STATE: Partition = Partition::new(2048, 4096); 173 const FIRMWARE_SIZE: usize = 12288;
141 const ACTIVE: Partition = Partition::new(4096, 16384); 174 let flash = AsyncTestFlash::new(BootLoaderConfig {
142 const DFU: Partition = Partition::new(0, 16384); 175 active: MemFlash::<12288, 4096, 8>::random(),
143 176 dfu: MemFlash::<16384, 2048, 8>::random(),
144 let mut active = MemFlash::<16384, 4096, 8>::random(); 177 state: MemFlash::<2048, 128, 4>::random(),
145 let mut dfu = MemFlash::<16384, 2048, 8>::random(); 178 });
146 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];
147 let mut aligned = [0; 4]; 182 let mut aligned = [0; 4];
148 183
149 let original = [rand::random::<u8>(); ACTIVE.size() as usize]; 184 block_on(flash.active().erase(0, ORIGINAL.len() as u32)).unwrap();
150 let update = [rand::random::<u8>(); ACTIVE.size() as usize]; 185 block_on(flash.active().write(0, &ORIGINAL)).unwrap();
151
152 active.program(ACTIVE.from, &original).unwrap();
153 186
154 let mut updater = FirmwareUpdater::new(DFU, STATE); 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();
155 193
156 block_on(updater.write_firmware(0, &update, &mut dfu)).unwrap(); 194 let flash = flash.into_blocking();
157 block_on(updater.mark_updated(&mut state, &mut aligned)).unwrap(); 195 let mut bootloader = BootLoader::new(BootLoaderConfig {
196 active: flash.active(),
197 dfu: flash.dfu(),
198 state: flash.state(),
199 });
158 200
159 let mut bootloader: BootLoader = BootLoader::new(ACTIVE, DFU, STATE);
160 let mut page = [0; 4096]; 201 let mut page = [0; 4096];
202 assert_eq!(State::Swap, bootloader.prepare_boot(&mut page).unwrap());
161 203
162 assert_eq!( 204 let mut read_buf = [0; FIRMWARE_SIZE];
163 State::Swap, 205 flash.active().read(0, &mut read_buf).unwrap();
164 bootloader 206 assert_eq!(UPDATE, read_buf);
165 .prepare_boot(&mut MultiFlashConfig::new(&mut active, &mut state, &mut dfu), &mut page)
166 .unwrap()
167 );
168
169 active.assert_eq(ACTIVE.from, &update);
170 // First DFU page is untouched 207 // First DFU page is untouched
171 dfu.assert_eq(DFU.from + 4096, &original); 208 flash.dfu().read(4096, &mut read_buf).unwrap();
209 assert_eq!(ORIGINAL, read_buf);
172 } 210 }
173 211
174 #[test] 212 #[test]
175 #[cfg(all(feature = "nightly", not(feature = "_verify")))] 213 #[cfg(all(feature = "nightly", not(feature = "_verify")))]
176 fn test_separate_flash_dfu_page_biggest() { 214 fn test_swap_state_dfu_page_biggest() {
177 const STATE: Partition = Partition::new(2048, 4096); 215 const FIRMWARE_SIZE: usize = 12288;
178 const ACTIVE: Partition = Partition::new(4096, 16384); 216 let flash = AsyncTestFlash::new(BootLoaderConfig {
179 const DFU: Partition = Partition::new(0, 16384); 217 active: MemFlash::<FIRMWARE_SIZE, 2048, 4>::random(),
180 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];
181 let mut aligned = [0; 4]; 224 let mut aligned = [0; 4];
182 let mut active = MemFlash::<16384, 2048, 4>::random();
183 let mut dfu = MemFlash::<16384, 4096, 8>::random();
184 let mut state = MemFlash::<4096, 128, 4>::random();
185
186 let original = [rand::random::<u8>(); ACTIVE.size() as usize];
187 let update = [rand::random::<u8>(); ACTIVE.size() as usize];
188
189 active.program(ACTIVE.from, &original).unwrap();
190 225
191 let mut updater = FirmwareUpdater::new(DFU, STATE); 226 block_on(flash.active().erase(0, ORIGINAL.len() as u32)).unwrap();
192 227 block_on(flash.active().write(0, &ORIGINAL)).unwrap();
193 block_on(updater.write_firmware(0, &update, &mut dfu)).unwrap(); 228
194 block_on(updater.mark_updated(&mut state, &mut aligned)).unwrap(); 229 let mut updater = FirmwareUpdater::new(FirmwareUpdaterConfig {
195 230 dfu: flash.dfu(),
196 let mut bootloader: BootLoader = BootLoader::new(ACTIVE, DFU, STATE); 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 });
197 let mut page = [0; 4096]; 242 let mut page = [0; 4096];
198 assert_eq!( 243 assert_eq!(State::Swap, bootloader.prepare_boot(&mut page).unwrap());
199 State::Swap,
200 bootloader
201 .prepare_boot(
202 &mut MultiFlashConfig::new(&mut active, &mut state, &mut dfu,),
203 &mut page
204 )
205 .unwrap()
206 );
207 244
208 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);
209 // First DFU page is untouched 248 // First DFU page is untouched
210 dfu.assert_eq(DFU.from + 4096, &original); 249 flash.dfu().read(4096, &mut read_buf).unwrap();
250 assert_eq!(ORIGINAL, read_buf);
211 } 251 }
212 252
213 #[test] 253 #[test]
@@ -233,25 +273,28 @@ mod tests {
233 let public_key: PublicKey = keypair.public; 273 let public_key: PublicKey = keypair.public;
234 274
235 // Setup flash 275 // Setup flash
236 276 let flash = BlockingTestFlash::new(BootLoaderConfig {
237 const STATE: Partition = Partition::new(0, 4096); 277 active: MemFlash::<0, 0, 0>::default(),
238 const DFU: Partition = Partition::new(4096, 8192); 278 dfu: MemFlash::<4096, 4096, 4>::default(),
239 let mut flash = MemFlash::<8192, 4096, 4>::default(); 279 state: MemFlash::<4096, 4096, 4>::default(),
280 });
240 281
241 let firmware_len = firmware.len(); 282 let firmware_len = firmware.len();
242 283
243 let mut write_buf = [0; 4096]; 284 let mut write_buf = [0; 4096];
244 write_buf[0..firmware_len].copy_from_slice(firmware); 285 write_buf[0..firmware_len].copy_from_slice(firmware);
245 DFU.write_blocking(&mut flash, 0, &write_buf).unwrap(); 286 flash.dfu().write(0, &write_buf).unwrap();
246 287
247 // On with the test 288 // On with the test
248 289 let flash = flash.into_async();
249 let mut updater = FirmwareUpdater::new(DFU, STATE); 290 let mut updater = FirmwareUpdater::new(FirmwareUpdaterConfig {
291 dfu: flash.dfu(),
292 state: flash.state(),
293 });
250 294
251 let mut aligned = [0; 4]; 295 let mut aligned = [0; 4];
252 296
253 assert!(block_on(updater.verify_and_mark_updated( 297 assert!(block_on(updater.verify_and_mark_updated(
254 &mut flash,
255 &public_key.to_bytes(), 298 &public_key.to_bytes(),
256 &signature.to_bytes(), 299 &signature.to_bytes(),
257 firmware_len as u32, 300 firmware_len as u32,