blob: 4e2f6c371cea56f192036a167c0df0f1e584097e [file] [log] [blame]
David Browne2acfae2020-01-21 16:45:01 -07001// Copyright (c) 2017-2019 Linaro LTD
2// Copyright (c) 2017-2019 JUUL Labs
3// Copyright (c) 2019 Arm Limited
4//
5// SPDX-License-Identifier: Apache-2.0
6
David Brown2639e072017-10-11 11:18:44 -06007use docopt::Docopt;
David Brown5c9e0f12019-01-09 16:34:33 -07008use log::{warn, error};
David Brown10b5de12019-01-02 16:10:01 -07009use std::{
10 fmt,
David Brown10b5de12019-01-02 16:10:01 -070011 process,
David Brown10b5de12019-01-02 16:10:01 -070012};
13use serde_derive::Deserialize;
David Brown2639e072017-10-11 11:18:44 -060014
15mod caps;
David Brownc3898d62019-08-05 14:20:02 -060016mod depends;
David Brown5c9e0f12019-01-09 16:34:33 -070017mod image;
David Brown2639e072017-10-11 11:18:44 -060018mod tlv;
David Brownca7b5d32017-11-03 08:37:38 -060019pub mod testlog;
David Brown2639e072017-10-11 11:18:44 -060020
David Brownc3898d62019-08-05 14:20:02 -060021pub use crate::{
22 depends::{
23 DepTest,
24 DepType,
25 UpgradeInfo,
26 NO_DEPS,},
27 image::{
28 ImagesBuilder,
David Brownfe5ab1c2019-08-13 15:35:23 -060029 Images,
David Brownc3898d62019-08-05 14:20:02 -060030 show_sizes,
31 },
David Brown5c9e0f12019-01-09 16:34:33 -070032};
David Brown2639e072017-10-11 11:18:44 -060033
34const USAGE: &'static str = "
35Mcuboot simulator
36
37Usage:
38 bootsim sizes
39 bootsim run --device TYPE [--align SIZE]
40 bootsim runall
41 bootsim (--help | --version)
42
43Options:
44 -h, --help Show this message
45 --version Version
46 --device TYPE MCU to simulate
47 Valid values: stm32f4, k64f
48 --align SIZE Flash write alignment
49";
50
51#[derive(Debug, Deserialize)]
52struct Args {
53 flag_help: bool,
54 flag_version: bool,
55 flag_device: Option<DeviceName>,
56 flag_align: Option<AlignArg>,
57 cmd_sizes: bool,
58 cmd_run: bool,
59 cmd_runall: bool,
60}
61
62#[derive(Copy, Clone, Debug, Deserialize)]
David Brown2bff6472019-03-05 13:58:35 -070063pub enum DeviceName { Stm32f4, K64f, K64fBig, K64fMulti, Nrf52840, Nrf52840SpiFlash, }
David Brown2639e072017-10-11 11:18:44 -060064
David Browndd2b1182017-11-02 15:39:21 -060065pub static ALL_DEVICES: &'static [DeviceName] = &[
David Brown2639e072017-10-11 11:18:44 -060066 DeviceName::Stm32f4,
67 DeviceName::K64f,
68 DeviceName::K64fBig,
David Brown2bff6472019-03-05 13:58:35 -070069 DeviceName::K64fMulti,
David Brown2639e072017-10-11 11:18:44 -060070 DeviceName::Nrf52840,
Fabio Utzigafb2bc92018-11-19 16:11:52 -020071 DeviceName::Nrf52840SpiFlash,
David Brown2639e072017-10-11 11:18:44 -060072];
73
74impl fmt::Display for DeviceName {
David Brown10b5de12019-01-02 16:10:01 -070075 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
David Brown2639e072017-10-11 11:18:44 -060076 let name = match *self {
77 DeviceName::Stm32f4 => "stm32f4",
78 DeviceName::K64f => "k64f",
79 DeviceName::K64fBig => "k64fbig",
David Brown2bff6472019-03-05 13:58:35 -070080 DeviceName::K64fMulti => "k64fmulti",
David Brown2639e072017-10-11 11:18:44 -060081 DeviceName::Nrf52840 => "nrf52840",
Fabio Utzigafb2bc92018-11-19 16:11:52 -020082 DeviceName::Nrf52840SpiFlash => "Nrf52840SpiFlash",
David Brown2639e072017-10-11 11:18:44 -060083 };
84 f.write_str(name)
85 }
86}
87
88#[derive(Debug)]
David Brown5a317752019-11-15 09:53:39 -070089struct AlignArg(usize);
David Brown2639e072017-10-11 11:18:44 -060090
91struct AlignArgVisitor;
92
93impl<'de> serde::de::Visitor<'de> for AlignArgVisitor {
94 type Value = AlignArg;
95
David Brown10b5de12019-01-02 16:10:01 -070096 fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
David Brown2639e072017-10-11 11:18:44 -060097 formatter.write_str("1, 2, 4 or 8")
98 }
99
David Brown5a317752019-11-15 09:53:39 -0700100 fn visit_u32<E>(self, n: u32) -> Result<Self::Value, E>
David Brown2639e072017-10-11 11:18:44 -0600101 where E: serde::de::Error
102 {
103 Ok(match n {
David Brown5a317752019-11-15 09:53:39 -0700104 1 | 2 | 4 | 8 => AlignArg(n as usize),
David Brown2639e072017-10-11 11:18:44 -0600105 n => {
106 let err = format!("Could not deserialize '{}' as alignment", n);
107 return Err(E::custom(err));
108 }
109 })
110 }
111}
112
113impl<'de> serde::de::Deserialize<'de> for AlignArg {
114 fn deserialize<D>(d: D) -> Result<AlignArg, D::Error>
115 where D: serde::de::Deserializer<'de>
116 {
117 d.deserialize_u8(AlignArgVisitor)
118 }
119}
120
121pub fn main() {
122 let args: Args = Docopt::new(USAGE)
123 .and_then(|d| d.deserialize())
124 .unwrap_or_else(|e| e.exit());
125 // println!("args: {:#?}", args);
126
127 if args.cmd_sizes {
128 show_sizes();
129 return;
130 }
131
132 let mut status = RunStatus::new();
133 if args.cmd_run {
134
135 let align = args.flag_align.map(|x| x.0).unwrap_or(1);
136
137
138 let device = match args.flag_device {
139 None => panic!("Missing mandatory device argument"),
140 Some(dev) => dev,
141 };
142
Fabio Utzigea0290b2018-08-09 14:23:01 -0300143 status.run_single(device, align, 0xff);
David Brown2639e072017-10-11 11:18:44 -0600144 }
145
146 if args.cmd_runall {
147 for &dev in ALL_DEVICES {
148 for &align in &[1, 2, 4, 8] {
Fabio Utzigea0290b2018-08-09 14:23:01 -0300149 for &erased_val in &[0, 0xff] {
150 status.run_single(dev, align, erased_val);
151 }
David Brown2639e072017-10-11 11:18:44 -0600152 }
153 }
154 }
155
156 if status.failures > 0 {
157 error!("{} Tests ran with {} failures", status.failures + status.passes, status.failures);
158 process::exit(1);
159 } else {
160 error!("{} Tests ran successfully", status.passes);
161 process::exit(0);
162 }
163}
164
David Browndd2b1182017-11-02 15:39:21 -0600165pub struct RunStatus {
David Brown2639e072017-10-11 11:18:44 -0600166 failures: usize,
167 passes: usize,
168}
169
170impl RunStatus {
David Browndd2b1182017-11-02 15:39:21 -0600171 pub fn new() -> RunStatus {
David Brown2639e072017-10-11 11:18:44 -0600172 RunStatus {
173 failures: 0,
174 passes: 0,
175 }
176 }
177
David Brown5a317752019-11-15 09:53:39 -0700178 pub fn run_single(&mut self, device: DeviceName, align: usize, erased_val: u8) {
David Brown2639e072017-10-11 11:18:44 -0600179 warn!("Running on device {} with alignment {}", device, align);
180
David Brown5bc62c62019-03-05 12:11:48 -0700181 let run = match ImagesBuilder::new(device, align, erased_val) {
Fabio Utzig114a6472019-11-28 10:24:09 -0300182 Ok(builder) => builder,
183 Err(msg) => {
184 warn!("Skipping {}: {}", device, msg);
David Brown5bc62c62019-03-05 12:11:48 -0700185 return;
186 }
187 };
David Brown2639e072017-10-11 11:18:44 -0600188
David Brown2639e072017-10-11 11:18:44 -0600189 let mut failed = false;
190
David Vincze2d736ad2019-02-18 11:50:22 +0100191 // Creates a badly signed image in the secondary slot to check that
192 // it is not upgraded to
David Brown01617af2019-02-28 10:45:12 -0700193 let bad_secondary_slot_image = run.clone().make_bad_secondary_slot_image();
David Brown2639e072017-10-11 11:18:44 -0600194
David Vincze2d736ad2019-02-18 11:50:22 +0100195 failed |= bad_secondary_slot_image.run_signfail_upgrade();
David Brown2639e072017-10-11 11:18:44 -0600196
David Brownc3898d62019-08-05 14:20:02 -0600197 let images = run.clone().make_no_upgrade_image(&NO_DEPS);
David Brown5f7ec2b2017-11-06 13:54:02 -0700198 failed |= images.run_norevert_newimage();
David Brown2639e072017-10-11 11:18:44 -0600199
David Brownc3898d62019-08-05 14:20:02 -0600200 let images = run.make_image(&NO_DEPS, true);
David Brown2639e072017-10-11 11:18:44 -0600201
David Brown5f7ec2b2017-11-06 13:54:02 -0700202 failed |= images.run_basic_revert();
David Brownc49811e2017-11-06 14:20:45 -0700203 failed |= images.run_revert_with_fails();
204 failed |= images.run_perm_with_fails();
205 failed |= images.run_perm_with_random_fails(5);
David Brown5f7ec2b2017-11-06 13:54:02 -0700206 failed |= images.run_norevert();
David Brown2639e072017-10-11 11:18:44 -0600207
Fabio Utzigb841f0a2017-11-24 08:11:05 -0200208 failed |= images.run_with_status_fails_complete();
Fabio Utzigeedcc452017-11-24 10:48:52 -0200209 failed |= images.run_with_status_fails_with_reset();
Fabio Utzigb841f0a2017-11-24 08:11:05 -0200210
David Brown2639e072017-10-11 11:18:44 -0600211 //show_flash(&flash);
212
213 if failed {
214 self.failures += 1;
215 } else {
216 self.passes += 1;
217 }
218 }
David Browndd2b1182017-11-02 15:39:21 -0600219
220 pub fn failures(&self) -> usize {
221 self.failures
222 }
David Brown2639e072017-10-11 11:18:44 -0600223}
224