sim: Add dependency tests to simulator
Create a trait `Depender` which is passed down to the image create and
verification to check and test for various types of dependency
resolution. Add a test that uses this to test the simple case of unmet
dependencies preventing an upgrade.
The actual test is disabled (with an `if false ...`) because the code
under test loops forever in this configuration.
Signed-off-by: David Brown <david.brown@linaro.org>
diff --git a/sim/src/image.rs b/sim/src/image.rs
index b0d996d..6b351f8 100644
--- a/sim/src/image.rs
+++ b/sim/src/image.rs
@@ -23,6 +23,13 @@
DeviceName,
};
use crate::caps::Caps;
+use crate::depends::{
+ BoringDep,
+ Depender,
+ DepTest,
+ PairDep,
+ UpgradeInfo,
+};
use crate::tlv::{ManifestGen, TlvGen, TlvFlags, AES_SEC_KEY};
/// A builder for Images. This describes a single run of the simulator,
@@ -139,11 +146,17 @@
}
/// Construct an `Images` that doesn't expect an upgrade to happen.
- pub fn make_no_upgrade_image(self) -> Images {
+ pub fn make_no_upgrade_image(self, deps: &DepTest) -> Images {
+ let num_images = self.num_images();
let mut flash = self.flash;
- let images = self.slots.into_iter().map(|slots| {
- let primaries = install_image(&mut flash, &slots[0], 42784, false);
- let upgrades = install_image(&mut flash, &slots[1], 46928, false);
+ let images = self.slots.into_iter().enumerate().map(|(image_num, slots)| {
+ let dep: Box<dyn Depender> = if num_images > 1 {
+ Box::new(PairDep::new(num_images, image_num, deps))
+ } else {
+ Box::new(BoringDep(image_num))
+ };
+ let primaries = install_image(&mut flash, &slots[0], 42784, &*dep, false);
+ let upgrades = install_image(&mut flash, &slots[1], 46928, &*dep, false);
OneImage {
slots: slots,
primaries: primaries,
@@ -157,8 +170,8 @@
}
}
- pub fn make_image(self, permanent: bool) -> Images {
- let mut images = self.make_no_upgrade_image();
+ pub fn make_image(self, deps: &DepTest, permanent: bool) -> Images {
+ let mut images = self.make_no_upgrade_image(deps);
for image in &images.images {
mark_upgrade(&mut images.flash, &image.slots[1]);
}
@@ -177,9 +190,10 @@
pub fn make_bad_secondary_slot_image(self) -> Images {
let mut bad_flash = self.flash;
- let images = self.slots.into_iter().map(|slots| {
- let primaries = install_image(&mut bad_flash, &slots[0], 32784, false);
- let upgrades = install_image(&mut bad_flash, &slots[1], 41928, true);
+ let images = self.slots.into_iter().enumerate().map(|(image_num, slots)| {
+ let dep = BoringDep(image_num);
+ let primaries = install_image(&mut bad_flash, &slots[0], 32784, &dep, false);
+ let upgrades = install_image(&mut bad_flash, &slots[1], 41928, &dep, true);
OneImage {
slots: slots,
primaries: primaries,
@@ -298,6 +312,10 @@
}
}
}
+
+ pub fn num_images(&self) -> usize {
+ self.slots.len()
+ }
}
impl Images {
@@ -317,6 +335,14 @@
}
}
+ /// Test a simple upgrade, with dependencies given, and verify that the
+ /// image does as is described in the test.
+ pub fn run_check_deps(&self, deps: &DepTest) -> bool {
+ let (flash, _) = self.try_upgrade(None, true);
+
+ self.verify_dep_images(&flash, deps)
+ }
+
pub fn run_basic_revert(&self) -> bool {
if Caps::OverwriteUpgrade.present() {
return false;
@@ -961,6 +987,23 @@
true
}
+ /// Verify the images, according to the dependency test.
+ fn verify_dep_images(&self, flash: &SimMultiFlash, deps: &DepTest) -> bool {
+ for (image_num, (image, upgrade)) in self.images.iter().zip(deps.upgrades.iter()).enumerate() {
+ info!("Upgrade: slot:{}, {:?}", image_num, upgrade);
+ if !verify_image(flash, &image.slots[0],
+ match upgrade {
+ UpgradeInfo::Upgraded => &image.upgrades,
+ UpgradeInfo::Held => &image.primaries,
+ }) {
+ error!("Failed to upgrade properly: image: {}, upgrade: {:?}", image_num, upgrade);
+ return true;
+ }
+ }
+
+ false
+ }
+
/// Verify that at least one of the trailers of the images have the
/// specified values.
fn verify_trailers_loose(&self, flash: &SimMultiFlash, slot: usize,
@@ -1018,13 +1061,18 @@
/// Install a "program" into the given image. This fakes the image header, or at least all of the
/// fields used by the given code. Returns a copy of the image that was written.
fn install_image(flash: &mut SimMultiFlash, slot: &SlotInfo, len: usize,
- bad_sig: bool) -> ImageData {
+ deps: &dyn Depender, bad_sig: bool) -> ImageData {
let offset = slot.base_off;
let slot_len = slot.len;
let dev_id = slot.dev_id;
let mut tlv: Box<dyn ManifestGen> = Box::new(make_tlv());
+ // Add the dependencies early to the tlv.
+ for dep in deps.my_deps(offset, slot.index) {
+ tlv.add_dependency(deps.other_id(), &dep);
+ }
+
const HDR_SIZE: usize = 32;
// Generate a boot header. Note that the size doesn't include the header.
@@ -1035,12 +1083,7 @@
protect_tlv_size: tlv.protect_size(),
img_size: len as u32,
flags: tlv.get_flags(),
- ver: ImageVersion {
- major: (offset / (128 * 1024)) as u8,
- minor: 0,
- revision: 1,
- build_num: offset as u32,
- },
+ ver: deps.my_version(offset, slot.index),
_pad2: 0,
};
@@ -1219,8 +1262,8 @@
if buf != ©[..] {
for i in 0 .. buf.len() {
if buf[i] != copy[i] {
- info!("First failure for slot{} at {:#x} {:#x}!={:#x}",
- slot.index, offset + i, 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;
}
}
@@ -1309,7 +1352,7 @@
impl AsRaw for ImageHeader {}
#[repr(C)]
-#[derive(Clone)]
+#[derive(Clone, Debug)]
pub struct ImageVersion {
pub major: u8,
pub minor: u8,
@@ -1317,7 +1360,7 @@
pub build_num: u32,
}
-#[derive(Clone)]
+#[derive(Clone, Debug)]
pub struct SlotInfo {
pub base_off: usize,
pub trailer_off: usize,