sim: Add swap using offset to tests
Enables testing this new mode
Signed-off-by: Jamie McCrae <jamie.mccrae@nordicsemi.no>
diff --git a/sim/Cargo.toml b/sim/Cargo.toml
index 7cef823..6d2262d 100644
--- a/sim/Cargo.toml
+++ b/sim/Cargo.toml
@@ -15,6 +15,7 @@
sig-p384 = ["mcuboot-sys/sig-p384"]
sig-ed25519 = ["mcuboot-sys/sig-ed25519"]
overwrite-only = ["mcuboot-sys/overwrite-only"]
+swap-offset = ["mcuboot-sys/swap-offset"]
swap-move = ["mcuboot-sys/swap-move"]
validate-primary-slot = ["mcuboot-sys/validate-primary-slot"]
enc-rsa = ["mcuboot-sys/enc-rsa"]
diff --git a/sim/mcuboot-sys/Cargo.toml b/sim/mcuboot-sys/Cargo.toml
index ab97bbf..f2eb706 100644
--- a/sim/mcuboot-sys/Cargo.toml
+++ b/sim/mcuboot-sys/Cargo.toml
@@ -36,6 +36,10 @@
# Overwrite only upgrade
overwrite-only = []
+# Swap using offset mode
+swap-offset = []
+
+# Swap using move move
swap-move = []
# Disable validation of the primary slot
diff --git a/sim/mcuboot-sys/build.rs b/sim/mcuboot-sys/build.rs
index 47ee880..e74a086 100644
--- a/sim/mcuboot-sys/build.rs
+++ b/sim/mcuboot-sys/build.rs
@@ -20,6 +20,7 @@
let sig_ed25519 = env::var("CARGO_FEATURE_SIG_ED25519").is_ok();
let overwrite_only = env::var("CARGO_FEATURE_OVERWRITE_ONLY").is_ok();
let swap_move = env::var("CARGO_FEATURE_SWAP_MOVE").is_ok();
+ let swap_offset = env::var("CARGO_FEATURE_SWAP_OFFSET").is_ok();
let validate_primary_slot =
env::var("CARGO_FEATURE_VALIDATE_PRIMARY_SLOT").is_ok();
let enc_rsa = env::var("CARGO_FEATURE_ENC_RSA").is_ok();
@@ -253,7 +254,9 @@
conf.conf.define("MCUBOOT_OVERWRITE_ONLY", None);
}
- if swap_move {
+ if swap_offset {
+ conf.conf.define("MCUBOOT_SWAP_USING_OFFSET", None);
+ } else if swap_move {
conf.conf.define("MCUBOOT_SWAP_USING_MOVE", None);
} else if !overwrite_only && !direct_xip && !ram_load {
conf.conf.define("CONFIG_BOOT_SWAP_USING_SCRATCH", None);
@@ -461,6 +464,7 @@
conf.file("../../boot/bootutil/src/swap_misc.c");
conf.file("../../boot/bootutil/src/swap_scratch.c");
conf.file("../../boot/bootutil/src/swap_move.c");
+ conf.file("../../boot/bootutil/src/swap_offset.c");
conf.file("../../boot/bootutil/src/caps.c");
conf.file("../../boot/bootutil/src/bootutil_misc.c");
conf.file("../../boot/bootutil/src/bootutil_public.c");
diff --git a/sim/src/caps.rs b/sim/src/caps.rs
index d8dd068..2b98ab6 100644
--- a/sim/src/caps.rs
+++ b/sim/src/caps.rs
@@ -30,6 +30,7 @@
DirectXip = (1 << 17),
HwRollbackProtection = (1 << 18),
EcdsaP384 = (1 << 19),
+ SwapUsingOffset = (1 << 20),
}
impl Caps {
diff --git a/sim/src/image.rs b/sim/src/image.rs
index 4cd6488..e406a81 100644
--- a/sim/src/image.rs
+++ b/sim/src/image.rs
@@ -235,20 +235,20 @@
let (primaries,upgrades) = if img_manipulation == ImageManipulation::CorruptHigherVersionImage && !higher_version_corrupted {
higher_version_corrupted = true;
let prim = install_image(&mut flash, &slots[0],
- maximal(42784), &ram, &*dep, ImageManipulation::None, Some(0));
+ maximal(42784), &ram, &*dep, ImageManipulation::None, Some(0), false);
let upgr = match deps.depends[image_num] {
DepType::NoUpgrade => install_no_image(),
_ => install_image(&mut flash, &slots[1],
- maximal(46928), &ram, &*dep, ImageManipulation::BadSignature, Some(0))
+ maximal(46928), &ram, &*dep, ImageManipulation::BadSignature, Some(0), true)
};
(prim, upgr)
} else {
let prim = install_image(&mut flash, &slots[0],
- maximal(42784), &ram, &*dep, img_manipulation, Some(0));
+ maximal(42784), &ram, &*dep, img_manipulation, Some(0), false);
let upgr = match deps.depends[image_num] {
DepType::NoUpgrade => install_no_image(),
_ => install_image(&mut flash, &slots[1],
- maximal(46928), &ram, &*dep, img_manipulation, Some(0))
+ maximal(46928), &ram, &*dep, img_manipulation, Some(0), true)
};
(prim, upgr)
};
@@ -299,9 +299,9 @@
let images = self.slots.into_iter().enumerate().map(|(image_num, slots)| {
let dep = BoringDep::new(image_num, &NO_DEPS);
let primaries = install_image(&mut bad_flash, &slots[0],
- maximal(32784), &ram, &dep, ImageManipulation::None, Some(0));
+ maximal(32784), &ram, &dep, ImageManipulation::None, Some(0), false);
let upgrades = install_image(&mut bad_flash, &slots[1],
- maximal(41928), &ram, &dep, ImageManipulation::BadSignature, Some(0));
+ maximal(41928), &ram, &dep, ImageManipulation::BadSignature, Some(0), true);
OneImage {
slots,
primaries,
@@ -322,9 +322,9 @@
let images = self.slots.into_iter().enumerate().map(|(image_num, slots)| {
let dep = BoringDep::new(image_num, &NO_DEPS);
let primaries = install_image(&mut bad_flash, &slots[0],
- maximal(32784), &ram, &dep, ImageManipulation::None, Some(0));
+ maximal(32784), &ram, &dep, ImageManipulation::None, Some(0), false);
let upgrades = install_image(&mut bad_flash, &slots[1],
- ImageSize::Oversized, &ram, &dep, ImageManipulation::None, Some(0));
+ ImageSize::Oversized, &ram, &dep, ImageManipulation::None, Some(0), true);
OneImage {
slots,
primaries,
@@ -345,7 +345,7 @@
let images = self.slots.into_iter().enumerate().map(|(image_num, slots)| {
let dep = BoringDep::new(image_num, &NO_DEPS);
let primaries = install_image(&mut flash, &slots[0],
- maximal(32784), &ram, &dep,ImageManipulation::None, Some(0));
+ maximal(32784), &ram, &dep,ImageManipulation::None, Some(0), false);
let upgrades = install_no_image();
OneImage {
slots,
@@ -368,7 +368,7 @@
let dep = BoringDep::new(image_num, &NO_DEPS);
let primaries = install_no_image();
let upgrades = install_image(&mut flash, &slots[1],
- maximal(32784), &ram, &dep, ImageManipulation::None, Some(0));
+ maximal(32784), &ram, &dep, ImageManipulation::None, Some(0), true);
OneImage {
slots,
primaries,
@@ -390,7 +390,7 @@
let dep = BoringDep::new(image_num, &NO_DEPS);
let primaries = install_no_image();
let upgrades = install_image(&mut flash, &slots[1],
- ImageSize::Oversized, &ram, &dep, ImageManipulation::None, Some(0));
+ ImageSize::Oversized, &ram, &dep, ImageManipulation::None, Some(0), true);
OneImage {
slots,
primaries,
@@ -412,9 +412,9 @@
let images = self.slots.into_iter().enumerate().map(|(image_num, slots)| {
let dep = BoringDep::new(image_num, &NO_DEPS);
let primaries = install_image(&mut flash, &slots[0],
- maximal(32784), &ram, &dep, ImageManipulation::None, security_cnt);
+ maximal(32784), &ram, &dep, ImageManipulation::None, security_cnt, false);
let upgrades = install_image(&mut flash, &slots[1],
- maximal(41928), &ram, &dep, ImageManipulation::None, security_cnt.map(|v| v + 1));
+ maximal(41928), &ram, &dep, ImageManipulation::None, security_cnt.map(|v| v + 1), true);
OneImage {
slots,
primaries,
@@ -451,7 +451,7 @@
let mut flash = SimMultiFlash::new();
flash.insert(dev_id, dev);
- (flash, Rc::new(areadesc), &[Caps::SwapUsingMove])
+ (flash, Rc::new(areadesc), &[Caps::SwapUsingMove, Caps::SwapUsingOffset])
}
DeviceName::K64f => {
// NXP style flash. Small sectors, one small sector for scratch.
@@ -482,7 +482,7 @@
let mut flash = SimMultiFlash::new();
flash.insert(dev_id, dev);
- (flash, Rc::new(areadesc), &[Caps::SwapUsingMove])
+ (flash, Rc::new(areadesc), &[Caps::SwapUsingMove, Caps::SwapUsingOffset])
}
DeviceName::Nrf52840 => {
// Simulating the flash on the nrf52840 with partitions set up so that the scratch size
@@ -511,7 +511,20 @@
let mut flash = SimMultiFlash::new();
flash.insert(dev_id, dev);
- (flash, Rc::new(areadesc), &[Caps::SwapUsingScratch, Caps::OverwriteUpgrade])
+ (flash, Rc::new(areadesc), &[Caps::SwapUsingScratch, Caps::OverwriteUpgrade, Caps::SwapUsingOffset])
+ }
+ DeviceName::Nrf52840UnequalSlotsLargerSlot1 => {
+ let dev = SimFlash::new(vec![4096; 128], align as usize, erased_val);
+
+ let dev_id = 0;
+ let mut areadesc = AreaDesc::new();
+ areadesc.add_flash_sectors(dev_id, &dev);
+ areadesc.add_image(0x008000, 0x03b000, FlashId::Image0, dev_id);
+ areadesc.add_image(0x043000, 0x03c000, FlashId::Image1, dev_id);
+
+ let mut flash = SimMultiFlash::new();
+ flash.insert(dev_id, dev);
+ (flash, Rc::new(areadesc), &[Caps::SwapUsingScratch, Caps::OverwriteUpgrade, Caps::SwapUsingMove, Caps::RamLoad, Caps::DirectXip])
}
DeviceName::Nrf52840SpiFlash => {
// Simulate nrf52840 with external SPI flash. The external SPI flash
@@ -530,7 +543,7 @@
let mut flash = SimMultiFlash::new();
flash.insert(0, dev0);
flash.insert(1, dev1);
- (flash, Rc::new(areadesc), &[Caps::SwapUsingMove])
+ (flash, Rc::new(areadesc), &[Caps::SwapUsingMove, Caps::SwapUsingOffset])
}
DeviceName::K64fMulti => {
// NXP style flash, but larger, to support multiple images.
@@ -653,7 +666,7 @@
}
fn is_swap_upgrade(&self) -> bool {
- Caps::SwapUsingScratch.present() || Caps::SwapUsingMove.present()
+ Caps::SwapUsingScratch.present() || Caps::SwapUsingMove.present() || Caps::SwapUsingOffset.present()
}
pub fn run_basic_revert(&self) -> bool {
@@ -1738,7 +1751,7 @@
// This computation is incorrect, and we need to figure out the correct size.
// c::boot_status_sz(dev.align() as u32) as usize
16 + 4 * dev.align()
- } else if Caps::SwapUsingMove.present() {
+ } else if Caps::SwapUsingOffset.present() || Caps::SwapUsingMove.present() {
let sector_size = dev.sector_iter().next().unwrap().size as u32;
align_up(c::boot_trailer_sz(dev.align() as u32), sector_size) as usize
} else if Caps::SwapUsingScratch.present() {
@@ -1754,13 +1767,19 @@
/// fields used by the given code. Returns a copy of the image that was written.
fn install_image(flash: &mut SimMultiFlash, slot: &SlotInfo, len: ImageSize,
ram: &RamData,
- deps: &dyn Depender, img_manipulation: ImageManipulation, security_counter:Option<u32>) -> ImageData {
- let offset = slot.base_off;
+ deps: &dyn Depender, img_manipulation: ImageManipulation, security_counter:Option<u32>, secondary_slot:bool) -> ImageData {
+ let mut offset = slot.base_off;
let slot_len = slot.len;
let dev_id = slot.dev_id;
let dev = flash.get_mut(&dev_id).unwrap();
let mut tlv: Box<dyn ManifestGen> = Box::new(make_tlv());
+
+ if Caps::SwapUsingOffset.present() && secondary_slot {
+ let sector_size = dev.sector_iter().next().unwrap().size as usize;
+ offset += sector_size;
+ }
+
if img_manipulation == ImageManipulation::IgnoreRamLoadFlag {
tlv.set_ignore_ram_load_flag();
}
@@ -1798,11 +1817,19 @@
ImageSize::Oversized => {
let trailer = image_largest_trailer(dev);
let tlv_len = tlv.estimate_size();
+ let mut sector_offset = 0;
+
+ if Caps::SwapUsingOffset.present() && secondary_slot {
+ // This accounts for when both slots have the same size, it will not work where
+ // the second slot is one sector larger than the primary
+ sector_offset = dev.sector_iter().next().unwrap().size as usize;
+ }
+
info!("slot: 0x{:x}, HDR: 0x{:x}, trailer: 0x{:x}",
slot_len, HDR_SIZE, trailer);
// the overflow size is rougly estimated to work for all
// configurations. It might be precise if tlv_len will be maked precise.
- slot_len - HDR_SIZE - trailer - tlv_len + dev.align()*4
+ slot_len - HDR_SIZE - trailer - tlv_len - sector_offset + dev.align()*4
}
};
@@ -2046,17 +2073,37 @@
let dev = flash.get(&dev_id).unwrap();
dev.read(offset, &mut copy).unwrap();
- if buf != ©[..] {
- for i in 0 .. buf.len() {
- if buf[i] != copy[i] {
- info!("First failure for slot{} at {:#x} ({:#x} within) {:#x}!={:#x}",
- slot.index, offset + i, i, buf[i], copy[i]);
- break;
+ if Caps::SwapUsingOffset.present() && (slot.index % 2) == 1 {
+ let sector_size = dev.sector_iter().next().unwrap().size as usize;
+ let mut copy_offset = vec![0u8; buf.len()];
+ let offset_offset = slot.base_off + sector_size;
+ dev.read(offset_offset, &mut copy_offset).unwrap();
+
+ if buf != ©[..] && buf != ©_offset[..] {
+ for i in 0 .. buf.len() {
+ if buf[i] != copy[i] && buf[i] != copy_offset[i] {
+ info!("First failure for slot{} at {:#x} ({:#x} within) {:#x}!=({:#x} or {:#x})",
+ slot.index, offset + i, i, buf[i], copy[i], copy_offset[i]);
+ break;
+ }
}
+ false
+ } else {
+ true
}
- false
} else {
- true
+ if buf != ©[..] {
+ for i in 0 .. buf.len() {
+ if buf[i] != copy[i] {
+ info!("First failure for slot{} at {:#x} ({:#x} within) {:#x}!={:#x}",
+ slot.index, offset + i, i, buf[i], copy[i]);
+ break;
+ }
+ }
+ false
+ } else {
+ true
+ }
}
}
@@ -2294,6 +2341,7 @@
/// Returns an ImageSize representing the best size to test, possibly just with the given size.
fn maximal(size: usize) -> ImageSize {
if Caps::OverwriteUpgrade.present() ||
+ Caps::SwapUsingOffset.present() ||
Caps::SwapUsingMove.present()
{
ImageSize::Given(size)
diff --git a/sim/src/lib.rs b/sim/src/lib.rs
index fe43e46..5e4304b 100644
--- a/sim/src/lib.rs
+++ b/sim/src/lib.rs
@@ -64,7 +64,7 @@
#[derive(Copy, Clone, Debug, Deserialize)]
pub enum DeviceName {
Stm32f4, K64f, K64fBig, K64fMulti, Nrf52840, Nrf52840SpiFlash,
- Nrf52840UnequalSlots,
+ Nrf52840UnequalSlots, Nrf52840UnequalSlotsLargerSlot1,
}
pub static ALL_DEVICES: &[DeviceName] = &[
@@ -75,6 +75,7 @@
DeviceName::Nrf52840,
DeviceName::Nrf52840SpiFlash,
DeviceName::Nrf52840UnequalSlots,
+ DeviceName::Nrf52840UnequalSlotsLargerSlot1,
];
impl fmt::Display for DeviceName {
@@ -87,6 +88,7 @@
DeviceName::Nrf52840 => "nrf52840",
DeviceName::Nrf52840SpiFlash => "Nrf52840SpiFlash",
DeviceName::Nrf52840UnequalSlots => "Nrf52840UnequalSlots",
+ DeviceName::Nrf52840UnequalSlotsLargerSlot1 => "Nrf52840UnequalSlotsLargerSlot1",
};
f.write_str(name)
}