1 // Copyright (c) 2019-2021 Linaro LTD
2 // Copyright (c) 2019-2020 JUUL Labs
3 // Copyright (c) 2019-2023 Arm Limited
4 //
5 // SPDX-License-Identifier: Apache-2.0
6 
7 use byteorder::{
8     LittleEndian, WriteBytesExt,
9 };
10 use log::{
11     Level::Info,
12     error,
13     info,
14     log_enabled,
15     warn,
16 };
17 use rand::{
18     Rng, RngCore, SeedableRng,
19     rngs::SmallRng,
20 };
21 use std::{
22     collections::{BTreeMap, HashSet},
23     io::{Cursor, Write},
24     mem,
25     slice,
26 };
27 use aes::{
28     Aes128,
29     Aes128Ctr,
30     Aes256,
31     Aes256Ctr,
32     NewBlockCipher,
33 };
34 use cipher::{
35     FromBlockCipher,
36     generic_array::GenericArray,
37     StreamCipher,
38     };
39 
40 use simflash::{Flash, SimFlash, SimMultiFlash};
41 use mcuboot_sys::{c, AreaDesc, FlashId, RamBlock};
42 use crate::{
43     ALL_DEVICES,
44     DeviceName,
45 };
46 use crate::caps::Caps;
47 use crate::depends::{
48     BoringDep,
49     Depender,
50     DepTest,
51     DepType,
52     NO_DEPS,
53     PairDep,
54     UpgradeInfo,
55 };
56 use crate::tlv::{ManifestGen, TlvGen, TlvFlags};
57 use crate::utils::align_up;
58 use typenum::{U32, U16};
59 
60 /// For testing, use a non-zero offset for the ram-load, to make sure the offset is getting used
61 /// properly, but the value is not really that important.
62 const RAM_LOAD_ADDR: u32 = 1024;
63 
64 /// A builder for Images.  This describes a single run of the simulator,
65 /// capturing the configuration of a particular set of devices, including
66 /// the flash simulator(s) and the information about the slots.
67 #[derive(Clone)]
68 pub struct ImagesBuilder {
69     flash: SimMultiFlash,
70     areadesc: AreaDesc,
71     slots: Vec<[SlotInfo; 2]>,
72     ram: RamData,
73 }
74 
75 /// Images represents the state of a simulation for a given set of images.
76 /// The flash holds the state of the simulated flash, whereas primaries
77 /// and upgrades hold the expected contents of these images.
78 pub struct Images {
79     flash: SimMultiFlash,
80     areadesc: AreaDesc,
81     images: Vec<OneImage>,
82     total_count: Option<i32>,
83     ram: RamData,
84 }
85 
86 /// When doing multi-image, there is an instance of this information for
87 /// each of the images.  Single image there will be one of these.
88 struct OneImage {
89     slots: [SlotInfo; 2],
90     primaries: ImageData,
91     upgrades: ImageData,
92 }
93 
94 /// The Rust-side representation of an image.  For unencrypted images, this
95 /// is just the unencrypted payload.  For encrypted images, we store both
96 /// the encrypted and the plaintext.
97 struct ImageData {
98     size: usize,
99     plain: Vec<u8>,
100     cipher: Option<Vec<u8>>,
101 }
102 
103 /// For the RamLoad test cases, we need a contiguous area of RAM to load these images into.  For
104 /// multi-image builds, these may not correspond with the offsets.  This has to be computed early,
105 /// before images are built, because each image contains the offset where the image is to be loaded
106 /// in the header, which is contained within the signature.
107 #[derive(Clone, Debug)]
108 struct RamData {
109     places: BTreeMap<SlotKey, SlotPlace>,
110     total: u32,
111 }
112 
113 /// Every slot is indexed by this key.
114 #[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
115 struct SlotKey {
116     dev_id: u8,
117     base_off: usize,
118 }
119 
120 #[derive(Clone, Debug)]
121 struct SlotPlace {
122     offset: u32,
123     size: u32,
124 }
125 
126 impl ImagesBuilder {
127     /// Construct a new image builder for the given device.  Returns
128     /// Some(builder) if is possible to test this configuration, or None if
129     /// not possible (for example, if there aren't enough image slots).
new(device: DeviceName, align: usize, erased_val: u8) -> Result<Self, String>130     pub fn new(device: DeviceName, align: usize, erased_val: u8) -> Result<Self, String> {
131         let (flash, areadesc, unsupported_caps) = Self::make_device(device, align, erased_val);
132 
133         for cap in unsupported_caps {
134             if cap.present() {
135                 return Err(format!("unsupported {:?}", cap));
136             }
137         }
138 
139         let num_images = Caps::get_num_images();
140 
141         let mut slots = Vec::with_capacity(num_images);
142         for image in 0..num_images {
143             // This mapping must match that defined in
144             // `boot/zephyr/include/sysflash/sysflash.h`.
145             let id0 = match image {
146                 0 => FlashId::Image0,
147                 1 => FlashId::Image2,
148                 _ => panic!("More than 2 images not supported"),
149             };
150             let (primary_base, primary_len, primary_dev_id) = match areadesc.find(id0) {
151                 Some(info) => info,
152                 None => return Err("insufficient partitions".to_string()),
153             };
154             let id1 = match image {
155                 0 => FlashId::Image1,
156                 1 => FlashId::Image3,
157                 _ => panic!("More than 2 images not supported"),
158             };
159             let (secondary_base, secondary_len, secondary_dev_id) = match areadesc.find(id1) {
160                 Some(info) => info,
161                 None => return Err("insufficient partitions".to_string()),
162             };
163 
164             let offset_from_end = c::boot_magic_sz() + c::boot_max_align() * 4;
165 
166             // Construct a primary image.
167             let primary = SlotInfo {
168                 base_off: primary_base as usize,
169                 trailer_off: primary_base + primary_len - offset_from_end,
170                 len: primary_len as usize,
171                 dev_id: primary_dev_id,
172                 index: 0,
173             };
174 
175             // And an upgrade image.
176             let secondary = SlotInfo {
177                 base_off: secondary_base as usize,
178                 trailer_off: secondary_base + secondary_len - offset_from_end,
179                 len: secondary_len as usize,
180                 dev_id: secondary_dev_id,
181                 index: 1,
182             };
183 
184             slots.push([primary, secondary]);
185         }
186 
187         let ram = RamData::new(&slots);
188 
189         Ok(ImagesBuilder {
190             flash,
191             areadesc,
192             slots,
193             ram,
194         })
195     }
196 
each_device<F>(f: F) where F: Fn(Self)197     pub fn each_device<F>(f: F)
198         where F: Fn(Self)
199     {
200         for &dev in ALL_DEVICES {
201             for &align in test_alignments() {
202                 for &erased_val in &[0, 0xff] {
203                     match Self::new(dev, align, erased_val) {
204                         Ok(run) => f(run),
205                         Err(msg) => warn!("Skipping {}: {}", dev, msg),
206                     }
207                 }
208             }
209         }
210     }
211 
212     /// Construct an `Images` that doesn't expect an upgrade to happen.
make_no_upgrade_image(self, deps: &DepTest) -> Images213     pub fn make_no_upgrade_image(self, deps: &DepTest) -> Images {
214         let num_images = self.num_images();
215         let mut flash = self.flash;
216         let ram = self.ram.clone();  // TODO: This is wasteful.
217         let images = self.slots.into_iter().enumerate().map(|(image_num, slots)| {
218             let dep: Box<dyn Depender> = if num_images > 1 {
219                 Box::new(PairDep::new(num_images, image_num, deps))
220             } else {
221                 Box::new(BoringDep::new(image_num, deps))
222             };
223             let primaries = install_image(&mut flash, &slots[0],
224                 maximal(42784), &ram, &*dep, false);
225             let upgrades = match deps.depends[image_num] {
226                 DepType::NoUpgrade => install_no_image(),
227                 _ => install_image(&mut flash, &slots[1],
228                     maximal(46928), &ram, &*dep, false)
229             };
230             OneImage {
231                 slots,
232                 primaries,
233                 upgrades,
234             }}).collect();
235         install_ptable(&mut flash, &self.areadesc);
236         Images {
237             flash,
238             areadesc: self.areadesc,
239             images,
240             total_count: None,
241             ram: self.ram,
242         }
243     }
244 
make_image(self, deps: &DepTest, permanent: bool) -> Images245     pub fn make_image(self, deps: &DepTest, permanent: bool) -> Images {
246         let mut images = self.make_no_upgrade_image(deps);
247         for image in &images.images {
248             mark_upgrade(&mut images.flash, &image.slots[1]);
249         }
250 
251         // The count is meaningless if no flash operations are performed.
252         if !Caps::modifies_flash() {
253             return images;
254         }
255 
256         // upgrades without fails, counts number of flash operations
257         let total_count = match images.run_basic_upgrade(permanent) {
258             Some(v)  => v,
259             None =>
260                 if deps.upgrades.iter().any(|u| *u == UpgradeInfo::Held) {
261                     0
262                 } else {
263                     panic!("Unable to perform basic upgrade");
264                 }
265         };
266 
267         images.total_count = Some(total_count);
268         images
269     }
270 
make_bad_secondary_slot_image(self) -> Images271     pub fn make_bad_secondary_slot_image(self) -> Images {
272         let mut bad_flash = self.flash;
273         let ram = self.ram.clone(); // TODO: Avoid this clone.
274         let images = self.slots.into_iter().enumerate().map(|(image_num, slots)| {
275             let dep = BoringDep::new(image_num, &NO_DEPS);
276             let primaries = install_image(&mut bad_flash, &slots[0],
277                 maximal(32784), &ram, &dep, false);
278             let upgrades = install_image(&mut bad_flash, &slots[1],
279                 maximal(41928), &ram, &dep, true);
280             OneImage {
281                 slots,
282                 primaries,
283                 upgrades,
284             }}).collect();
285         Images {
286             flash: bad_flash,
287             areadesc: self.areadesc,
288             images,
289             total_count: None,
290             ram: self.ram,
291         }
292     }
293 
make_oversized_secondary_slot_image(self) -> Images294     pub fn make_oversized_secondary_slot_image(self) -> Images {
295         let mut bad_flash = self.flash;
296         let ram = self.ram.clone(); // TODO: Avoid this clone.
297         let images = self.slots.into_iter().enumerate().map(|(image_num, slots)| {
298             let dep = BoringDep::new(image_num, &NO_DEPS);
299             let primaries = install_image(&mut bad_flash, &slots[0],
300                 maximal(32784), &ram, &dep, false);
301             let upgrades = install_image(&mut bad_flash, &slots[1],
302                 ImageSize::Oversized, &ram, &dep, false);
303             OneImage {
304                 slots,
305                 primaries,
306                 upgrades,
307             }}).collect();
308         Images {
309             flash: bad_flash,
310             areadesc: self.areadesc,
311             images,
312             total_count: None,
313             ram: self.ram,
314         }
315     }
316 
make_erased_secondary_image(self) -> Images317     pub fn make_erased_secondary_image(self) -> Images {
318         let mut flash = self.flash;
319         let ram = self.ram.clone(); // TODO: Avoid this clone.
320         let images = self.slots.into_iter().enumerate().map(|(image_num, slots)| {
321             let dep = BoringDep::new(image_num, &NO_DEPS);
322             let primaries = install_image(&mut flash, &slots[0],
323                 maximal(32784), &ram, &dep, false);
324             let upgrades = install_no_image();
325             OneImage {
326                 slots,
327                 primaries,
328                 upgrades,
329             }}).collect();
330         Images {
331             flash,
332             areadesc: self.areadesc,
333             images,
334             total_count: None,
335             ram: self.ram,
336         }
337     }
338 
make_bootstrap_image(self) -> Images339     pub fn make_bootstrap_image(self) -> Images {
340         let mut flash = self.flash;
341         let ram = self.ram.clone(); // TODO: Avoid this clone.
342         let images = self.slots.into_iter().enumerate().map(|(image_num, slots)| {
343             let dep = BoringDep::new(image_num, &NO_DEPS);
344             let primaries = install_no_image();
345             let upgrades = install_image(&mut flash, &slots[1],
346                 maximal(32784), &ram, &dep, false);
347             OneImage {
348                 slots,
349                 primaries,
350                 upgrades,
351             }}).collect();
352         Images {
353             flash,
354             areadesc: self.areadesc,
355             images,
356             total_count: None,
357             ram: self.ram,
358         }
359     }
360 
make_oversized_bootstrap_image(self) -> Images361     pub fn make_oversized_bootstrap_image(self) -> Images {
362         let mut flash = self.flash;
363         let ram = self.ram.clone(); // TODO: Avoid this clone.
364         let images = self.slots.into_iter().enumerate().map(|(image_num, slots)| {
365             let dep = BoringDep::new(image_num, &NO_DEPS);
366             let primaries = install_no_image();
367             let upgrades = install_image(&mut flash, &slots[1],
368                 ImageSize::Oversized, &ram, &dep, false);
369             OneImage {
370                 slots,
371                 primaries,
372                 upgrades,
373             }}).collect();
374         Images {
375             flash,
376             areadesc: self.areadesc,
377             images,
378             total_count: None,
379             ram: self.ram,
380         }
381     }
382 
383     /// Build the Flash and area descriptor for a given device.
make_device(device: DeviceName, align: usize, erased_val: u8) -> (SimMultiFlash, AreaDesc, &'static [Caps])384     pub fn make_device(device: DeviceName, align: usize, erased_val: u8) -> (SimMultiFlash, AreaDesc, &'static [Caps]) {
385         match device {
386             DeviceName::Stm32f4 => {
387                 // STM style flash.  Large sectors, with a large scratch area.
388                 // The flash layout as described is not present in any real STM32F4 device, but it
389                 // serves to exercise support for sectors of varying sizes inside a single slot,
390                 // as long as they are compatible in both slots and all fit in the scratch.
391                 let dev = SimFlash::new(vec![16 * 1024, 16 * 1024, 16 * 1024, 16 * 1024, 64 * 1024,
392                                         32 * 1024, 32 * 1024, 64 * 1024,
393                                         32 * 1024, 32 * 1024, 64 * 1024,
394                                         128 * 1024],
395                                         align as usize, erased_val);
396                 let dev_id = 0;
397                 let mut areadesc = AreaDesc::new();
398                 areadesc.add_flash_sectors(dev_id, &dev);
399                 areadesc.add_image(0x020000, 0x020000, FlashId::Image0, dev_id);
400                 areadesc.add_image(0x040000, 0x020000, FlashId::Image1, dev_id);
401                 areadesc.add_image(0x060000, 0x020000, FlashId::ImageScratch, dev_id);
402 
403                 let mut flash = SimMultiFlash::new();
404                 flash.insert(dev_id, dev);
405                 (flash, areadesc, &[Caps::SwapUsingMove])
406             }
407             DeviceName::K64f => {
408                 // NXP style flash.  Small sectors, one small sector for scratch.
409                 let dev = SimFlash::new(vec![4096; 128], align as usize, erased_val);
410 
411                 let dev_id = 0;
412                 let mut areadesc = AreaDesc::new();
413                 areadesc.add_flash_sectors(dev_id, &dev);
414                 areadesc.add_image(0x020000, 0x020000, FlashId::Image0, dev_id);
415                 areadesc.add_image(0x040000, 0x020000, FlashId::Image1, dev_id);
416                 areadesc.add_image(0x060000, 0x001000, FlashId::ImageScratch, dev_id);
417 
418                 let mut flash = SimMultiFlash::new();
419                 flash.insert(dev_id, dev);
420                 (flash, areadesc, &[])
421             }
422             DeviceName::K64fBig => {
423                 // Simulating an STM style flash on top of an NXP style flash.  Underlying flash device
424                 // uses small sectors, but we tell the bootloader they are large.
425                 let dev = SimFlash::new(vec![4096; 128], align as usize, erased_val);
426 
427                 let dev_id = 0;
428                 let mut areadesc = AreaDesc::new();
429                 areadesc.add_flash_sectors(dev_id, &dev);
430                 areadesc.add_simple_image(0x020000, 0x020000, FlashId::Image0, dev_id);
431                 areadesc.add_simple_image(0x040000, 0x020000, FlashId::Image1, dev_id);
432                 areadesc.add_simple_image(0x060000, 0x020000, FlashId::ImageScratch, dev_id);
433 
434                 let mut flash = SimMultiFlash::new();
435                 flash.insert(dev_id, dev);
436                 (flash, areadesc, &[Caps::SwapUsingMove])
437             }
438             DeviceName::Nrf52840 => {
439                 // Simulating the flash on the nrf52840 with partitions set up so that the scratch size
440                 // does not divide into the image size.
441                 let dev = SimFlash::new(vec![4096; 128], align as usize, erased_val);
442 
443                 let dev_id = 0;
444                 let mut areadesc = AreaDesc::new();
445                 areadesc.add_flash_sectors(dev_id, &dev);
446                 areadesc.add_image(0x008000, 0x034000, FlashId::Image0, dev_id);
447                 areadesc.add_image(0x03c000, 0x034000, FlashId::Image1, dev_id);
448                 areadesc.add_image(0x070000, 0x00d000, FlashId::ImageScratch, dev_id);
449 
450                 let mut flash = SimMultiFlash::new();
451                 flash.insert(dev_id, dev);
452                 (flash, areadesc, &[])
453             }
454             DeviceName::Nrf52840UnequalSlots => {
455                 let dev = SimFlash::new(vec![4096; 128], align as usize, erased_val);
456 
457                 let dev_id = 0;
458                 let mut areadesc = AreaDesc::new();
459                 areadesc.add_flash_sectors(dev_id, &dev);
460                 areadesc.add_image(0x008000, 0x03c000, FlashId::Image0, dev_id);
461                 areadesc.add_image(0x044000, 0x03b000, FlashId::Image1, dev_id);
462 
463                 let mut flash = SimMultiFlash::new();
464                 flash.insert(dev_id, dev);
465                 (flash, areadesc, &[Caps::SwapUsingScratch, Caps::OverwriteUpgrade])
466             }
467             DeviceName::Nrf52840SpiFlash => {
468                 // Simulate nrf52840 with external SPI flash. The external SPI flash
469                 // has a larger sector size so for now store scratch on that flash.
470                 let dev0 = SimFlash::new(vec![4096; 128], align as usize, erased_val);
471                 let dev1 = SimFlash::new(vec![8192; 64], align as usize, erased_val);
472 
473                 let mut areadesc = AreaDesc::new();
474                 areadesc.add_flash_sectors(0, &dev0);
475                 areadesc.add_flash_sectors(1, &dev1);
476 
477                 areadesc.add_image(0x008000, 0x068000, FlashId::Image0, 0);
478                 areadesc.add_image(0x000000, 0x068000, FlashId::Image1, 1);
479                 areadesc.add_image(0x068000, 0x018000, FlashId::ImageScratch, 1);
480 
481                 let mut flash = SimMultiFlash::new();
482                 flash.insert(0, dev0);
483                 flash.insert(1, dev1);
484                 (flash, areadesc, &[Caps::SwapUsingMove])
485             }
486             DeviceName::K64fMulti => {
487                 // NXP style flash, but larger, to support multiple images.
488                 let dev = SimFlash::new(vec![4096; 256], align as usize, erased_val);
489 
490                 let dev_id = 0;
491                 let mut areadesc = AreaDesc::new();
492                 areadesc.add_flash_sectors(dev_id, &dev);
493                 areadesc.add_image(0x020000, 0x020000, FlashId::Image0, dev_id);
494                 areadesc.add_image(0x040000, 0x020000, FlashId::Image1, dev_id);
495                 areadesc.add_image(0x060000, 0x001000, FlashId::ImageScratch, dev_id);
496                 areadesc.add_image(0x080000, 0x020000, FlashId::Image2, dev_id);
497                 areadesc.add_image(0x0a0000, 0x020000, FlashId::Image3, dev_id);
498 
499                 let mut flash = SimMultiFlash::new();
500                 flash.insert(dev_id, dev);
501                 (flash, areadesc, &[])
502             }
503         }
504     }
505 
num_images(&self) -> usize506     pub fn num_images(&self) -> usize {
507         self.slots.len()
508     }
509 }
510 
511 impl Images {
512     /// A simple upgrade without forced failures.
513     ///
514     /// Returns the number of flash operations which can later be used to
515     /// inject failures at chosen steps.  Returns None if it was unable to
516     /// count the operations in a basic upgrade.
run_basic_upgrade(&self, permanent: bool) -> Option<i32>517     pub fn run_basic_upgrade(&self, permanent: bool) -> Option<i32> {
518         let (flash, total_count) = self.try_upgrade(None, permanent);
519         info!("Total flash operation count={}", total_count);
520 
521         if !self.verify_images(&flash, 0, 1) {
522             warn!("Image mismatch after first boot");
523             None
524         } else {
525             Some(total_count)
526         }
527     }
528 
run_bootstrap(&self) -> bool529     pub fn run_bootstrap(&self) -> bool {
530         let mut flash = self.flash.clone();
531         let mut fails = 0;
532 
533         if Caps::Bootstrap.present() {
534             info!("Try bootstraping image in the primary");
535 
536             if !c::boot_go(&mut flash, &self.areadesc, None, None, false).success() {
537                 warn!("Failed first boot");
538                 fails += 1;
539             }
540 
541             if !self.verify_images(&flash, 0, 1) {
542                 warn!("Image in the first slot was not bootstrapped");
543                 fails += 1;
544             }
545 
546             if !self.verify_trailers(&flash, 0, BOOT_MAGIC_GOOD,
547                                      BOOT_FLAG_SET, BOOT_FLAG_SET) {
548                 warn!("Mismatched trailer for the primary slot");
549                 fails += 1;
550             }
551         }
552 
553         if fails > 0 {
554             error!("Expected trailer on secondary slot to be erased");
555         }
556 
557         fails > 0
558     }
559 
run_oversized_bootstrap(&self) -> bool560     pub fn run_oversized_bootstrap(&self) -> bool {
561         let mut flash = self.flash.clone();
562         let mut fails = 0;
563 
564         if Caps::Bootstrap.present() {
565             info!("Try bootstraping image in the primary");
566 
567             let boot_result = c::boot_go(&mut flash, &self.areadesc, None, None, false).interrupted();
568 
569             if boot_result {
570                 warn!("Failed first boot");
571                 fails += 1;
572             }
573 
574             if self.verify_images(&flash, 0, 1) {
575                 warn!("Image in the first slot was not bootstrapped");
576                 fails += 1;
577             }
578 
579             if self.verify_trailers(&flash, 0, BOOT_MAGIC_GOOD,
580                                      BOOT_FLAG_SET, BOOT_FLAG_SET) {
581                 warn!("Mismatched trailer for the primary slot");
582                 fails += 1;
583             }
584         }
585 
586         if fails > 0 {
587             error!("Expected trailer on secondary slot to be erased");
588         }
589 
590         fails > 0
591     }
592 
593 
594     /// Test a simple upgrade, with dependencies given, and verify that the
595     /// image does as is described in the test.
run_check_deps(&self, deps: &DepTest) -> bool596     pub fn run_check_deps(&self, deps: &DepTest) -> bool {
597         if !Caps::modifies_flash() {
598             return false;
599         }
600 
601         let (flash, _) = self.try_upgrade(None, true);
602 
603         self.verify_dep_images(&flash, deps)
604     }
605 
is_swap_upgrade(&self) -> bool606     fn is_swap_upgrade(&self) -> bool {
607         Caps::SwapUsingScratch.present() || Caps::SwapUsingMove.present()
608     }
609 
run_basic_revert(&self) -> bool610     pub fn run_basic_revert(&self) -> bool {
611         if Caps::OverwriteUpgrade.present() || !Caps::modifies_flash() {
612             return false;
613         }
614 
615         let mut fails = 0;
616 
617         // FIXME: this test would also pass if no swap is ever performed???
618         if self.is_swap_upgrade() {
619             for count in 2 .. 5 {
620                 info!("Try revert: {}", count);
621                 let flash = self.try_revert(count);
622                 if !self.verify_images(&flash, 0, 0) {
623                     error!("Revert failure on count {}", count);
624                     fails += 1;
625                 }
626             }
627         }
628 
629         fails > 0
630     }
631 
run_perm_with_fails(&self) -> bool632     pub fn run_perm_with_fails(&self) -> bool {
633         if !Caps::modifies_flash() {
634             return false;
635         }
636 
637         let mut fails = 0;
638         let total_flash_ops = self.total_count.unwrap();
639 
640         // Let's try an image halfway through.
641         for i in 1 .. total_flash_ops {
642             info!("Try interruption at {}", i);
643             let (flash, count) = self.try_upgrade(Some(i), true);
644             info!("Second boot, count={}", count);
645             if !self.verify_images(&flash, 0, 1) {
646                 warn!("FAIL at step {} of {}", i, total_flash_ops);
647                 fails += 1;
648             }
649 
650             if !self.verify_trailers(&flash, 0, BOOT_MAGIC_GOOD,
651                                      BOOT_FLAG_SET, BOOT_FLAG_SET) {
652                 warn!("Mismatched trailer for the primary slot");
653                 fails += 1;
654             }
655 
656             if !self.verify_trailers(&flash, 1, BOOT_MAGIC_UNSET,
657                                      BOOT_FLAG_UNSET, BOOT_FLAG_UNSET) {
658                 warn!("Mismatched trailer for the secondary slot");
659                 fails += 1;
660             }
661 
662             if self.is_swap_upgrade() && !self.verify_images(&flash, 1, 0) {
663                 warn!("Secondary slot FAIL at step {} of {}",
664                     i, total_flash_ops);
665                 fails += 1;
666             }
667         }
668 
669         if fails > 0 {
670             error!("{} out of {} failed {:.2}%", fails, total_flash_ops,
671                    fails as f32 * 100.0 / total_flash_ops as f32);
672         }
673 
674         fails > 0
675     }
676 
run_perm_with_random_fails(&self, total_fails: usize) -> bool677     pub fn run_perm_with_random_fails(&self, total_fails: usize) -> bool {
678         if !Caps::modifies_flash() {
679             return false;
680         }
681 
682         let mut fails = 0;
683         let total_flash_ops = self.total_count.unwrap();
684         let (flash, total_counts) = self.try_random_fails(total_flash_ops, total_fails);
685         info!("Random interruptions at reset points={:?}", total_counts);
686 
687         let primary_slot_ok = self.verify_images(&flash, 0, 1);
688         let secondary_slot_ok = if self.is_swap_upgrade() {
689             // TODO: This result is ignored.
690             self.verify_images(&flash, 1, 0)
691         } else {
692             true
693         };
694         if !primary_slot_ok || !secondary_slot_ok {
695             error!("Image mismatch after random interrupts: primary slot={} \
696                     secondary slot={}",
697                    if primary_slot_ok { "ok" } else { "fail" },
698                    if secondary_slot_ok { "ok" } else { "fail" });
699             fails += 1;
700         }
701         if !self.verify_trailers(&flash, 0, BOOT_MAGIC_GOOD,
702                                  BOOT_FLAG_SET, BOOT_FLAG_SET) {
703             error!("Mismatched trailer for the primary slot");
704             fails += 1;
705         }
706         if !self.verify_trailers(&flash, 1, BOOT_MAGIC_UNSET,
707                                  BOOT_FLAG_UNSET, BOOT_FLAG_UNSET) {
708             error!("Mismatched trailer for the secondary slot");
709             fails += 1;
710         }
711 
712         if fails > 0 {
713             error!("Error testing perm upgrade with {} fails", total_fails);
714         }
715 
716         fails > 0
717     }
718 
run_revert_with_fails(&self) -> bool719     pub fn run_revert_with_fails(&self) -> bool {
720         if Caps::OverwriteUpgrade.present() || !Caps::modifies_flash() {
721             return false;
722         }
723 
724         let mut fails = 0;
725 
726         if self.is_swap_upgrade() {
727             for i in 1 .. self.total_count.unwrap() {
728                 info!("Try interruption at {}", i);
729                 if self.try_revert_with_fail_at(i) {
730                     error!("Revert failed at interruption {}", i);
731                     fails += 1;
732                 }
733             }
734         }
735 
736         fails > 0
737     }
738 
run_norevert(&self) -> bool739     pub fn run_norevert(&self) -> bool {
740         if Caps::OverwriteUpgrade.present() || !Caps::modifies_flash() {
741             return false;
742         }
743 
744         let mut flash = self.flash.clone();
745         let mut fails = 0;
746 
747         info!("Try norevert");
748 
749         // First do a normal upgrade...
750         if !c::boot_go(&mut flash, &self.areadesc, None, None, false).success() {
751             warn!("Failed first boot");
752             fails += 1;
753         }
754 
755         //FIXME: copy_done is written by boot_go, is it ok if no copy
756         //       was ever done?
757 
758         if !self.verify_images(&flash, 0, 1) {
759             warn!("Primary slot image verification FAIL");
760             fails += 1;
761         }
762         if !self.verify_trailers(&flash, 0, BOOT_MAGIC_GOOD,
763                                  BOOT_FLAG_UNSET, BOOT_FLAG_SET) {
764             warn!("Mismatched trailer for the primary slot");
765             fails += 1;
766         }
767         if !self.verify_trailers(&flash, 1, BOOT_MAGIC_UNSET,
768                                  BOOT_FLAG_UNSET, BOOT_FLAG_UNSET) {
769             warn!("Mismatched trailer for the secondary slot");
770             fails += 1;
771         }
772 
773         // Marks image in the primary slot as permanent,
774         // no revert should happen...
775         self.mark_permanent_upgrades(&mut flash, 0);
776 
777         if !self.verify_trailers(&flash, 0, BOOT_MAGIC_GOOD,
778                                  BOOT_FLAG_SET, BOOT_FLAG_SET) {
779             warn!("Mismatched trailer for the primary slot");
780             fails += 1;
781         }
782 
783         if !c::boot_go(&mut flash, &self.areadesc, None, None, false).success() {
784             warn!("Failed second boot");
785             fails += 1;
786         }
787 
788         if !self.verify_trailers(&flash, 0, BOOT_MAGIC_GOOD,
789                                  BOOT_FLAG_SET, BOOT_FLAG_SET) {
790             warn!("Mismatched trailer for the primary slot");
791             fails += 1;
792         }
793         if !self.verify_images(&flash, 0, 1) {
794             warn!("Failed image verification");
795             fails += 1;
796         }
797 
798         if fails > 0 {
799             error!("Error running upgrade without revert");
800         }
801 
802         fails > 0
803     }
804 
805     // Test taht too big upgrade image will be rejected
run_oversizefail_upgrade(&self) -> bool806     pub fn run_oversizefail_upgrade(&self) -> bool {
807         let mut flash = self.flash.clone();
808         let mut fails = 0;
809 
810         info!("Try upgrade image with to big size");
811 
812         // Only perform this test if an upgrade is expected to happen.
813         if !Caps::modifies_flash() {
814             info!("Skipping upgrade image with bad signature");
815             return false;
816         }
817 
818         self.mark_upgrades(&mut flash, 0);
819         self.mark_permanent_upgrades(&mut flash, 0);
820         self.mark_upgrades(&mut flash, 1);
821 
822         if !self.verify_trailers(&flash, 0, BOOT_MAGIC_GOOD,
823                                  BOOT_FLAG_SET, BOOT_FLAG_UNSET) {
824             warn!("1. Mismatched trailer for the primary slot");
825             fails += 1;
826         }
827 
828         // Run the bootloader...
829         if !c::boot_go(&mut flash, &self.areadesc, None, None, false).success() {
830             warn!("Failed first boot");
831             fails += 1;
832         }
833 
834         // State should not have changed
835         if !self.verify_images(&flash, 0, 0) {
836             warn!("Failed image verification");
837             fails += 1;
838         }
839         if !self.verify_trailers(&flash, 0, BOOT_MAGIC_GOOD,
840                                  BOOT_FLAG_SET, BOOT_FLAG_UNSET) {
841             warn!("2. Mismatched trailer for the primary slot");
842             fails += 1;
843         }
844 
845         if fails > 0 {
846             error!("Expected an upgrade failure when image has to big size");
847         }
848 
849         fails > 0
850     }
851 
852     // Test that an upgrade is rejected.  Assumes that the image was build
853     // such that the upgrade is instead a downgrade.
run_nodowngrade(&self) -> bool854     pub fn run_nodowngrade(&self) -> bool {
855         if !Caps::DowngradePrevention.present() {
856             return false;
857         }
858 
859         let mut flash = self.flash.clone();
860         let mut fails = 0;
861 
862         info!("Try no downgrade");
863 
864         // First, do a normal upgrade.
865         if !c::boot_go(&mut flash, &self.areadesc, None, None, false).success() {
866             warn!("Failed first boot");
867             fails += 1;
868         }
869 
870         if !self.verify_images(&flash, 0, 0) {
871             warn!("Failed verification after downgrade rejection");
872             fails += 1;
873         }
874 
875         if fails > 0 {
876             error!("Error testing downgrade rejection");
877         }
878 
879         fails > 0
880     }
881 
882     // Tests a new image written to the primary slot that already has magic and
883     // image_ok set while there is no image on the secondary slot, so no revert
884     // should ever happen...
run_norevert_newimage(&self) -> bool885     pub fn run_norevert_newimage(&self) -> bool {
886         if !Caps::modifies_flash() {
887             info!("Skipping run_norevert_newimage, as configuration doesn't modify flash");
888             return false;
889         }
890 
891         let mut flash = self.flash.clone();
892         let mut fails = 0;
893 
894         info!("Try non-revert on imgtool generated image");
895 
896         self.mark_upgrades(&mut flash, 0);
897 
898         // This simulates writing an image created by imgtool to
899         // the primary slot
900         if !self.verify_trailers(&flash, 0, BOOT_MAGIC_GOOD,
901                                  BOOT_FLAG_UNSET, BOOT_FLAG_UNSET) {
902             warn!("Mismatched trailer for the primary slot");
903             fails += 1;
904         }
905 
906         // Run the bootloader...
907         if !c::boot_go(&mut flash, &self.areadesc, None, None, false).success() {
908             warn!("Failed first boot");
909             fails += 1;
910         }
911 
912         // State should not have changed
913         if !self.verify_images(&flash, 0, 0) {
914             warn!("Failed image verification");
915             fails += 1;
916         }
917         if !self.verify_trailers(&flash, 0, BOOT_MAGIC_GOOD,
918                                  BOOT_FLAG_UNSET, BOOT_FLAG_UNSET) {
919             warn!("Mismatched trailer for the primary slot");
920             fails += 1;
921         }
922         if !self.verify_trailers(&flash, 1, BOOT_MAGIC_UNSET,
923                                  BOOT_FLAG_UNSET, BOOT_FLAG_UNSET) {
924             warn!("Mismatched trailer for the secondary slot");
925             fails += 1;
926         }
927 
928         if fails > 0 {
929             error!("Expected a non revert with new image");
930         }
931 
932         fails > 0
933     }
934 
935     // Tests a new image written to the primary slot that already has magic and
936     // image_ok set while there is no image on the secondary slot, so no revert
937     // should ever happen...
run_signfail_upgrade(&self) -> bool938     pub fn run_signfail_upgrade(&self) -> bool {
939         let mut flash = self.flash.clone();
940         let mut fails = 0;
941 
942         info!("Try upgrade image with bad signature");
943 
944         // Only perform this test if an upgrade is expected to happen.
945         if !Caps::modifies_flash() {
946             info!("Skipping upgrade image with bad signature");
947             return false;
948         }
949 
950         self.mark_upgrades(&mut flash, 0);
951         self.mark_permanent_upgrades(&mut flash, 0);
952         self.mark_upgrades(&mut flash, 1);
953 
954         if !self.verify_trailers(&flash, 0, BOOT_MAGIC_GOOD,
955                                  BOOT_FLAG_SET, BOOT_FLAG_UNSET) {
956             warn!("Mismatched trailer for the primary slot");
957             fails += 1;
958         }
959 
960         // Run the bootloader...
961         if !c::boot_go(&mut flash, &self.areadesc, None, None, false).success() {
962             warn!("Failed first boot");
963             fails += 1;
964         }
965 
966         // State should not have changed
967         if !self.verify_images(&flash, 0, 0) {
968             warn!("Failed image verification");
969             fails += 1;
970         }
971         if !self.verify_trailers(&flash, 0, BOOT_MAGIC_GOOD,
972                                  BOOT_FLAG_SET, BOOT_FLAG_UNSET) {
973             warn!("Mismatched trailer for the primary slot");
974             fails += 1;
975         }
976 
977         if fails > 0 {
978             error!("Expected an upgrade failure when image has bad signature");
979         }
980 
981         fails > 0
982     }
983 
984     // Should detect there is a leftover trailer in an otherwise erased
985     // secondary slot and erase its trailer.
run_secondary_leftover_trailer(&self) -> bool986     pub fn run_secondary_leftover_trailer(&self) -> bool {
987         if !Caps::modifies_flash() {
988             return false;
989         }
990 
991         let mut flash = self.flash.clone();
992         let mut fails = 0;
993 
994         info!("Try with a leftover trailer in the secondary; must be erased");
995 
996         // Add a trailer on the secondary slot
997         self.mark_permanent_upgrades(&mut flash, 1);
998         self.mark_upgrades(&mut flash, 1);
999 
1000         // Run the bootloader...
1001         if !c::boot_go(&mut flash, &self.areadesc, None, None, false).success() {
1002             warn!("Failed first boot");
1003             fails += 1;
1004         }
1005 
1006         // State should not have changed
1007         if !self.verify_images(&flash, 0, 0) {
1008             warn!("Failed image verification");
1009             fails += 1;
1010         }
1011         if !self.verify_trailers(&flash, 1, BOOT_MAGIC_UNSET,
1012                                  BOOT_FLAG_UNSET, BOOT_FLAG_UNSET) {
1013             warn!("Mismatched trailer for the secondary slot");
1014             fails += 1;
1015         }
1016 
1017         if fails > 0 {
1018             error!("Expected trailer on secondary slot to be erased");
1019         }
1020 
1021         fails > 0
1022     }
1023 
trailer_sz(&self, align: usize) -> usize1024     fn trailer_sz(&self, align: usize) -> usize {
1025         c::boot_trailer_sz(align as u32) as usize
1026     }
1027 
status_sz(&self, align: usize) -> usize1028     fn status_sz(&self, align: usize) -> usize {
1029         c::boot_status_sz(align as u32) as usize
1030     }
1031 
1032     /// This test runs a simple upgrade with no fails in the images, but
1033     /// allowing for fails in the status area. This should run to the end
1034     /// and warn that write fails were detected...
run_with_status_fails_complete(&self) -> bool1035     pub fn run_with_status_fails_complete(&self) -> bool {
1036         if !Caps::ValidatePrimarySlot.present() || !Caps::modifies_flash() {
1037             return false;
1038         }
1039 
1040         let mut flash = self.flash.clone();
1041         let mut fails = 0;
1042 
1043         info!("Try swap with status fails");
1044 
1045         self.mark_permanent_upgrades(&mut flash, 1);
1046         self.mark_bad_status_with_rate(&mut flash, 0, 1.0);
1047 
1048         let result = c::boot_go(&mut flash, &self.areadesc, None, None, true);
1049         if !result.success() {
1050             warn!("Failed!");
1051             fails += 1;
1052         }
1053 
1054         // Failed writes to the marked "bad" region don't assert anymore.
1055         // Any detected assert() is happening in another part of the code.
1056         if result.asserts() != 0 {
1057             warn!("At least one assert() was called");
1058             fails += 1;
1059         }
1060 
1061         if !self.verify_trailers(&flash, 0, BOOT_MAGIC_GOOD,
1062                                  BOOT_FLAG_SET, BOOT_FLAG_SET) {
1063             warn!("Mismatched trailer for the primary slot");
1064             fails += 1;
1065         }
1066 
1067         if !self.verify_images(&flash, 0, 1) {
1068             warn!("Failed image verification");
1069             fails += 1;
1070         }
1071 
1072         info!("validate primary slot enabled; \
1073                re-run of boot_go should just work");
1074         if !c::boot_go(&mut flash, &self.areadesc, None, None, false).success() {
1075             warn!("Failed!");
1076             fails += 1;
1077         }
1078 
1079         if fails > 0 {
1080             error!("Error running upgrade with status write fails");
1081         }
1082 
1083         fails > 0
1084     }
1085 
1086     /// This test runs a simple upgrade with no fails in the images, but
1087     /// allowing for fails in the status area. This should run to the end
1088     /// and warn that write fails were detected...
run_with_status_fails_with_reset(&self) -> bool1089     pub fn run_with_status_fails_with_reset(&self) -> bool {
1090         if Caps::OverwriteUpgrade.present() || !Caps::modifies_flash() {
1091             false
1092         } else if Caps::ValidatePrimarySlot.present() {
1093 
1094             let mut flash = self.flash.clone();
1095             let mut fails = 0;
1096             let mut count = self.total_count.unwrap() / 2;
1097 
1098             //info!("count={}\n", count);
1099 
1100             info!("Try interrupted swap with status fails");
1101 
1102             self.mark_permanent_upgrades(&mut flash, 1);
1103             self.mark_bad_status_with_rate(&mut flash, 0, 0.5);
1104 
1105             // Should not fail, writing to bad regions does not assert
1106             let asserts = c::boot_go(&mut flash, &self.areadesc,
1107                                      Some(&mut count), None, true).asserts();
1108             if asserts != 0 {
1109                 warn!("At least one assert() was called");
1110                 fails += 1;
1111             }
1112 
1113             self.reset_bad_status(&mut flash, 0);
1114 
1115             info!("Resuming an interrupted swap operation");
1116             let asserts = c::boot_go(&mut flash, &self.areadesc, None, None,
1117                                      true).asserts();
1118 
1119             // This might throw no asserts, for large sector devices, where
1120             // a single failure writing is indistinguishable from no failure,
1121             // or throw a single assert for small sector devices that fail
1122             // multiple times...
1123             if asserts > 1 {
1124                 warn!("Expected single assert validating the primary slot, \
1125                        more detected {}", asserts);
1126                 fails += 1;
1127             }
1128 
1129             if fails > 0 {
1130                 error!("Error running upgrade with status write fails");
1131             }
1132 
1133             fails > 0
1134         } else {
1135             let mut flash = self.flash.clone();
1136             let mut fails = 0;
1137 
1138             info!("Try interrupted swap with status fails");
1139 
1140             self.mark_permanent_upgrades(&mut flash, 1);
1141             self.mark_bad_status_with_rate(&mut flash, 0, 1.0);
1142 
1143             // This is expected to fail while writing to bad regions...
1144             let asserts = c::boot_go(&mut flash, &self.areadesc, None, None,
1145                                      true).asserts();
1146             if asserts == 0 {
1147                 warn!("No assert() detected");
1148                 fails += 1;
1149             }
1150 
1151             fails > 0
1152         }
1153     }
1154 
1155     /// Test the direct XIP configuration.  With this mode, flash images are never moved, and the
1156     /// bootloader merely selects which partition is the proper one to boot.
run_direct_xip(&self) -> bool1157     pub fn run_direct_xip(&self) -> bool {
1158         if !Caps::DirectXip.present() {
1159             return false;
1160         }
1161 
1162         // Clone the flash so we can tell if unchanged.
1163         let mut flash = self.flash.clone();
1164 
1165         let result = c::boot_go(&mut flash, &self.areadesc, None, None, true);
1166 
1167         // Ensure the boot was successful.
1168         let resp = if let Some(resp) = result.resp() {
1169             resp
1170         } else {
1171             panic!("Boot didn't return a valid result");
1172         };
1173 
1174         // This configuration should always try booting from the first upgrade slot.
1175         if let Some((offset, _, dev_id)) = self.areadesc.find(FlashId::Image1) {
1176             assert_eq!(offset, resp.image_off as usize);
1177             assert_eq!(dev_id, resp.flash_dev_id);
1178         } else {
1179             panic!("Unable to find upgrade image");
1180         }
1181         false
1182     }
1183 
1184     /// Test the ram-loading.
run_ram_load(&self) -> bool1185     pub fn run_ram_load(&self) -> bool {
1186         if !Caps::RamLoad.present() {
1187             return false;
1188         }
1189 
1190         // Clone the flash so we can tell if unchanged.
1191         let mut flash = self.flash.clone();
1192 
1193         // Setup ram based on the ram configuration we determined earlier for the images.
1194         let ram = RamBlock::new(self.ram.total - RAM_LOAD_ADDR, RAM_LOAD_ADDR);
1195 
1196         // println!("Ram: {:#?}", self.ram);
1197 
1198         // Verify that the images area loaded into this.
1199         let result = ram.invoke(|| c::boot_go(&mut flash, &self.areadesc, None,
1200                                               None, true));
1201         if !result.success() {
1202             error!("Failed to execute ram-load");
1203             return true;
1204         }
1205 
1206         // Verify each image.
1207         for image in &self.images {
1208             let place = self.ram.lookup(&image.slots[0]);
1209             let ram_image = ram.borrow_part(place.offset as usize - RAM_LOAD_ADDR as usize,
1210                 place.size as usize);
1211             let src_sz = image.upgrades.size();
1212             if src_sz > ram_image.len() {
1213                 error!("Image ended up too large, nonsensical");
1214                 return true;
1215             }
1216             let src_image = &image.upgrades.plain[0..src_sz];
1217             let ram_image = &ram_image[0..src_sz];
1218             if ram_image != src_image {
1219                 error!("Image not loaded correctly");
1220                 return true;
1221             }
1222 
1223         }
1224 
1225         return false;
1226     }
1227 
1228     /// Test the split ram-loading.
run_split_ram_load(&self) -> bool1229     pub fn run_split_ram_load(&self) -> bool {
1230         if !Caps::RamLoad.present() {
1231             return false;
1232         }
1233 
1234         // Clone the flash so we can tell if unchanged.
1235         let mut flash = self.flash.clone();
1236 
1237         // Setup ram based on the ram configuration we determined earlier for the images.
1238         let ram = RamBlock::new(self.ram.total - RAM_LOAD_ADDR, RAM_LOAD_ADDR);
1239 
1240         for (idx, _image) in (&self.images).iter().enumerate() {
1241             // Verify that the images area loaded into this.
1242             let result = ram.invoke(|| c::boot_go(&mut flash, &self.areadesc,
1243                                                   None, Some(idx as i32), true));
1244             if !result.success() {
1245                 error!("Failed to execute ram-load");
1246                 return true;
1247             }
1248         }
1249 
1250         // Verify each image.
1251         for image in &self.images {
1252             let place = self.ram.lookup(&image.slots[0]);
1253             let ram_image = ram.borrow_part(place.offset as usize - RAM_LOAD_ADDR as usize,
1254                 place.size as usize);
1255             let src_sz = image.upgrades.size();
1256             if src_sz > ram_image.len() {
1257                 error!("Image ended up too large, nonsensical");
1258                 return true;
1259             }
1260             let src_image = &image.upgrades.plain[0..src_sz];
1261             let ram_image = &ram_image[0..src_sz];
1262             if ram_image != src_image {
1263                 error!("Image not loaded correctly");
1264                 return true;
1265             }
1266 
1267         }
1268 
1269         return false;
1270     }
1271 
1272     /// Adds a new flash area that fails statistically
mark_bad_status_with_rate(&self, flash: &mut SimMultiFlash, slot: usize, rate: f32)1273     fn mark_bad_status_with_rate(&self, flash: &mut SimMultiFlash, slot: usize,
1274                                  rate: f32) {
1275         if Caps::OverwriteUpgrade.present() {
1276             return;
1277         }
1278 
1279         // Set this for each image.
1280         for image in &self.images {
1281             let dev_id = &image.slots[slot].dev_id;
1282             let dev = flash.get_mut(&dev_id).unwrap();
1283             let align = dev.align();
1284             let off = &image.slots[slot].base_off;
1285             let len = &image.slots[slot].len;
1286             let status_off = off + len - self.trailer_sz(align);
1287 
1288             // Mark the status area as a bad area
1289             let _ = dev.add_bad_region(status_off, self.status_sz(align), rate);
1290         }
1291     }
1292 
reset_bad_status(&self, flash: &mut SimMultiFlash, slot: usize)1293     fn reset_bad_status(&self, flash: &mut SimMultiFlash, slot: usize) {
1294         if !Caps::ValidatePrimarySlot.present() {
1295             return;
1296         }
1297 
1298         for image in &self.images {
1299             let dev_id = &image.slots[slot].dev_id;
1300             let dev = flash.get_mut(&dev_id).unwrap();
1301             dev.reset_bad_regions();
1302 
1303             // Disabling write verification the only assert triggered by
1304             // boot_go should be checking for integrity of status bytes.
1305             dev.set_verify_writes(false);
1306         }
1307     }
1308 
1309     /// Test a boot, optionally stopping after 'n' flash options.  Returns a count
1310     /// of the number of flash operations done total.
try_upgrade(&self, stop: Option<i32>, permanent: bool) -> (SimMultiFlash, i32)1311     fn try_upgrade(&self, stop: Option<i32>, permanent: bool) -> (SimMultiFlash, i32) {
1312         // Clone the flash to have a new copy.
1313         let mut flash = self.flash.clone();
1314 
1315         if permanent {
1316             self.mark_permanent_upgrades(&mut flash, 1);
1317         }
1318 
1319         let mut counter = stop.unwrap_or(0);
1320 
1321         let (first_interrupted, count) = match c::boot_go(&mut flash,
1322                                                           &self.areadesc,
1323                                                           Some(&mut counter),
1324                                                           None, false) {
1325             x if x.interrupted() => (true, stop.unwrap()),
1326             x if x.success() => (false, -counter),
1327             x => panic!("Unknown return: {:?}", x),
1328         };
1329 
1330         counter = 0;
1331         if first_interrupted {
1332             // fl.dump();
1333             match c::boot_go(&mut flash, &self.areadesc, Some(&mut counter),
1334                              None, false) {
1335                 x if x.interrupted() => panic!("Shouldn't stop again"),
1336                 x if x.success() => (),
1337                 x => panic!("Unknown return: {:?}", x),
1338             }
1339         }
1340 
1341         (flash, count - counter)
1342     }
1343 
try_revert(&self, count: usize) -> SimMultiFlash1344     fn try_revert(&self, count: usize) -> SimMultiFlash {
1345         let mut flash = self.flash.clone();
1346 
1347         // fl.write_file("image0.bin").unwrap();
1348         for i in 0 .. count {
1349             info!("Running boot pass {}", i + 1);
1350             assert!(c::boot_go(&mut flash, &self.areadesc, None, None, false).success_no_asserts());
1351         }
1352         flash
1353     }
1354 
try_revert_with_fail_at(&self, stop: i32) -> bool1355     fn try_revert_with_fail_at(&self, stop: i32) -> bool {
1356         let mut flash = self.flash.clone();
1357         let mut fails = 0;
1358 
1359         let mut counter = stop;
1360         if !c::boot_go(&mut flash, &self.areadesc, Some(&mut counter), None,
1361                        false).interrupted() {
1362             warn!("Should have stopped test at interruption point");
1363             fails += 1;
1364         }
1365 
1366         // In a multi-image setup, copy done might be set if any number of
1367         // images was already successfully swapped.
1368         if !self.verify_trailers_loose(&flash, 0, None, None, BOOT_FLAG_UNSET) {
1369             warn!("copy_done should be unset");
1370             fails += 1;
1371         }
1372 
1373         if !c::boot_go(&mut flash, &self.areadesc, None, None, false).success() {
1374             warn!("Should have finished test upgrade");
1375             fails += 1;
1376         }
1377 
1378         if !self.verify_images(&flash, 0, 1) {
1379             warn!("Image in the primary slot before revert is invalid at stop={}",
1380                   stop);
1381             fails += 1;
1382         }
1383         if !self.verify_images(&flash, 1, 0) {
1384             warn!("Image in the secondary slot before revert is invalid at stop={}",
1385                   stop);
1386             fails += 1;
1387         }
1388         if !self.verify_trailers(&flash, 0, BOOT_MAGIC_GOOD,
1389                                  BOOT_FLAG_UNSET, BOOT_FLAG_SET) {
1390             warn!("Mismatched trailer for the primary slot before revert");
1391             fails += 1;
1392         }
1393         if !self.verify_trailers(&flash, 1, BOOT_MAGIC_UNSET,
1394                                 BOOT_FLAG_UNSET, BOOT_FLAG_UNSET) {
1395             warn!("Mismatched trailer for the secondary slot before revert");
1396             fails += 1;
1397         }
1398 
1399         // Do Revert
1400         let mut counter = stop;
1401         if !c::boot_go(&mut flash, &self.areadesc, Some(&mut counter), None,
1402                        false).interrupted() {
1403             warn!("Should have stopped revert at interruption point");
1404             fails += 1;
1405         }
1406 
1407         if !c::boot_go(&mut flash, &self.areadesc, None, None, false).success() {
1408             warn!("Should have finished revert upgrade");
1409             fails += 1;
1410         }
1411 
1412         if !self.verify_images(&flash, 0, 0) {
1413             warn!("Image in the primary slot after revert is invalid at stop={}",
1414                   stop);
1415             fails += 1;
1416         }
1417         if !self.verify_images(&flash, 1, 1) {
1418             warn!("Image in the secondary slot after revert is invalid at stop={}",
1419                   stop);
1420             fails += 1;
1421         }
1422 
1423         if !self.verify_trailers(&flash, 0, BOOT_MAGIC_GOOD,
1424                                  BOOT_FLAG_SET, BOOT_FLAG_SET) {
1425             warn!("Mismatched trailer for the primary slot after revert");
1426             fails += 1;
1427         }
1428         if !self.verify_trailers(&flash, 1, BOOT_MAGIC_UNSET,
1429                                  BOOT_FLAG_UNSET, BOOT_FLAG_UNSET) {
1430             warn!("Mismatched trailer for the secondary slot after revert");
1431             fails += 1;
1432         }
1433 
1434         if !c::boot_go(&mut flash, &self.areadesc, None, None, false).success() {
1435             warn!("Should have finished 3rd boot");
1436             fails += 1;
1437         }
1438 
1439         if !self.verify_images(&flash, 0, 0) {
1440             warn!("Image in the primary slot is invalid on 1st boot after revert");
1441             fails += 1;
1442         }
1443         if !self.verify_images(&flash, 1, 1) {
1444             warn!("Image in the secondary slot is invalid on 1st boot after revert");
1445             fails += 1;
1446         }
1447 
1448         fails > 0
1449     }
1450 
1451 
try_random_fails(&self, total_ops: i32, count: usize) -> (SimMultiFlash, Vec<i32>)1452     fn try_random_fails(&self, total_ops: i32, count: usize) -> (SimMultiFlash, Vec<i32>) {
1453         let mut flash = self.flash.clone();
1454 
1455         self.mark_permanent_upgrades(&mut flash, 1);
1456 
1457         let mut rng = rand::thread_rng();
1458         let mut resets = vec![0i32; count];
1459         let mut remaining_ops = total_ops;
1460         for reset in &mut resets {
1461             let reset_counter = rng.gen_range(1 ..= remaining_ops / 2);
1462             let mut counter = reset_counter;
1463             match c::boot_go(&mut flash, &self.areadesc, Some(&mut counter),
1464                              None, false) {
1465                 x if x.interrupted() => (),
1466                 x => panic!("Unknown return: {:?}", x),
1467             }
1468             remaining_ops -= reset_counter;
1469             *reset = reset_counter;
1470         }
1471 
1472         match c::boot_go(&mut flash, &self.areadesc, None, None, false) {
1473             x if x.interrupted() => panic!("Should not be have been interrupted!"),
1474             x if x.success() => (),
1475             x => panic!("Unknown return: {:?}", x),
1476         }
1477 
1478         (flash, resets)
1479     }
1480 
1481     /// Verify the image in the given flash device, the specified slot
1482     /// against the expected image.
verify_images(&self, flash: &SimMultiFlash, slot: usize, against: usize) -> bool1483     fn verify_images(&self, flash: &SimMultiFlash, slot: usize, against: usize) -> bool {
1484         self.images.iter().all(|image| {
1485             verify_image(flash, &image.slots[slot],
1486                          match against {
1487                              0 => &image.primaries,
1488                              1 => &image.upgrades,
1489                              _ => panic!("Invalid 'against'")
1490                              })
1491         })
1492     }
1493 
1494     /// Verify the images, according to the dependency test.
verify_dep_images(&self, flash: &SimMultiFlash, deps: &DepTest) -> bool1495     fn verify_dep_images(&self, flash: &SimMultiFlash, deps: &DepTest) -> bool {
1496         for (image_num, (image, upgrade)) in self.images.iter().zip(deps.upgrades.iter()).enumerate() {
1497             info!("Upgrade: slot:{}, {:?}", image_num, upgrade);
1498             if !verify_image(flash, &image.slots[0],
1499                             match upgrade {
1500                                 UpgradeInfo::Upgraded => &image.upgrades,
1501                                 UpgradeInfo::Held => &image.primaries,
1502                             }) {
1503                 error!("Failed to upgrade properly: image: {}, upgrade: {:?}", image_num, upgrade);
1504                 return true;
1505             }
1506         }
1507 
1508         false
1509     }
1510 
1511     /// Verify that at least one of the trailers of the images have the
1512     /// specified values.
verify_trailers_loose(&self, flash: &SimMultiFlash, slot: usize, magic: Option<u8>, image_ok: Option<u8>, copy_done: Option<u8>) -> bool1513     fn verify_trailers_loose(&self, flash: &SimMultiFlash, slot: usize,
1514                              magic: Option<u8>, image_ok: Option<u8>,
1515                              copy_done: Option<u8>) -> bool {
1516         self.images.iter().any(|image| {
1517             verify_trailer(flash, &image.slots[slot],
1518                            magic, image_ok, copy_done)
1519         })
1520     }
1521 
1522     /// Verify that the trailers of the images have the specified
1523     /// values.
verify_trailers(&self, flash: &SimMultiFlash, slot: usize, magic: Option<u8>, image_ok: Option<u8>, copy_done: Option<u8>) -> bool1524     fn verify_trailers(&self, flash: &SimMultiFlash, slot: usize,
1525                        magic: Option<u8>, image_ok: Option<u8>,
1526                        copy_done: Option<u8>) -> bool {
1527         self.images.iter().all(|image| {
1528             verify_trailer(flash, &image.slots[slot],
1529                            magic, image_ok, copy_done)
1530         })
1531     }
1532 
1533     /// Mark each of the images for permanent upgrade.
mark_permanent_upgrades(&self, flash: &mut SimMultiFlash, slot: usize)1534     fn mark_permanent_upgrades(&self, flash: &mut SimMultiFlash, slot: usize) {
1535         for image in &self.images {
1536             mark_permanent_upgrade(flash, &image.slots[slot]);
1537         }
1538     }
1539 
1540     /// Mark each of the images for permanent upgrade.
mark_upgrades(&self, flash: &mut SimMultiFlash, slot: usize)1541     fn mark_upgrades(&self, flash: &mut SimMultiFlash, slot: usize) {
1542         for image in &self.images {
1543             mark_upgrade(flash, &image.slots[slot]);
1544         }
1545     }
1546 
1547     /// Dump out the flash image(s) to one or more files for debugging
1548     /// purposes.  The names will be written as either "{prefix}.mcubin" or
1549     /// "{prefix}-001.mcubin" depending on how many images there are.
debug_dump(&self, prefix: &str)1550     pub fn debug_dump(&self, prefix: &str) {
1551         for (id, fdev) in &self.flash {
1552             let name = if self.flash.len() == 1 {
1553                 format!("{}.mcubin", prefix)
1554             } else {
1555                 format!("{}-{:>0}.mcubin", prefix, id)
1556             };
1557             fdev.write_file(&name).unwrap();
1558         }
1559     }
1560 }
1561 
1562 impl RamData {
1563     // TODO: This is not correct. The second slot of each image should be at the same address as
1564     // the primary.
new(slots: &[[SlotInfo; 2]]) -> RamData1565     fn new(slots: &[[SlotInfo; 2]]) -> RamData {
1566         let mut addr = RAM_LOAD_ADDR;
1567         let mut places = BTreeMap::new();
1568         // println!("Setup:-------------");
1569         for imgs in slots {
1570             for si in imgs {
1571                 // println!("Setup: si: {:?}", si);
1572                 let offset = addr;
1573                 let size = si.len as u32;
1574                 places.insert(SlotKey {
1575                     dev_id: si.dev_id,
1576                     base_off: si.base_off,
1577                 }, SlotPlace { offset, size });
1578                 // println!("  load: offset: {}, size: {}", offset, size);
1579             }
1580             addr += imgs[0].len as u32;
1581         }
1582         RamData {
1583             places,
1584             total: addr,
1585         }
1586     }
1587 
1588     /// Lookup the ram data associated with a given flash partition.  We just panic if not present,
1589     /// because all slots used should be in the map.
lookup(&self, slot: &SlotInfo) -> &SlotPlace1590     fn lookup(&self, slot: &SlotInfo) -> &SlotPlace {
1591         self.places.get(&SlotKey{dev_id: slot.dev_id, base_off: slot.base_off})
1592             .expect("RamData should contain all slots")
1593     }
1594 }
1595 
1596 /// Show the flash layout.
1597 #[allow(dead_code)]
show_flash(flash: &dyn Flash)1598 fn show_flash(flash: &dyn Flash) {
1599     println!("---- Flash configuration ----");
1600     for sector in flash.sector_iter() {
1601         println!("    {:3}: 0x{:08x}, 0x{:08x}",
1602                  sector.num, sector.base, sector.size);
1603     }
1604     println!();
1605 }
1606 
1607 #[derive(Debug)]
1608 enum ImageSize {
1609     /// Make the image the specified given size.
1610     Given(usize),
1611     /// Make the image as large as it can be for the partition/device.
1612     Largest,
1613     /// Make the image quite larger than it can be for the partition/device/
1614     Oversized,
1615 }
1616 
1617 #[cfg(not(feature = "max-align-32"))]
tralier_estimation(dev: &dyn Flash) -> usize1618 fn tralier_estimation(dev: &dyn Flash) -> usize {
1619     c::boot_trailer_sz(dev.align() as u32) as usize
1620 }
1621 
1622 #[cfg(feature = "max-align-32")]
tralier_estimation(dev: &dyn Flash) -> usize1623 fn tralier_estimation(dev: &dyn Flash) -> usize {
1624 
1625     let sector_size = dev.sector_iter().next().unwrap().size as u32;
1626 
1627     align_up(c::boot_trailer_sz(dev.align() as u32), sector_size) as usize
1628 }
1629 
image_largest_trailer(dev: &dyn Flash) -> usize1630 fn image_largest_trailer(dev: &dyn Flash) -> usize {
1631             // Using the header size we know, the trailer size, and the slot size, we can compute
1632             // the largest image possible.
1633             let trailer = if Caps::OverwriteUpgrade.present() {
1634                 // This computation is incorrect, and we need to figure out the correct size.
1635                 // c::boot_status_sz(dev.align() as u32) as usize
1636                 16 + 4 * dev.align()
1637             } else if Caps::SwapUsingMove.present() {
1638                 let sector_size = dev.sector_iter().next().unwrap().size as u32;
1639                 align_up(c::boot_trailer_sz(dev.align() as u32), sector_size) as usize
1640             } else if Caps::SwapUsingScratch.present() {
1641                 tralier_estimation(dev)
1642             } else {
1643                 panic!("The maximum image size can't be calculated.")
1644             };
1645 
1646             trailer
1647 }
1648 
1649 /// Install a "program" into the given image.  This fakes the image header, or at least all of the
1650 /// fields used by the given code.  Returns a copy of the image that was written.
install_image(flash: &mut SimMultiFlash, slot: &SlotInfo, len: ImageSize, ram: &RamData, deps: &dyn Depender, bad_sig: bool) -> ImageData1651 fn install_image(flash: &mut SimMultiFlash, slot: &SlotInfo, len: ImageSize,
1652                  ram: &RamData,
1653                  deps: &dyn Depender, bad_sig: bool) -> ImageData {
1654     let offset = slot.base_off;
1655     let slot_len = slot.len;
1656     let dev_id = slot.dev_id;
1657     let dev = flash.get_mut(&dev_id).unwrap();
1658 
1659     let mut tlv: Box<dyn ManifestGen> = Box::new(make_tlv());
1660 
1661     // Add the dependencies early to the tlv.
1662     for dep in deps.my_deps(offset, slot.index) {
1663         tlv.add_dependency(deps.other_id(), &dep);
1664     }
1665 
1666     const HDR_SIZE: usize = 32;
1667 
1668     let place = ram.lookup(&slot);
1669     let load_addr = if Caps::RamLoad.present() {
1670         place.offset
1671     } else {
1672         0
1673     };
1674 
1675     let len = match len {
1676         ImageSize::Given(size) => size,
1677         ImageSize::Largest => {
1678             let trailer = image_largest_trailer(dev);
1679             let tlv_len = tlv.estimate_size();
1680             info!("slot: 0x{:x}, HDR: 0x{:x}, trailer: 0x{:x}",
1681                 slot_len, HDR_SIZE, trailer);
1682             slot_len - HDR_SIZE - trailer - tlv_len
1683         },
1684         ImageSize::Oversized => {
1685             let trailer = image_largest_trailer(dev);
1686             let tlv_len = tlv.estimate_size();
1687             info!("slot: 0x{:x}, HDR: 0x{:x}, trailer: 0x{:x}",
1688                 slot_len, HDR_SIZE, trailer);
1689             // the overflow size is rougly estimated to work for all
1690             // configurations. It might be precise if tlv_len will be maked precise.
1691             slot_len - HDR_SIZE - trailer - tlv_len + dev.align()*4
1692         }
1693 
1694     };
1695 
1696     // Generate a boot header.  Note that the size doesn't include the header.
1697     let header = ImageHeader {
1698         magic: tlv.get_magic(),
1699         load_addr,
1700         hdr_size: HDR_SIZE as u16,
1701         protect_tlv_size: tlv.protect_size(),
1702         img_size: len as u32,
1703         flags: tlv.get_flags(),
1704         ver: deps.my_version(offset, slot.index),
1705         _pad2: 0,
1706     };
1707 
1708     let mut b_header = [0; HDR_SIZE];
1709     b_header[..32].clone_from_slice(header.as_raw());
1710     assert_eq!(b_header.len(), HDR_SIZE);
1711 
1712     tlv.add_bytes(&b_header);
1713 
1714     // The core of the image itself is just pseudorandom data.
1715     let mut b_img = vec![0; len];
1716     splat(&mut b_img, offset);
1717 
1718     // Add some information at the start of the payload to make it easier
1719     // to see what it is.  This will fail if the image itself is too small.
1720     {
1721         let mut wr = Cursor::new(&mut b_img);
1722         writeln!(&mut wr, "offset: {:#x}, dev_id: {:#x}, slot_info: {:?}",
1723                  offset, dev_id, slot).unwrap();
1724         writeln!(&mut wr, "version: {:?}", deps.my_version(offset, slot.index)).unwrap();
1725     }
1726 
1727     // TLV signatures work over plain image
1728     tlv.add_bytes(&b_img);
1729 
1730     // Generate encrypted images
1731     let flag = TlvFlags::ENCRYPTED_AES128 as u32 | TlvFlags::ENCRYPTED_AES256 as u32;
1732     let is_encrypted = (tlv.get_flags() & flag) != 0;
1733     let mut b_encimg = vec![];
1734     if is_encrypted {
1735         let flag = TlvFlags::ENCRYPTED_AES256 as u32;
1736         let aes256 = (tlv.get_flags() & flag) == flag;
1737         tlv.generate_enc_key();
1738         let enc_key = tlv.get_enc_key();
1739         let nonce = GenericArray::from_slice(&[0; 16]);
1740         b_encimg = b_img.clone();
1741         if aes256 {
1742             let key: &GenericArray<u8, U32> = GenericArray::from_slice(enc_key.as_slice());
1743             let block = Aes256::new(&key);
1744             let mut cipher = Aes256Ctr::from_block_cipher(block, &nonce);
1745             cipher.apply_keystream(&mut b_encimg);
1746         } else {
1747             let key: &GenericArray<u8, U16> = GenericArray::from_slice(enc_key.as_slice());
1748             let block = Aes128::new(&key);
1749             let mut cipher = Aes128Ctr::from_block_cipher(block, &nonce);
1750             cipher.apply_keystream(&mut b_encimg);
1751         }
1752     }
1753 
1754     // Build the TLV itself.
1755     if bad_sig {
1756         tlv.corrupt_sig();
1757     }
1758     let mut b_tlv = tlv.make_tlv();
1759 
1760     let mut buf = vec![];
1761     buf.append(&mut b_header.to_vec());
1762     buf.append(&mut b_img);
1763     buf.append(&mut b_tlv.clone());
1764 
1765     // Pad the buffer to a multiple of the flash alignment.
1766     let align = dev.align();
1767     let image_sz = buf.len();
1768     while buf.len() % align != 0 {
1769         buf.push(dev.erased_val());
1770     }
1771 
1772     let mut encbuf = vec![];
1773     if is_encrypted {
1774         encbuf.append(&mut b_header.to_vec());
1775         encbuf.append(&mut b_encimg);
1776         encbuf.append(&mut b_tlv);
1777 
1778         while encbuf.len() % align != 0 {
1779             encbuf.push(dev.erased_val());
1780         }
1781     }
1782 
1783     // Since images are always non-encrypted in the primary slot, we first write
1784     // an encrypted image, re-read to use for verification, erase + flash
1785     // un-encrypted. In the secondary slot the image is written un-encrypted,
1786     // and if encryption is requested, it follows an erase + flash encrypted.
1787 
1788     if slot.index == 0 {
1789         let enc_copy: Option<Vec<u8>>;
1790 
1791         if is_encrypted {
1792             dev.write(offset, &encbuf).unwrap();
1793 
1794             let mut enc = vec![0u8; encbuf.len()];
1795             dev.read(offset, &mut enc).unwrap();
1796 
1797             enc_copy = Some(enc);
1798 
1799             dev.erase(offset, slot_len).unwrap();
1800         } else {
1801             enc_copy = None;
1802         }
1803 
1804         dev.write(offset, &buf).unwrap();
1805 
1806         let mut copy = vec![0u8; buf.len()];
1807         dev.read(offset, &mut copy).unwrap();
1808 
1809         ImageData {
1810             size: image_sz,
1811             plain: copy,
1812             cipher: enc_copy,
1813         }
1814     } else {
1815 
1816         dev.write(offset, &buf).unwrap();
1817 
1818         let mut copy = vec![0u8; buf.len()];
1819         dev.read(offset, &mut copy).unwrap();
1820 
1821         let enc_copy: Option<Vec<u8>>;
1822 
1823         if is_encrypted {
1824             dev.erase(offset, slot_len).unwrap();
1825 
1826             dev.write(offset, &encbuf).unwrap();
1827 
1828             let mut enc = vec![0u8; encbuf.len()];
1829             dev.read(offset, &mut enc).unwrap();
1830 
1831             enc_copy = Some(enc);
1832         } else {
1833             enc_copy = None;
1834         }
1835 
1836         ImageData {
1837             size: image_sz,
1838             plain: copy,
1839             cipher: enc_copy,
1840         }
1841     }
1842 }
1843 
1844 /// Install no image.  This is used when no upgrade happens.
install_no_image() -> ImageData1845 fn install_no_image() -> ImageData {
1846     ImageData {
1847         size: 0,
1848         plain: vec![],
1849         cipher: None,
1850     }
1851 }
1852 
1853 /// Construct a TLV generator based on how MCUboot is currently configured.  The returned
1854 /// ManifestGen will generate the appropriate entries based on this configuration.
make_tlv() -> TlvGen1855 fn make_tlv() -> TlvGen {
1856     let aes_key_size = if Caps::Aes256.present() { 256 } else { 128 };
1857 
1858     if Caps::EncKw.present() {
1859         if Caps::RSA2048.present() {
1860             TlvGen::new_rsa_kw(aes_key_size)
1861         } else if Caps::EcdsaP256.present() {
1862             TlvGen::new_ecdsa_kw(aes_key_size)
1863         } else {
1864             TlvGen::new_enc_kw(aes_key_size)
1865         }
1866     } else if Caps::EncRsa.present() {
1867         if Caps::RSA2048.present() {
1868             TlvGen::new_sig_enc_rsa(aes_key_size)
1869         } else {
1870             TlvGen::new_enc_rsa(aes_key_size)
1871         }
1872     } else if Caps::EncEc256.present() {
1873         if Caps::EcdsaP256.present() {
1874             TlvGen::new_ecdsa_ecies_p256(aes_key_size)
1875         } else {
1876             TlvGen::new_ecies_p256(aes_key_size)
1877         }
1878     } else if Caps::EncX25519.present() {
1879         if Caps::Ed25519.present() {
1880             TlvGen::new_ed25519_ecies_x25519(aes_key_size)
1881         } else {
1882             TlvGen::new_ecies_x25519(aes_key_size)
1883         }
1884     } else {
1885         // The non-encrypted configuration.
1886         if Caps::RSA2048.present() {
1887             TlvGen::new_rsa_pss()
1888         } else if Caps::RSA3072.present() {
1889             TlvGen::new_rsa3072_pss()
1890         } else if Caps::EcdsaP256.present() {
1891             TlvGen::new_ecdsa()
1892         } else if Caps::Ed25519.present() {
1893             TlvGen::new_ed25519()
1894         } else {
1895             TlvGen::new_hash_only()
1896         }
1897     }
1898 }
1899 
1900 impl ImageData {
1901     /// Find the image contents for the given slot.  This assumes that slot 0
1902     /// is unencrypted, and slot 1 is encrypted.
find(&self, slot: usize) -> &Vec<u8>1903     fn find(&self, slot: usize) -> &Vec<u8> {
1904         let encrypted = Caps::EncRsa.present() || Caps::EncKw.present() ||
1905             Caps::EncEc256.present() || Caps::EncX25519.present();
1906         match (encrypted, slot) {
1907             (false, _) => &self.plain,
1908             (true, 0) => &self.plain,
1909             (true, 1) => self.cipher.as_ref().expect("Invalid image"),
1910             _ => panic!("Invalid slot requested"),
1911         }
1912     }
1913 
size(&self) -> usize1914     fn size(&self) -> usize {
1915         self.size
1916     }
1917 }
1918 
1919 /// Verify that given image is present in the flash at the given offset.
verify_image(flash: &SimMultiFlash, slot: &SlotInfo, images: &ImageData) -> bool1920 fn verify_image(flash: &SimMultiFlash, slot: &SlotInfo, images: &ImageData) -> bool {
1921     let image = images.find(slot.index);
1922     let buf = image.as_slice();
1923     let dev_id = slot.dev_id;
1924 
1925     let mut copy = vec![0u8; buf.len()];
1926     let offset = slot.base_off;
1927     let dev = flash.get(&dev_id).unwrap();
1928     dev.read(offset, &mut copy).unwrap();
1929 
1930     if buf != &copy[..] {
1931         for i in 0 .. buf.len() {
1932             if buf[i] != copy[i] {
1933                 info!("First failure for slot{} at {:#x} ({:#x} within) {:#x}!={:#x}",
1934                       slot.index, offset + i, i, buf[i], copy[i]);
1935                 break;
1936             }
1937         }
1938         false
1939     } else {
1940         true
1941     }
1942 }
1943 
verify_trailer(flash: &SimMultiFlash, slot: &SlotInfo, magic: Option<u8>, image_ok: Option<u8>, copy_done: Option<u8>) -> bool1944 fn verify_trailer(flash: &SimMultiFlash, slot: &SlotInfo,
1945                   magic: Option<u8>, image_ok: Option<u8>,
1946                   copy_done: Option<u8>) -> bool {
1947     if Caps::OverwriteUpgrade.present() {
1948         return true;
1949     }
1950 
1951     let offset = slot.trailer_off + c::boot_max_align();
1952     let dev_id = slot.dev_id;
1953     let mut copy = vec![0u8; c::boot_magic_sz() + c::boot_max_align() * 3];
1954     let mut failed = false;
1955 
1956     let dev = flash.get(&dev_id).unwrap();
1957     let erased_val = dev.erased_val();
1958     dev.read(offset, &mut copy).unwrap();
1959 
1960     failed |= match magic {
1961         Some(v) => {
1962             let magic_off = (c::boot_max_align() * 3) + (c::boot_magic_sz() - MAGIC.len());
1963             if v == 1 && &copy[magic_off..] != MAGIC {
1964                 warn!("\"magic\" mismatch at {:#x}", offset);
1965                 true
1966             } else if v == 3 {
1967                 let expected = [erased_val; 16];
1968                 if copy[magic_off..] != expected {
1969                     warn!("\"magic\" mismatch at {:#x}", offset);
1970                     true
1971                 } else {
1972                     false
1973                 }
1974             } else {
1975                 false
1976             }
1977         },
1978         None => false,
1979     };
1980 
1981     failed |= match image_ok {
1982         Some(v) => {
1983             let image_ok_off = c::boot_max_align() * 2;
1984             if (v == 1 && copy[image_ok_off] != v) || (v == 3 && copy[image_ok_off] != erased_val) {
1985                 warn!("\"image_ok\" mismatch at {:#x} v={} val={:#x}", offset, v, copy[image_ok_off]);
1986                 true
1987             } else {
1988                 false
1989             }
1990         },
1991         None => false,
1992     };
1993 
1994     failed |= match copy_done {
1995         Some(v) => {
1996             let copy_done_off = c::boot_max_align();
1997             if (v == 1 && copy[copy_done_off] != v) || (v == 3 && copy[copy_done_off] != erased_val) {
1998                 warn!("\"copy_done\" mismatch at {:#x} v={} val={:#x}", offset, v, copy[copy_done_off]);
1999                 true
2000             } else {
2001                 false
2002             }
2003         },
2004         None => false,
2005     };
2006 
2007     !failed
2008 }
2009 
2010 /// Install a partition table.  This is a simplified partition table that
2011 /// we write at the beginning of flash so make it easier for external tools
2012 /// to analyze these images.
install_ptable(flash: &mut SimMultiFlash, areadesc: &AreaDesc)2013 fn install_ptable(flash: &mut SimMultiFlash, areadesc: &AreaDesc) {
2014     let ids: HashSet<u8> = areadesc.iter_areas().map(|area| area.device_id).collect();
2015     for &id in &ids {
2016         // If there are any partitions in this device that start at 0, and
2017         // aren't marked as the BootLoader partition, avoid adding the
2018         // partition table.  This makes it harder to view the image, but
2019         // avoids messing up images already written.
2020         let skip_ptable = areadesc
2021             .iter_areas()
2022             .any(|area| {
2023                 area.device_id == id &&
2024                     area.off == 0 &&
2025                     area.flash_id != FlashId::BootLoader
2026             });
2027         if skip_ptable {
2028             if log_enabled!(Info) {
2029                 let special: Vec<FlashId> = areadesc.iter_areas()
2030                     .filter(|area| area.device_id == id && area.off == 0)
2031                     .map(|area| area.flash_id)
2032                     .collect();
2033                 info!("Skipping partition table: {:?}", special);
2034             }
2035             break;
2036         }
2037 
2038         let mut buf: Vec<u8> = vec![];
2039         write!(&mut buf, "mcuboot\0").unwrap();
2040 
2041         // Iterate through all of the partitions in that device, and encode
2042         // into the table.
2043         let count = areadesc.iter_areas().filter(|area| area.device_id == id).count();
2044         buf.write_u32::<LittleEndian>(count as u32).unwrap();
2045 
2046         for area in areadesc.iter_areas().filter(|area| area.device_id == id) {
2047             buf.write_u32::<LittleEndian>(area.flash_id as u32).unwrap();
2048             buf.write_u32::<LittleEndian>(area.off).unwrap();
2049             buf.write_u32::<LittleEndian>(area.size).unwrap();
2050             buf.write_u32::<LittleEndian>(0).unwrap();
2051         }
2052 
2053         let dev = flash.get_mut(&id).unwrap();
2054 
2055         // Pad to alignment.
2056         while buf.len() % dev.align() != 0 {
2057             buf.push(0);
2058         }
2059 
2060         dev.write(0, &buf).unwrap();
2061     }
2062 }
2063 
2064 /// The image header
2065 #[repr(C)]
2066 #[derive(Debug)]
2067 pub struct ImageHeader {
2068     magic: u32,
2069     load_addr: u32,
2070     hdr_size: u16,
2071     protect_tlv_size: u16,
2072     img_size: u32,
2073     flags: u32,
2074     ver: ImageVersion,
2075     _pad2: u32,
2076 }
2077 
2078 impl AsRaw for ImageHeader {}
2079 
2080 #[repr(C)]
2081 #[derive(Clone, Debug)]
2082 pub struct ImageVersion {
2083     pub major: u8,
2084     pub minor: u8,
2085     pub revision: u16,
2086     pub build_num: u32,
2087 }
2088 
2089 #[derive(Clone, Debug)]
2090 pub struct SlotInfo {
2091     pub base_off: usize,
2092     pub trailer_off: usize,
2093     pub len: usize,
2094     // Which slot within this device.
2095     pub index: usize,
2096     pub dev_id: u8,
2097 }
2098 
2099 #[cfg(not(feature = "max-align-32"))]
2100 const MAGIC: &[u8] = &[0x77, 0xc2, 0x95, 0xf3,
2101                        0x60, 0xd2, 0xef, 0x7f,
2102                        0x35, 0x52, 0x50, 0x0f,
2103                        0x2c, 0xb6, 0x79, 0x80];
2104 
2105 #[cfg(feature = "max-align-32")]
2106 const MAGIC: &[u8] = &[0x20, 0x00, 0x2d, 0xe1,
2107                        0x5d, 0x29, 0x41, 0x0b,
2108                        0x8d, 0x77, 0x67, 0x9c,
2109                        0x11, 0x0f, 0x1f, 0x8a];
2110 
2111 // Replicates defines found in bootutil.h
2112 const BOOT_MAGIC_GOOD: Option<u8> = Some(1);
2113 const BOOT_MAGIC_UNSET: Option<u8> = Some(3);
2114 
2115 const BOOT_FLAG_SET: Option<u8> = Some(1);
2116 const BOOT_FLAG_UNSET: Option<u8> = Some(3);
2117 
2118 /// Write out the magic so that the loader tries doing an upgrade.
mark_upgrade(flash: &mut SimMultiFlash, slot: &SlotInfo)2119 pub fn mark_upgrade(flash: &mut SimMultiFlash, slot: &SlotInfo) {
2120     let dev = flash.get_mut(&slot.dev_id).unwrap();
2121     let align = dev.align();
2122     let offset = slot.trailer_off + c::boot_max_align() * 4;
2123     if offset % align != 0 || MAGIC.len() % align != 0 {
2124         // The write size is larger than the magic value.  Fill a buffer
2125         // with the erased value, put the MAGIC in it, and write it in its
2126         // entirety.
2127         let mut buf = vec![dev.erased_val(); c::boot_max_align()];
2128         let magic_off = (offset % align) + (c::boot_magic_sz() - MAGIC.len());
2129         buf[magic_off..].copy_from_slice(MAGIC);
2130         dev.write(offset - (offset % align), &buf).unwrap();
2131     } else {
2132         dev.write(offset, MAGIC).unwrap();
2133     }
2134 }
2135 
2136 /// Writes the image_ok flag which, guess what, tells the bootloader
2137 /// the this image is ok (not a test, and no revert is to be performed).
mark_permanent_upgrade(flash: &mut SimMultiFlash, slot: &SlotInfo)2138 fn mark_permanent_upgrade(flash: &mut SimMultiFlash, slot: &SlotInfo) {
2139     // Overwrite mode always is permanent, and only the magic is used in
2140     // the trailer.  To avoid problems with large write sizes, don't try to
2141     // set anything in this case.
2142     if Caps::OverwriteUpgrade.present() {
2143         return;
2144     }
2145 
2146     let dev = flash.get_mut(&slot.dev_id).unwrap();
2147     let align = dev.align();
2148     let mut ok = vec![dev.erased_val(); align];
2149     ok[0] = 1u8;
2150     let off = slot.trailer_off + c::boot_max_align() * 3;
2151     dev.write(off, &ok).unwrap();
2152 }
2153 
2154 // Drop some pseudo-random gibberish onto the data.
splat(data: &mut [u8], seed: usize)2155 fn splat(data: &mut [u8], seed: usize) {
2156     let mut seed_block = [0u8; 32];
2157     let mut buf = Cursor::new(&mut seed_block[..]);
2158     buf.write_u32::<LittleEndian>(0x135782ea).unwrap();
2159     buf.write_u32::<LittleEndian>(0x92184728).unwrap();
2160     buf.write_u32::<LittleEndian>(data.len() as u32).unwrap();
2161     buf.write_u32::<LittleEndian>(seed as u32).unwrap();
2162     let mut rng: SmallRng = SeedableRng::from_seed(seed_block);
2163     rng.fill_bytes(data);
2164 }
2165 
2166 /// Return a read-only view into the raw bytes of this object
2167 trait AsRaw : Sized {
as_raw(&self) -> &[u8]2168     fn as_raw(&self) -> &[u8] {
2169         unsafe { slice::from_raw_parts(self as *const _ as *const u8,
2170                                        mem::size_of::<Self>()) }
2171     }
2172 }
2173 
2174 /// Determine whether it makes sense to test this configuration with a maximally-sized image.
2175 /// Returns an ImageSize representing the best size to test, possibly just with the given size.
maximal(size: usize) -> ImageSize2176 fn maximal(size: usize) -> ImageSize {
2177     if Caps::OverwriteUpgrade.present() ||
2178         Caps::SwapUsingMove.present()
2179     {
2180         ImageSize::Given(size)
2181     } else {
2182         ImageSize::Largest
2183     }
2184 }
2185 
show_sizes()2186 pub fn show_sizes() {
2187     // This isn't panic safe.
2188     for min in &[1, 2, 4, 8] {
2189         let msize = c::boot_trailer_sz(*min);
2190         println!("{:2}: {} (0x{:x})", min, msize, msize);
2191     }
2192 }
2193 
2194 #[cfg(not(feature = "max-align-32"))]
test_alignments() -> &'static [usize]2195 fn test_alignments() -> &'static [usize] {
2196     &[1, 2, 4, 8]
2197 }
2198 
2199 #[cfg(feature = "max-align-32")]
test_alignments() -> &'static [usize]2200 fn test_alignments() -> &'static [usize] {
2201     &[32]
2202 }
2203