sim: Add new ram-load test cases

Adds new test cases to various ram-load related logic.

Signed-off-by: Roland Mikhel <roland.mikhel@arm.com>
Change-Id: I3a0ca951b2c720be4e6fe2ed0e5d1830fcfb240c
diff --git a/sim/src/image.rs b/sim/src/image.rs
index 71f2d3c..54e4f31 100644
--- a/sim/src/image.rs
+++ b/sim/src/image.rs
@@ -123,6 +123,19 @@
     size: u32,
 }
 
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+pub enum ImageManipulation {
+    None,
+    BadSignature,
+    WrongOffset,
+    IgnoreRamLoadFlag,
+    /// True to use same address,
+    /// false to overlap by 1 byte
+    OverlapImages(bool),
+    CorruptHigherVersionImage,
+}
+
+
 impl ImagesBuilder {
     /// Construct a new image builder for the given device.  Returns
     /// Some(builder) if is possible to test this configuration, or None if
@@ -210,22 +223,37 @@
     }
 
     /// Construct an `Images` that doesn't expect an upgrade to happen.
-    pub fn make_no_upgrade_image(self, deps: &DepTest) -> Images {
+    pub fn make_no_upgrade_image(self, deps: &DepTest, img_manipulation: ImageManipulation) -> Images {
         let num_images = self.num_images();
         let mut flash = self.flash;
-        let ram = self.ram.clone();  // TODO: This is wasteful.
+        let ram = self.ram.clone();  // TODO: Avoid this clone.
+        let mut higher_version_corrupted = 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::new(image_num, deps))
             };
-            let primaries = install_image(&mut flash, &slots[0],
-                maximal(42784), &ram, &*dep, false, Some(0));
-            let upgrades = match deps.depends[image_num] {
-                DepType::NoUpgrade => install_no_image(),
-                _ => install_image(&mut flash, &slots[1],
-                    maximal(46928), &ram, &*dep, false, Some(0))
+
+            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));
+                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))
+                };
+                (prim, upgr)
+            } else {
+                let prim = install_image(&mut flash, &slots[0],
+                    maximal(42784), &ram, &*dep, img_manipulation, Some(0));
+                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))
+                    };
+                (prim, upgr)
             };
             OneImage {
                 slots,
@@ -243,7 +271,7 @@
     }
 
     pub fn make_image(self, deps: &DepTest, permanent: bool) -> Images {
-        let mut images = self.make_no_upgrade_image(deps);
+        let mut images = self.make_no_upgrade_image(deps, ImageManipulation::None);
         for image in &images.images {
             mark_upgrade(&mut images.flash, &image.slots[1]);
         }
@@ -274,9 +302,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, false, Some(0));
+                maximal(32784), &ram, &dep, ImageManipulation::None, Some(0));
             let upgrades = install_image(&mut bad_flash, &slots[1],
-                maximal(41928), &ram, &dep, true, Some(0));
+                maximal(41928), &ram, &dep, ImageManipulation::BadSignature, Some(0));
             OneImage {
                 slots,
                 primaries,
@@ -297,9 +325,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, false, Some(0));
+                maximal(32784), &ram, &dep, ImageManipulation::None, Some(0));
             let upgrades = install_image(&mut bad_flash, &slots[1],
-                ImageSize::Oversized, &ram, &dep, false, Some(0));
+                ImageSize::Oversized, &ram, &dep, ImageManipulation::None, Some(0));
             OneImage {
                 slots,
                 primaries,
@@ -320,7 +348,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, false, Some(0));
+                maximal(32784), &ram, &dep,ImageManipulation::None, Some(0));
             let upgrades = install_no_image();
             OneImage {
                 slots,
@@ -343,7 +371,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, false, Some(0));
+                maximal(32784), &ram, &dep, ImageManipulation::None, Some(0));
             OneImage {
                 slots,
                 primaries,
@@ -365,7 +393,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, false, Some(0));
+                ImageSize::Oversized, &ram, &dep, ImageManipulation::None, Some(0));
             OneImage {
                 slots,
                 primaries,
@@ -387,9 +415,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, false, security_cnt);
+                maximal(32784), &ram, &dep,  ImageManipulation::None, security_cnt);
             let upgrades = install_image(&mut flash, &slots[1],
-                maximal(41928), &ram, &dep, false, security_cnt.map(|v| v + 1));
+                maximal(41928), &ram, &dep, ImageManipulation::None, security_cnt.map(|v| v + 1));
             OneImage {
                 slots,
                 primaries,
@@ -1318,6 +1346,28 @@
         false
     }
 
+    pub fn run_ram_load_boot_with_result(&self, expected_result: bool) -> bool {
+        if !Caps::RamLoad.present() {
+            return false;
+        }
+        // Clone the flash so we can tell if unchanged.
+        let mut flash = self.flash.clone();
+
+        // Create RAM config.
+        let ram = RamBlock::new(self.ram.total - RAM_LOAD_ADDR, RAM_LOAD_ADDR);
+
+        // Run the bootloader, and verify that it couldn't run to completion.
+        let result = ram.invoke(|| c::boot_go(&mut flash, &self.areadesc, None,
+            None, true));
+
+        if result.success() != expected_result {
+            error!("RAM load boot result was not of the expected value! (was: {}, expected: {})", result.success(), expected_result);
+            return true;
+        }
+
+        false
+    }
+
     /// Adds a new flash area that fails statistically
     fn mark_bad_status_with_rate(&self, flash: &mut SimMultiFlash, slot: usize,
                                  rate: f32) {
@@ -1699,26 +1749,34 @@
 /// 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, bad_sig: bool, security_counter:Option<u32>) -> ImageData {
+                 deps: &dyn Depender, img_manipulation: ImageManipulation, security_counter:Option<u32>) -> ImageData {
     let 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 img_manipulation == ImageManipulation::IgnoreRamLoadFlag {
+        tlv.set_ignore_ram_load_flag();
+    }
 
     tlv.set_security_counter(security_counter);
 
+
     // 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;
-
     let place = ram.lookup(&slot);
     let load_addr = if Caps::RamLoad.present() {
-        place.offset
+        match img_manipulation {
+            ImageManipulation::WrongOffset => u32::MAX,
+            ImageManipulation::OverlapImages(true) => RAM_LOAD_ADDR,
+            ImageManipulation::OverlapImages(false) => place.offset - 1,
+            _ => place.offset
+        }
     } else {
         0
     };
@@ -1803,7 +1861,7 @@
     }
 
     // Build the TLV itself.
-    if bad_sig {
+    if img_manipulation == ImageManipulation::BadSignature  {
         tlv.corrupt_sig();
     }
     let mut b_tlv = tlv.make_tlv();
diff --git a/sim/src/lib.rs b/sim/src/lib.rs
index df1919e..fe43e46 100644
--- a/sim/src/lib.rs
+++ b/sim/src/lib.rs
@@ -1,6 +1,6 @@
 // Copyright (c) 2017-2019 Linaro LTD
 // Copyright (c) 2017-2019 JUUL Labs
-// Copyright (c) 2019 Arm Limited
+// Copyright (c) 2019-2023 Arm Limited
 //
 // SPDX-License-Identifier: Apache-2.0
 
@@ -30,6 +30,7 @@
     image::{
         ImagesBuilder,
         Images,
+        ImageManipulation,
         show_sizes,
     },
 };
@@ -201,7 +202,7 @@
 
         failed |= bad_secondary_slot_image.run_signfail_upgrade();
 
-        let images = run.clone().make_no_upgrade_image(&NO_DEPS);
+        let images = run.clone().make_no_upgrade_image(&NO_DEPS, ImageManipulation::None);
         failed |= images.run_norevert_newimage();
 
         let images = run.make_image(&NO_DEPS, true);
diff --git a/sim/src/tlv.rs b/sim/src/tlv.rs
index 99c02d9..5541f11 100644
--- a/sim/src/tlv.rs
+++ b/sim/src/tlv.rs
@@ -112,6 +112,10 @@
 
     /// Set the security counter to the specified value.
     fn set_security_counter(&mut self, security_cnt: Option<u32>);
+
+    /// Sets the ignore_ram_load_flag so that can be validated when it is missing,
+    /// it will not load successfully.
+    fn set_ignore_ram_load_flag(&mut self);
 }
 
 #[derive(Debug, Default)]
@@ -124,6 +128,8 @@
     /// Should this signature be corrupted.
     gen_corrupted: bool,
     security_cnt: Option<u32>,
+    /// Ignore RAM_LOAD flag
+    ignore_ram_load_flag: bool,
 }
 
 #[derive(Debug)]
@@ -318,7 +324,7 @@
     /// Retrieve the header flags for this configuration.  This can be called at any time.
     fn get_flags(&self) -> u32 {
         // For the RamLoad case, add in the flag for this feature.
-        if Caps::RamLoad.present() {
+        if Caps::RamLoad.present() && !self.ignore_ram_load_flag {
             self.flags | (TlvFlags::RAM_LOAD as u32)
         } else {
             self.flags
@@ -793,6 +799,10 @@
     fn set_security_counter(&mut self, security_cnt: Option<u32>) {
         self.security_cnt = security_cnt;
     }
+
+    fn set_ignore_ram_load_flag(&mut self) {
+        self.ignore_ram_load_flag = true;
+    }
 }
 
 include!("rsa_pub_key-rs.txt");