blob: 177871327627fe015ce3f99a3ad53c10a533faad [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)]
David Brown2bff6472019-03-05 13:58:35 -070048pub enum DeviceName { Stm32f4, K64f, K64fBig, K64fMulti, 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,
David Brown2bff6472019-03-05 13:58:35 -070054 DeviceName::K64fMulti,
David Brown2639e072017-10-11 11:18:44 -060055 DeviceName::Nrf52840,
Fabio Utzigafb2bc92018-11-19 16:11:52 -020056 DeviceName::Nrf52840SpiFlash,
David Brown2639e072017-10-11 11:18:44 -060057];
58
59impl fmt::Display for DeviceName {
David Brown10b5de12019-01-02 16:10:01 -070060 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
David Brown2639e072017-10-11 11:18:44 -060061 let name = match *self {
62 DeviceName::Stm32f4 => "stm32f4",
63 DeviceName::K64f => "k64f",
64 DeviceName::K64fBig => "k64fbig",
David Brown2bff6472019-03-05 13:58:35 -070065 DeviceName::K64fMulti => "k64fmulti",
David Brown2639e072017-10-11 11:18:44 -060066 DeviceName::Nrf52840 => "nrf52840",
Fabio Utzigafb2bc92018-11-19 16:11:52 -020067 DeviceName::Nrf52840SpiFlash => "Nrf52840SpiFlash",
David Brown2639e072017-10-11 11:18:44 -060068 };
69 f.write_str(name)
70 }
71}
72
73#[derive(Debug)]
74struct AlignArg(u8);
75
76struct AlignArgVisitor;
77
78impl<'de> serde::de::Visitor<'de> for AlignArgVisitor {
79 type Value = AlignArg;
80
David Brown10b5de12019-01-02 16:10:01 -070081 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
David Brown2639e072017-10-11 11:18:44 -060082 formatter.write_str("1, 2, 4 or 8")
83 }
84
85 fn visit_u8<E>(self, n: u8) -> Result<Self::Value, E>
86 where E: serde::de::Error
87 {
88 Ok(match n {
89 1 | 2 | 4 | 8 => AlignArg(n),
90 n => {
91 let err = format!("Could not deserialize '{}' as alignment", n);
92 return Err(E::custom(err));
93 }
94 })
95 }
96}
97
98impl<'de> serde::de::Deserialize<'de> for AlignArg {
99 fn deserialize<D>(d: D) -> Result<AlignArg, D::Error>
100 where D: serde::de::Deserializer<'de>
101 {
102 d.deserialize_u8(AlignArgVisitor)
103 }
104}
105
106pub fn main() {
107 let args: Args = Docopt::new(USAGE)
108 .and_then(|d| d.deserialize())
109 .unwrap_or_else(|e| e.exit());
110 // println!("args: {:#?}", args);
111
112 if args.cmd_sizes {
113 show_sizes();
114 return;
115 }
116
117 let mut status = RunStatus::new();
118 if args.cmd_run {
119
120 let align = args.flag_align.map(|x| x.0).unwrap_or(1);
121
122
123 let device = match args.flag_device {
124 None => panic!("Missing mandatory device argument"),
125 Some(dev) => dev,
126 };
127
Fabio Utzigea0290b2018-08-09 14:23:01 -0300128 status.run_single(device, align, 0xff);
David Brown2639e072017-10-11 11:18:44 -0600129 }
130
131 if args.cmd_runall {
132 for &dev in ALL_DEVICES {
133 for &align in &[1, 2, 4, 8] {
Fabio Utzigea0290b2018-08-09 14:23:01 -0300134 for &erased_val in &[0, 0xff] {
135 status.run_single(dev, align, erased_val);
136 }
David Brown2639e072017-10-11 11:18:44 -0600137 }
138 }
139 }
140
141 if status.failures > 0 {
142 error!("{} Tests ran with {} failures", status.failures + status.passes, status.failures);
143 process::exit(1);
144 } else {
145 error!("{} Tests ran successfully", status.passes);
146 process::exit(0);
147 }
148}
149
David Browndd2b1182017-11-02 15:39:21 -0600150pub struct RunStatus {
David Brown2639e072017-10-11 11:18:44 -0600151 failures: usize,
152 passes: usize,
153}
154
155impl RunStatus {
David Browndd2b1182017-11-02 15:39:21 -0600156 pub fn new() -> RunStatus {
David Brown2639e072017-10-11 11:18:44 -0600157 RunStatus {
158 failures: 0,
159 passes: 0,
160 }
161 }
162
Fabio Utzigea0290b2018-08-09 14:23:01 -0300163 pub fn run_single(&mut self, device: DeviceName, align: u8, erased_val: u8) {
David Brown2639e072017-10-11 11:18:44 -0600164 warn!("Running on device {} with alignment {}", device, align);
165
David Brown5bc62c62019-03-05 12:11:48 -0700166 let run = match ImagesBuilder::new(device, align, erased_val) {
167 Some(builder) => builder,
168 None => {
169 warn!("Skipping device with insuffienct partitions");
170 return;
171 }
172 };
David Brown2639e072017-10-11 11:18:44 -0600173
David Brown2639e072017-10-11 11:18:44 -0600174 let mut failed = false;
175
David Vincze2d736ad2019-02-18 11:50:22 +0100176 // Creates a badly signed image in the secondary slot to check that
177 // it is not upgraded to
David Brown01617af2019-02-28 10:45:12 -0700178 let bad_secondary_slot_image = run.clone().make_bad_secondary_slot_image();
David Brown2639e072017-10-11 11:18:44 -0600179
David Vincze2d736ad2019-02-18 11:50:22 +0100180 failed |= bad_secondary_slot_image.run_signfail_upgrade();
David Brown2639e072017-10-11 11:18:44 -0600181
David Brown01617af2019-02-28 10:45:12 -0700182 let images = run.clone().make_no_upgrade_image();
David Brown5f7ec2b2017-11-06 13:54:02 -0700183 failed |= images.run_norevert_newimage();
David Brown2639e072017-10-11 11:18:44 -0600184
David Brownf48b9502017-11-06 14:00:26 -0700185 let images = run.make_image();
David Brown2639e072017-10-11 11:18:44 -0600186
David Brown5f7ec2b2017-11-06 13:54:02 -0700187 failed |= images.run_basic_revert();
David Brownc49811e2017-11-06 14:20:45 -0700188 failed |= images.run_revert_with_fails();
189 failed |= images.run_perm_with_fails();
190 failed |= images.run_perm_with_random_fails(5);
David Brown5f7ec2b2017-11-06 13:54:02 -0700191 failed |= images.run_norevert();
David Brown2639e072017-10-11 11:18:44 -0600192
Fabio Utzigb841f0a2017-11-24 08:11:05 -0200193 failed |= images.run_with_status_fails_complete();
Fabio Utzigeedcc452017-11-24 10:48:52 -0200194 failed |= images.run_with_status_fails_with_reset();
Fabio Utzigb841f0a2017-11-24 08:11:05 -0200195
David Brown2639e072017-10-11 11:18:44 -0600196 //show_flash(&flash);
197
198 if failed {
199 self.failures += 1;
200 } else {
201 self.passes += 1;
202 }
203 }
David Browndd2b1182017-11-02 15:39:21 -0600204
205 pub fn failures(&self) -> usize {
206 self.failures
207 }
David Brown2639e072017-10-11 11:18:44 -0600208}
209