blob: 58f5c59fe9dc948022c3becaad751e62fef2bb23 [file] [log] [blame]
David Brown2639e072017-10-11 11:18:44 -06001use docopt::Docopt;
David Brown5c9e0f12019-01-09 16:34:33 -07002use log::{warn, error};
David Brown10b5de12019-01-02 16:10:01 -07003use std::{
4 fmt,
David Brown10b5de12019-01-02 16:10:01 -07005 process,
David Brown10b5de12019-01-02 16:10:01 -07006};
7use serde_derive::Deserialize;
David Brown2639e072017-10-11 11:18:44 -06008
9mod caps;
David Brown5c9e0f12019-01-09 16:34:33 -070010mod image;
David Brown2639e072017-10-11 11:18:44 -060011mod tlv;
David Brownca7b5d32017-11-03 08:37:38 -060012pub mod testlog;
David Brown2639e072017-10-11 11:18:44 -060013
David Browne5133242019-02-28 11:05:19 -070014pub use crate::image::{
15 ImagesBuilder,
David Brown5c9e0f12019-01-09 16:34:33 -070016 show_sizes,
17};
David Brown2639e072017-10-11 11:18:44 -060018
19const USAGE: &'static str = "
20Mcuboot simulator
21
22Usage:
23 bootsim sizes
24 bootsim run --device TYPE [--align SIZE]
25 bootsim runall
26 bootsim (--help | --version)
27
28Options:
29 -h, --help Show this message
30 --version Version
31 --device TYPE MCU to simulate
32 Valid values: stm32f4, k64f
33 --align SIZE Flash write alignment
34";
35
36#[derive(Debug, Deserialize)]
37struct Args {
38 flag_help: bool,
39 flag_version: bool,
40 flag_device: Option<DeviceName>,
41 flag_align: Option<AlignArg>,
42 cmd_sizes: bool,
43 cmd_run: bool,
44 cmd_runall: bool,
45}
46
47#[derive(Copy, Clone, Debug, Deserialize)]
Fabio Utzigafb2bc92018-11-19 16:11:52 -020048pub enum DeviceName { Stm32f4, K64f, K64fBig, Nrf52840, Nrf52840SpiFlash, }
David Brown2639e072017-10-11 11:18:44 -060049
David Browndd2b1182017-11-02 15:39:21 -060050pub static ALL_DEVICES: &'static [DeviceName] = &[
David Brown2639e072017-10-11 11:18:44 -060051 DeviceName::Stm32f4,
52 DeviceName::K64f,
53 DeviceName::K64fBig,
54 DeviceName::Nrf52840,
Fabio Utzigafb2bc92018-11-19 16:11:52 -020055 DeviceName::Nrf52840SpiFlash,
David Brown2639e072017-10-11 11:18:44 -060056];
57
58impl fmt::Display for DeviceName {
David Brown10b5de12019-01-02 16:10:01 -070059 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
David Brown2639e072017-10-11 11:18:44 -060060 let name = match *self {
61 DeviceName::Stm32f4 => "stm32f4",
62 DeviceName::K64f => "k64f",
63 DeviceName::K64fBig => "k64fbig",
64 DeviceName::Nrf52840 => "nrf52840",
Fabio Utzigafb2bc92018-11-19 16:11:52 -020065 DeviceName::Nrf52840SpiFlash => "Nrf52840SpiFlash",
David Brown2639e072017-10-11 11:18:44 -060066 };
67 f.write_str(name)
68 }
69}
70
71#[derive(Debug)]
72struct AlignArg(u8);
73
74struct AlignArgVisitor;
75
76impl<'de> serde::de::Visitor<'de> for AlignArgVisitor {
77 type Value = AlignArg;
78
David Brown10b5de12019-01-02 16:10:01 -070079 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
David Brown2639e072017-10-11 11:18:44 -060080 formatter.write_str("1, 2, 4 or 8")
81 }
82
83 fn visit_u8<E>(self, n: u8) -> Result<Self::Value, E>
84 where E: serde::de::Error
85 {
86 Ok(match n {
87 1 | 2 | 4 | 8 => AlignArg(n),
88 n => {
89 let err = format!("Could not deserialize '{}' as alignment", n);
90 return Err(E::custom(err));
91 }
92 })
93 }
94}
95
96impl<'de> serde::de::Deserialize<'de> for AlignArg {
97 fn deserialize<D>(d: D) -> Result<AlignArg, D::Error>
98 where D: serde::de::Deserializer<'de>
99 {
100 d.deserialize_u8(AlignArgVisitor)
101 }
102}
103
104pub fn main() {
105 let args: Args = Docopt::new(USAGE)
106 .and_then(|d| d.deserialize())
107 .unwrap_or_else(|e| e.exit());
108 // println!("args: {:#?}", args);
109
110 if args.cmd_sizes {
111 show_sizes();
112 return;
113 }
114
115 let mut status = RunStatus::new();
116 if args.cmd_run {
117
118 let align = args.flag_align.map(|x| x.0).unwrap_or(1);
119
120
121 let device = match args.flag_device {
122 None => panic!("Missing mandatory device argument"),
123 Some(dev) => dev,
124 };
125
Fabio Utzigea0290b2018-08-09 14:23:01 -0300126 status.run_single(device, align, 0xff);
David Brown2639e072017-10-11 11:18:44 -0600127 }
128
129 if args.cmd_runall {
130 for &dev in ALL_DEVICES {
131 for &align in &[1, 2, 4, 8] {
Fabio Utzigea0290b2018-08-09 14:23:01 -0300132 for &erased_val in &[0, 0xff] {
133 status.run_single(dev, align, erased_val);
134 }
David Brown2639e072017-10-11 11:18:44 -0600135 }
136 }
137 }
138
139 if status.failures > 0 {
140 error!("{} Tests ran with {} failures", status.failures + status.passes, status.failures);
141 process::exit(1);
142 } else {
143 error!("{} Tests ran successfully", status.passes);
144 process::exit(0);
145 }
146}
147
David Browndd2b1182017-11-02 15:39:21 -0600148pub struct RunStatus {
David Brown2639e072017-10-11 11:18:44 -0600149 failures: usize,
150 passes: usize,
151}
152
153impl RunStatus {
David Browndd2b1182017-11-02 15:39:21 -0600154 pub fn new() -> RunStatus {
David Brown2639e072017-10-11 11:18:44 -0600155 RunStatus {
156 failures: 0,
157 passes: 0,
158 }
159 }
160
Fabio Utzigea0290b2018-08-09 14:23:01 -0300161 pub fn run_single(&mut self, device: DeviceName, align: u8, erased_val: u8) {
David Brown2639e072017-10-11 11:18:44 -0600162 warn!("Running on device {} with alignment {}", device, align);
163
David Browne5133242019-02-28 11:05:19 -0700164 let run = ImagesBuilder::new(device, align, erased_val);
David Brown2639e072017-10-11 11:18:44 -0600165
David Brown2639e072017-10-11 11:18:44 -0600166 let mut failed = false;
167
David Vincze2d736ad2019-02-18 11:50:22 +0100168 // Creates a badly signed image in the secondary slot to check that
169 // it is not upgraded to
David Brown01617af2019-02-28 10:45:12 -0700170 let bad_secondary_slot_image = run.clone().make_bad_secondary_slot_image();
David Brown2639e072017-10-11 11:18:44 -0600171
David Vincze2d736ad2019-02-18 11:50:22 +0100172 failed |= bad_secondary_slot_image.run_signfail_upgrade();
David Brown2639e072017-10-11 11:18:44 -0600173
David Brown01617af2019-02-28 10:45:12 -0700174 let images = run.clone().make_no_upgrade_image();
David Brown5f7ec2b2017-11-06 13:54:02 -0700175 failed |= images.run_norevert_newimage();
David Brown2639e072017-10-11 11:18:44 -0600176
David Brownf48b9502017-11-06 14:00:26 -0700177 let images = run.make_image();
David Brown2639e072017-10-11 11:18:44 -0600178
David Brown5f7ec2b2017-11-06 13:54:02 -0700179 failed |= images.run_basic_revert();
David Brownc49811e2017-11-06 14:20:45 -0700180 failed |= images.run_revert_with_fails();
181 failed |= images.run_perm_with_fails();
182 failed |= images.run_perm_with_random_fails(5);
David Brown5f7ec2b2017-11-06 13:54:02 -0700183 failed |= images.run_norevert();
David Brown2639e072017-10-11 11:18:44 -0600184
Fabio Utzigb841f0a2017-11-24 08:11:05 -0200185 failed |= images.run_with_status_fails_complete();
Fabio Utzigeedcc452017-11-24 10:48:52 -0200186 failed |= images.run_with_status_fails_with_reset();
Fabio Utzigb841f0a2017-11-24 08:11:05 -0200187
David Brown2639e072017-10-11 11:18:44 -0600188 //show_flash(&flash);
189
190 if failed {
191 self.failures += 1;
192 } else {
193 self.passes += 1;
194 }
195 }
David Browndd2b1182017-11-02 15:39:21 -0600196
197 pub fn failures(&self) -> usize {
198 self.failures
199 }
David Brown2639e072017-10-11 11:18:44 -0600200}
201