diff --git a/sim/src/main.rs b/sim/src/main.rs index 8b08a81f..fd9f664b 100644 --- a/sim/src/main.rs +++ b/sim/src/main.rs @@ -12,6 +12,7 @@ use docopt::Docopt; use rand::{Rng, SeedableRng, XorShiftRng}; use rustc_serialize::{Decodable, Decoder}; use std::mem; +use std::process; use std::slice; mod area; @@ -79,128 +80,181 @@ fn main() { return; } + let mut status = RunStatus::new(); + let align = args.flag_align.map(|x| x.0).unwrap_or(1); - let (mut flash, areadesc) = match args.flag_device { - None => panic!("Missing mandatory argument"), - Some(DeviceName::Stm32f4) => { - // STM style flash. Large sectors, with a large scratch area. - let flash = Flash::new(vec![16 * 1024, 16 * 1024, 16 * 1024, 16 * 1024, - 64 * 1024, - 128 * 1024, 128 * 1024, 128 * 1024], - align as usize); - let mut areadesc = AreaDesc::new(&flash); - areadesc.add_image(0x020000, 0x020000, FlashId::Image0); - areadesc.add_image(0x040000, 0x020000, FlashId::Image1); - areadesc.add_image(0x060000, 0x020000, FlashId::ImageScratch); - (flash, areadesc) - } - Some(DeviceName::K64f) => { - // NXP style flash. Small sectors, one small sector for scratch. - let flash = Flash::new(vec![4096; 128], align as usize); - - let mut areadesc = AreaDesc::new(&flash); - areadesc.add_image(0x020000, 0x020000, FlashId::Image0); - areadesc.add_image(0x040000, 0x020000, FlashId::Image1); - areadesc.add_image(0x060000, 0x001000, FlashId::ImageScratch); - (flash, areadesc) - } - Some(DeviceName::K64fBig) => { - // Simulating an STM style flash on top of an NXP style flash. Underlying flash device - // uses small sectors, but we tell the bootloader they are large. - let flash = Flash::new(vec![4096; 128], align as usize); - - let mut areadesc = AreaDesc::new(&flash); - areadesc.add_simple_image(0x020000, 0x020000, FlashId::Image0); - areadesc.add_simple_image(0x040000, 0x020000, FlashId::Image1); - areadesc.add_simple_image(0x060000, 0x020000, FlashId::ImageScratch); - (flash, areadesc) - } - Some(DeviceName::Nrf52840) => { - // Simulating the flash on the nrf52840 with partitions set up so that the scratch size - // does not divide into the image size. - let flash = Flash::new(vec![4096; 128], align as usize); - - let mut areadesc = AreaDesc::new(&flash); - areadesc.add_image(0x008000, 0x034000, FlashId::Image0); - areadesc.add_image(0x03c000, 0x034000, FlashId::Image1); - areadesc.add_image(0x070000, 0x00d000, FlashId::ImageScratch); - (flash, areadesc) - } + let device = match args.flag_device { + None => panic!("Missing mandatory device argument"), + Some(dev) => dev, }; - let (slot0_base, slot0_len) = areadesc.find(FlashId::Image0); - let (slot1_base, slot1_len) = areadesc.find(FlashId::Image1); - let (scratch_base, _) = areadesc.find(FlashId::ImageScratch); + status.run_single(device, align); - // Code below assumes that the slots are consecutive. - assert_eq!(slot1_base, slot0_base + slot0_len); - assert_eq!(scratch_base, slot1_base + slot1_len); + if status.failures > 0 { + warn!("{} Tests ran with {} failures", status.failures + status.passes, status.failures); + process::exit(1); + } else { + warn!("{} Tests ran successfully", status.passes); + process::exit(0); + } +} - // println!("Areas: {:#?}", areadesc.get_c()); +struct RunStatus { + failures: usize, + passes: usize, +} - // Install the boot trailer signature, so that the code will start an upgrade. - // TODO: This must be a multiple of flash alignment, add support for an image that is smaller, - // and just gets padded. - let primary = install_image(&mut flash, slot0_base, 32784); - - // Install an upgrade image. - let upgrade = install_image(&mut flash, slot1_base, 41928); - - // Set an alignment, and position the magic value. - c::set_sim_flash_align(align); - let trailer_size = c::boot_trailer_sz(); - - // Mark the upgrade as ready to install. (This looks like it might be a bug in the code, - // however.) - mark_upgrade(&mut flash, scratch_base - trailer_size as usize); - - let (fl2, total_count) = try_upgrade(&flash, &areadesc, None); - info!("First boot, count={}", total_count); - assert!(verify_image(&fl2, slot0_base, &upgrade)); - - let mut bad = 0; - // Let's try an image halfway through. - for i in 1 .. total_count { - info!("Try interruption at {}", i); - let (fl3, total_count) = try_upgrade(&flash, &areadesc, Some(i)); - info!("Second boot, count={}", total_count); - if !verify_image(&fl3, slot0_base, &upgrade) { - warn!("FAIL at step {} of {}", i, total_count); - bad += 1; - } - if !verify_image(&fl3, slot1_base, &primary) { - warn!("Slot 1 FAIL at step {} of {}", i, total_count); - bad += 1; +impl RunStatus { + fn new() -> RunStatus { + RunStatus { + failures: 0, + passes: 0, } } - error!("{} out of {} failed {:.2}%", - bad, total_count, - bad as f32 * 100.0 / total_count as f32); - for count in 2 .. 5 { - info!("Try revert: {}", count); - let fl2 = try_revert(&flash, &areadesc, count); - assert!(verify_image(&fl2, slot0_base, &primary)); + fn run_single(&mut self, device: DeviceName, align: u8) { + let mut failed = false; + + let (mut flash, areadesc) = match device { + DeviceName::Stm32f4 => { + // STM style flash. Large sectors, with a large scratch area. + let flash = Flash::new(vec![16 * 1024, 16 * 1024, 16 * 1024, 16 * 1024, + 64 * 1024, + 128 * 1024, 128 * 1024, 128 * 1024], + align as usize); + let mut areadesc = AreaDesc::new(&flash); + areadesc.add_image(0x020000, 0x020000, FlashId::Image0); + areadesc.add_image(0x040000, 0x020000, FlashId::Image1); + areadesc.add_image(0x060000, 0x020000, FlashId::ImageScratch); + (flash, areadesc) + } + DeviceName::K64f => { + // NXP style flash. Small sectors, one small sector for scratch. + let flash = Flash::new(vec![4096; 128], align as usize); + + let mut areadesc = AreaDesc::new(&flash); + areadesc.add_image(0x020000, 0x020000, FlashId::Image0); + areadesc.add_image(0x040000, 0x020000, FlashId::Image1); + areadesc.add_image(0x060000, 0x001000, FlashId::ImageScratch); + (flash, areadesc) + } + DeviceName::K64fBig => { + // Simulating an STM style flash on top of an NXP style flash. Underlying flash device + // uses small sectors, but we tell the bootloader they are large. + let flash = Flash::new(vec![4096; 128], align as usize); + + let mut areadesc = AreaDesc::new(&flash); + areadesc.add_simple_image(0x020000, 0x020000, FlashId::Image0); + areadesc.add_simple_image(0x040000, 0x020000, FlashId::Image1); + areadesc.add_simple_image(0x060000, 0x020000, FlashId::ImageScratch); + (flash, areadesc) + } + DeviceName::Nrf52840 => { + // Simulating the flash on the nrf52840 with partitions set up so that the scratch size + // does not divide into the image size. + let flash = Flash::new(vec![4096; 128], align as usize); + + let mut areadesc = AreaDesc::new(&flash); + areadesc.add_image(0x008000, 0x034000, FlashId::Image0); + areadesc.add_image(0x03c000, 0x034000, FlashId::Image1); + areadesc.add_image(0x070000, 0x00d000, FlashId::ImageScratch); + (flash, areadesc) + } + }; + + let (slot0_base, slot0_len) = areadesc.find(FlashId::Image0); + let (slot1_base, slot1_len) = areadesc.find(FlashId::Image1); + let (scratch_base, _) = areadesc.find(FlashId::ImageScratch); + + // Code below assumes that the slots are consecutive. + assert_eq!(slot1_base, slot0_base + slot0_len); + assert_eq!(scratch_base, slot1_base + slot1_len); + + // println!("Areas: {:#?}", areadesc.get_c()); + + // Install the boot trailer signature, so that the code will start an upgrade. + // TODO: This must be a multiple of flash alignment, add support for an image that is smaller, + // and just gets padded. + let primary = install_image(&mut flash, slot0_base, 32784); + + // Install an upgrade image. + let upgrade = install_image(&mut flash, slot1_base, 41928); + + // Set an alignment, and position the magic value. + c::set_sim_flash_align(align); + let trailer_size = c::boot_trailer_sz(); + + // Mark the upgrade as ready to install. (This looks like it might be a bug in the code, + // however.) + mark_upgrade(&mut flash, scratch_base - trailer_size as usize); + + let (fl2, total_count) = try_upgrade(&flash, &areadesc, None); + info!("First boot, count={}", total_count); + if !verify_image(&fl2, slot0_base, &upgrade) { + error!("Image mismatch after first boot"); + // This isn't really recoverable, and more tests aren't likely to reveal much. + self.failures += 1; + return; + } + + let mut bad = 0; + // Let's try an image halfway through. + for i in 1 .. total_count { + info!("Try interruption at {}", i); + let (fl3, total_count) = try_upgrade(&flash, &areadesc, Some(i)); + info!("Second boot, count={}", total_count); + if !verify_image(&fl3, slot0_base, &upgrade) { + warn!("FAIL at step {} of {}", i, total_count); + bad += 1; + } + if !verify_image(&fl3, slot1_base, &primary) { + warn!("Slot 1 FAIL at step {} of {}", i, total_count); + bad += 1; + } + } + error!("{} out of {} failed {:.2}%", + bad, total_count, + bad as f32 * 100.0 / total_count as f32); + if bad > 0 { + failed = true; + } + + for count in 2 .. 5 { + info!("Try revert: {}", count); + let fl2 = try_revert(&flash, &areadesc, count); + if !verify_image(&fl2, slot0_base, &primary) { + warn!("Revert failure on count {}", count); + failed = true; + } + } + + info!("Try norevert"); + let fl2 = try_norevert(&flash, &areadesc); + if !verify_image(&fl2, slot0_base, &upgrade) { + warn!("No revert failed"); + failed = true; + } + + /* + // show_flash(&flash); + + println!("First boot for upgrade"); + // c::set_flash_counter(570); + c::boot_go(&mut flash, &areadesc); + // println!("{} flash ops", c::get_flash_counter()); + + verify_image(&flash, slot0_base, &upgrade); + + println!("\n------------------\nSecond boot"); + c::boot_go(&mut flash, &areadesc); + */ + if failed { + self.failures += 1; + } else { + self.passes += 1; + } } - - info!("Try norevert"); - let fl2 = try_norevert(&flash, &areadesc); - assert!(verify_image(&fl2, slot0_base, &upgrade)); - - /* - // show_flash(&flash); - - println!("First boot for upgrade"); - // c::set_flash_counter(570); - c::boot_go(&mut flash, &areadesc); - // println!("{} flash ops", c::get_flash_counter()); - - verify_image(&flash, slot0_base, &upgrade); - - println!("\n------------------\nSecond boot"); - c::boot_go(&mut flash, &areadesc); - */ } /// Test a boot, optionally stopping after 'n' flash options. Returns a count of the number of