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/depends.rs b/sim/src/depends.rs
new file mode 100644
index 0000000..9036d8d
--- /dev/null
+++ b/sim/src/depends.rs
@@ -0,0 +1,133 @@
+//! Support and tests related to the dependency management for multi-image
+//! support.
+
+use crate::image::ImageVersion;
+
+pub trait Depender {
+    /// Generate a version for this particular image.  The slot indicates
+    /// which slot this is being put in.
+    fn my_version(&self, offset: usize, slot: usize) -> ImageVersion;
+
+    /// Return dependencies for this image/slot combination.
+    fn my_deps(&self, offset: usize, slot: usize) -> Vec<ImageVersion>;
+
+    /// Return the image ID of the other version.
+    fn other_id(&self) -> u8;
+}
+
+/// A boring image is used when we aren't testing dependencies.  There will
+/// be meaningful version numbers.  The size field is the image number we
+/// are.
+pub struct BoringDep(pub usize);
+
+impl Depender for BoringDep {
+    fn my_version(&self, _offset: usize, slot: usize) -> ImageVersion {
+        ImageVersion::new_synthetic(self.0 as u8, slot as u8, 0)
+    }
+
+    fn my_deps(&self, _offset: usize, _slot: usize) -> Vec<ImageVersion> {
+        vec![]
+    }
+
+    fn other_id(&self) -> u8 {
+        0
+    }
+}
+
+/// An individual test of the dependency mechanism describes one of the
+/// possibilities for the dependency information for each image, and what
+/// the expected outcome is.
+#[derive(Clone, Debug)]
+pub struct DepTest {
+    /// What kinds of dependency should be installed in the image.
+    pub depends: [DepType; 2],
+
+    /// What is the expected outcome of the upgrade.
+    pub upgrades: [UpgradeInfo; 2],
+}
+
+/// Describes the various types of dependency information that can be
+/// provided.
+#[derive(Clone, Debug)]
+pub enum DepType {
+    /// Do not include dependency information
+    Nothing,
+    /// Provide dependency information that matches the other image.
+    Correct,
+    /// Provide dependency information describing something newer than the
+    /// other image.
+    Newer,
+}
+
+/// Describes what our expectation is for an upgrade.
+#[derive(Clone, Debug)]
+pub enum UpgradeInfo {
+    /// The current version should be held.
+    Held,
+    /// The image should be upgraded
+    Upgraded,
+}
+
+/// A "test" that gives no dependency information.
+pub static NO_DEPS: DepTest = DepTest {
+    depends: [DepType::Nothing, DepType::Nothing],
+    upgrades: [UpgradeInfo::Upgraded, UpgradeInfo::Upgraded],
+};
+
+/// A PairDep describes the dependencies between two pairs.
+pub struct PairDep {
+    /// The image number of this image.
+    number: usize,
+
+    test: DepTest,
+}
+
+impl PairDep {
+    pub fn new(total_image: usize, my_image: usize, deps: &DepTest) -> PairDep {
+        if total_image != 2 {
+            panic!("PairDep only works when there are two images");
+        }
+
+        PairDep {
+            number: my_image,
+            test: deps.clone(),
+        }
+    }
+}
+
+impl Depender for PairDep {
+    fn my_version(&self, _offset: usize, slot: usize) -> ImageVersion {
+        ImageVersion::new_synthetic(self.number as u8, slot as u8, 0)
+    }
+
+    fn my_deps(&self, _offset: usize, slot: usize) -> Vec<ImageVersion> {
+        match self.test.depends[slot] {
+            DepType::Nothing => vec![],
+            DepType::Correct => vec![
+                ImageVersion::new_synthetic(self.other_id(), slot as u8, 0)
+            ],
+            DepType::Newer => vec![
+                ImageVersion::new_synthetic(self.other_id(), slot as u8, 1)
+            ],
+        }
+    }
+
+    fn other_id(&self) -> u8 {
+        (1 - self.number) as u8
+    }
+}
+
+impl ImageVersion {
+    /// Generate an image version based on some key information.  The image
+    /// number influences the major version number (by an arbitrary factor),
+    /// and the slot affects the major number on the build_number.  The minor
+    /// number can also be given to force numbers to be different.
+    fn new_synthetic(image_id: u8, slot: u8, minor: u8) -> ImageVersion {
+        ImageVersion {
+            major: image_id * 20 + slot,
+            minor: minor,
+            revision: 1,
+            build_num: slot as u32,
+        }
+    }
+}
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 != &copy[..] {
         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,
diff --git a/sim/src/lib.rs b/sim/src/lib.rs
index 1ed75dd..c8e8963 100644
--- a/sim/src/lib.rs
+++ b/sim/src/lib.rs
@@ -7,13 +7,21 @@
 use serde_derive::Deserialize;
 
 mod caps;
+mod depends;
 mod image;
 mod tlv;
 pub mod testlog;
 
-pub use crate::image::{
-    ImagesBuilder,
-    show_sizes,
+pub use crate::{
+    depends::{
+        DepTest,
+        DepType,
+        UpgradeInfo,
+        NO_DEPS,},
+    image::{
+        ImagesBuilder,
+        show_sizes,
+    },
 };
 
 const USAGE: &'static str = "
@@ -179,10 +187,10 @@
 
         failed |= bad_secondary_slot_image.run_signfail_upgrade();
 
-        let images = run.clone().make_no_upgrade_image();
+        let images = run.clone().make_no_upgrade_image(&NO_DEPS);
         failed |= images.run_norevert_newimage();
 
-        let images = run.make_image(true);
+        let images = run.make_image(&NO_DEPS, true);
 
         failed |= images.run_basic_revert();
         failed |= images.run_revert_with_fails();
diff --git a/sim/src/tlv.rs b/sim/src/tlv.rs
index 43dd2e2..c6f30dc 100644
--- a/sim/src/tlv.rs
+++ b/sim/src/tlv.rs
@@ -26,7 +26,7 @@
 use mcuboot_sys::c;
 
 #[repr(u8)]
-#[derive(Copy, Clone, PartialEq, Eq)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
 #[allow(dead_code)] // TODO: For now
 pub enum TlvKinds {
     KEYHASH = 0x01,
@@ -74,6 +74,7 @@
     fn make_tlv(self: Box<Self>) -> Vec<u8>;
 }
 
+#[derive(Debug)]
 pub struct TlvGen {
     flags: u32,
     kinds: Vec<TlvKinds>,
@@ -85,6 +86,7 @@
     dependencies: Vec<Dependency>,
 }
 
+#[derive(Debug)]
 struct Dependency {
     id: u8,
     version: ImageVersion,