blob: fda376afcfefa6b485a038410e61734c67c58196 [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 Brownc3898d62019-08-05 14:20:02 -060010mod depends;
David Brown5c9e0f12019-01-09 16:34:33 -070011mod image;
David Brown2639e072017-10-11 11:18:44 -060012mod tlv;
David Brownca7b5d32017-11-03 08:37:38 -060013pub mod testlog;
David Brown2639e072017-10-11 11:18:44 -060014
David Brownc3898d62019-08-05 14:20:02 -060015pub use crate::{
16 depends::{
17 DepTest,
18 DepType,
19 UpgradeInfo,
20 NO_DEPS,},
21 image::{
22 ImagesBuilder,
David Brownfe5ab1c2019-08-13 15:35:23 -060023 Images,
David Brownc3898d62019-08-05 14:20:02 -060024 show_sizes,
25 },
David Brown5c9e0f12019-01-09 16:34:33 -070026};
David Brown2639e072017-10-11 11:18:44 -060027
28const USAGE: &'static str = "
29Mcuboot simulator
30
31Usage:
32 bootsim sizes
33 bootsim run --device TYPE [--align SIZE]
34 bootsim runall
35 bootsim (--help | --version)
36
37Options:
38 -h, --help Show this message
39 --version Version
40 --device TYPE MCU to simulate
41 Valid values: stm32f4, k64f
42 --align SIZE Flash write alignment
43";
44
45#[derive(Debug, Deserialize)]
46struct Args {
47 flag_help: bool,
48 flag_version: bool,
49 flag_device: Option<DeviceName>,
50 flag_align: Option<AlignArg>,
51 cmd_sizes: bool,
52 cmd_run: bool,
53 cmd_runall: bool,
54}
55
56#[derive(Copy, Clone, Debug, Deserialize)]
David Brown2bff6472019-03-05 13:58:35 -070057pub enum DeviceName { Stm32f4, K64f, K64fBig, K64fMulti, Nrf52840, Nrf52840SpiFlash, }
David Brown2639e072017-10-11 11:18:44 -060058
David Browndd2b1182017-11-02 15:39:21 -060059pub static ALL_DEVICES: &'static [DeviceName] = &[
David Brown2639e072017-10-11 11:18:44 -060060 DeviceName::Stm32f4,
61 DeviceName::K64f,
62 DeviceName::K64fBig,
David Brown2bff6472019-03-05 13:58:35 -070063 DeviceName::K64fMulti,
David Brown2639e072017-10-11 11:18:44 -060064 DeviceName::Nrf52840,
Fabio Utzigafb2bc92018-11-19 16:11:52 -020065 DeviceName::Nrf52840SpiFlash,
David Brown2639e072017-10-11 11:18:44 -060066];
67
68impl fmt::Display for DeviceName {
David Brown10b5de12019-01-02 16:10:01 -070069 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
David Brown2639e072017-10-11 11:18:44 -060070 let name = match *self {
71 DeviceName::Stm32f4 => "stm32f4",
72 DeviceName::K64f => "k64f",
73 DeviceName::K64fBig => "k64fbig",
David Brown2bff6472019-03-05 13:58:35 -070074 DeviceName::K64fMulti => "k64fmulti",
David Brown2639e072017-10-11 11:18:44 -060075 DeviceName::Nrf52840 => "nrf52840",
Fabio Utzigafb2bc92018-11-19 16:11:52 -020076 DeviceName::Nrf52840SpiFlash => "Nrf52840SpiFlash",
David Brown2639e072017-10-11 11:18:44 -060077 };
78 f.write_str(name)
79 }
80}
81
82#[derive(Debug)]
David Brown5a317752019-11-15 09:53:39 -070083struct AlignArg(usize);
David Brown2639e072017-10-11 11:18:44 -060084
85struct AlignArgVisitor;
86
87impl<'de> serde::de::Visitor<'de> for AlignArgVisitor {
88 type Value = AlignArg;
89
David Brown10b5de12019-01-02 16:10:01 -070090 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
David Brown2639e072017-10-11 11:18:44 -060091 formatter.write_str("1, 2, 4 or 8")
92 }
93
David Brown5a317752019-11-15 09:53:39 -070094 fn visit_u32<E>(self, n: u32) -> Result<Self::Value, E>
David Brown2639e072017-10-11 11:18:44 -060095 where E: serde::de::Error
96 {
97 Ok(match n {
David Brown5a317752019-11-15 09:53:39 -070098 1 | 2 | 4 | 8 => AlignArg(n as usize),
David Brown2639e072017-10-11 11:18:44 -060099 n => {
100 let err = format!("Could not deserialize '{}' as alignment", n);
101 return Err(E::custom(err));
102 }
103 })
104 }
105}
106
107impl<'de> serde::de::Deserialize<'de> for AlignArg {
108 fn deserialize<D>(d: D) -> Result<AlignArg, D::Error>
109 where D: serde::de::Deserializer<'de>
110 {
111 d.deserialize_u8(AlignArgVisitor)
112 }
113}
114
115pub fn main() {
116 let args: Args = Docopt::new(USAGE)
117 .and_then(|d| d.deserialize())
118 .unwrap_or_else(|e| e.exit());
119 // println!("args: {:#?}", args);
120
121 if args.cmd_sizes {
122 show_sizes();
123 return;
124 }
125
126 let mut status = RunStatus::new();
127 if args.cmd_run {
128
129 let align = args.flag_align.map(|x| x.0).unwrap_or(1);
130
131
132 let device = match args.flag_device {
133 None => panic!("Missing mandatory device argument"),
134 Some(dev) => dev,
135 };
136
Fabio Utzigea0290b2018-08-09 14:23:01 -0300137 status.run_single(device, align, 0xff);
David Brown2639e072017-10-11 11:18:44 -0600138 }
139
140 if args.cmd_runall {
141 for &dev in ALL_DEVICES {
142 for &align in &[1, 2, 4, 8] {
Fabio Utzigea0290b2018-08-09 14:23:01 -0300143 for &erased_val in &[0, 0xff] {
144 status.run_single(dev, align, erased_val);
145 }
David Brown2639e072017-10-11 11:18:44 -0600146 }
147 }
148 }
149
150 if status.failures > 0 {
151 error!("{} Tests ran with {} failures", status.failures + status.passes, status.failures);
152 process::exit(1);
153 } else {
154 error!("{} Tests ran successfully", status.passes);
155 process::exit(0);
156 }
157}
158
David Browndd2b1182017-11-02 15:39:21 -0600159pub struct RunStatus {
David Brown2639e072017-10-11 11:18:44 -0600160 failures: usize,
161 passes: usize,
162}
163
164impl RunStatus {
David Browndd2b1182017-11-02 15:39:21 -0600165 pub fn new() -> RunStatus {
David Brown2639e072017-10-11 11:18:44 -0600166 RunStatus {
167 failures: 0,
168 passes: 0,
169 }
170 }
171
David Brown5a317752019-11-15 09:53:39 -0700172 pub fn run_single(&mut self, device: DeviceName, align: usize, erased_val: u8) {
David Brown2639e072017-10-11 11:18:44 -0600173 warn!("Running on device {} with alignment {}", device, align);
174
David Brown5bc62c62019-03-05 12:11:48 -0700175 let run = match ImagesBuilder::new(device, align, erased_val) {
176 Some(builder) => builder,
177 None => {
178 warn!("Skipping device with insuffienct partitions");
179 return;
180 }
181 };
David Brown2639e072017-10-11 11:18:44 -0600182
David Brown2639e072017-10-11 11:18:44 -0600183 let mut failed = false;
184
David Vincze2d736ad2019-02-18 11:50:22 +0100185 // Creates a badly signed image in the secondary slot to check that
186 // it is not upgraded to
David Brown01617af2019-02-28 10:45:12 -0700187 let bad_secondary_slot_image = run.clone().make_bad_secondary_slot_image();
David Brown2639e072017-10-11 11:18:44 -0600188
David Vincze2d736ad2019-02-18 11:50:22 +0100189 failed |= bad_secondary_slot_image.run_signfail_upgrade();
David Brown2639e072017-10-11 11:18:44 -0600190
David Brownc3898d62019-08-05 14:20:02 -0600191 let images = run.clone().make_no_upgrade_image(&NO_DEPS);
David Brown5f7ec2b2017-11-06 13:54:02 -0700192 failed |= images.run_norevert_newimage();
David Brown2639e072017-10-11 11:18:44 -0600193
David Brownc3898d62019-08-05 14:20:02 -0600194 let images = run.make_image(&NO_DEPS, true);
David Brown2639e072017-10-11 11:18:44 -0600195
David Brown5f7ec2b2017-11-06 13:54:02 -0700196 failed |= images.run_basic_revert();
David Brownc49811e2017-11-06 14:20:45 -0700197 failed |= images.run_revert_with_fails();
198 failed |= images.run_perm_with_fails();
199 failed |= images.run_perm_with_random_fails(5);
David Brown5f7ec2b2017-11-06 13:54:02 -0700200 failed |= images.run_norevert();
David Brown2639e072017-10-11 11:18:44 -0600201
Fabio Utzigb841f0a2017-11-24 08:11:05 -0200202 failed |= images.run_with_status_fails_complete();
Fabio Utzigeedcc452017-11-24 10:48:52 -0200203 failed |= images.run_with_status_fails_with_reset();
Fabio Utzigb841f0a2017-11-24 08:11:05 -0200204
David Brown2639e072017-10-11 11:18:44 -0600205 //show_flash(&flash);
206
207 if failed {
208 self.failures += 1;
209 } else {
210 self.passes += 1;
211 }
212 }
David Browndd2b1182017-11-02 15:39:21 -0600213
214 pub fn failures(&self) -> usize {
215 self.failures
216 }
David Brown2639e072017-10-11 11:18:44 -0600217}
218