Infineon: Switch to 1.9.0 code base, add xmc7000 family support, refactor memory layer
diff --git a/sim/Cargo.toml b/sim/Cargo.toml
index b80dbb2..3d443e2 100644
--- a/sim/Cargo.toml
+++ b/sim/Cargo.toml
@@ -29,8 +29,8 @@
 multiimage = ["mcuboot-sys/multiimage"]
 ram-load = ["mcuboot-sys/ram-load"]
 direct-xip = ["mcuboot-sys/direct-xip"]
-large-write = []
 downgrade-prevention = ["mcuboot-sys/downgrade-prevention"]
+max-align-32 = ["mcuboot-sys/max-align-32"]
 
 [dependencies]
 byteorder = "1.3"
diff --git a/sim/README.rst b/sim/README.rst
index d07bc11..fb9012b 100644
--- a/sim/README.rst
+++ b/sim/README.rst
@@ -1,4 +1,4 @@
-MCUboot Simulator
+MCUboot simulator
 #################
 
 This is a small simulator designed to exercise the mcuboot upgrade
diff --git a/sim/mcuboot-sys/Cargo.toml b/sim/mcuboot-sys/Cargo.toml
index e3a00cb..7f2ee83 100644
--- a/sim/mcuboot-sys/Cargo.toml
+++ b/sim/mcuboot-sys/Cargo.toml
@@ -82,9 +82,8 @@
 # Check (in software) against version downgrades.
 downgrade-prevention = []
 
-# Large write.  Not meaningful, but present here so that the
-# full-suite tests will work for this configuration.
-large-write = []
+# Support images with 32-byte maximum write alignment value.
+max-align-32 = []
 
 [build-dependencies]
 cc = "1.0.25"
@@ -93,8 +92,3 @@
 libc = "0.2"
 log = "0.4"
 simflash = { path = "../simflash" }
-
-# Optimize some, even when building for debugging, otherwise the tests
-# are too slow.
-[profile.test]
-opt-level = 1
diff --git a/sim/mcuboot-sys/build.rs b/sim/mcuboot-sys/build.rs
index 1a08741..294aea6 100644
--- a/sim/mcuboot-sys/build.rs
+++ b/sim/mcuboot-sys/build.rs
@@ -34,6 +34,7 @@
     let downgrade_prevention = env::var("CARGO_FEATURE_DOWNGRADE_PREVENTION").is_ok();
     let ram_load = env::var("CARGO_FEATURE_RAM_LOAD").is_ok();
     let direct_xip = env::var("CARGO_FEATURE_DIRECT_XIP").is_ok();
+    let max_align_32 = env::var("CARGO_FEATURE_MAX_ALIGN_32").is_ok();
 
     let mut conf = CachedBuild::new();
     conf.conf.define("__BOOTSIM__", None);
@@ -41,6 +42,13 @@
     conf.conf.define("MCUBOOT_USE_FLASH_AREA_GET_SECTORS", None);
     conf.conf.define("MCUBOOT_HAVE_ASSERT_H", None);
     conf.conf.define("MCUBOOT_MAX_IMG_SECTORS", Some("128"));
+
+    if max_align_32 {
+        conf.conf.define("MCUBOOT_BOOT_MAX_ALIGN", Some("32"));
+    } else {
+        conf.conf.define("MCUBOOT_BOOT_MAX_ALIGN", Some("8"));
+    }
+
     conf.conf.define("MCUBOOT_IMAGE_NUMBER", Some(if multiimage { "2" } else { "1" }));
 
     if downgrade_prevention && !overwrite_only {
@@ -163,9 +171,12 @@
         conf.conf.define("CONFIG_BOOT_SWAP_USING_SCRATCH", None);
         conf.conf.define("MCUBOOT_SWAP_USING_SCRATCH", None);
     }
+
     if swap_status {
         conf.conf.define("MCUBOOT_SWAP_USING_STATUS", None);
-        conf.conf.define("CY_FLASH_ALIGN", "512");
+        conf.conf.define("MEMORY_ALIGN", "512");
+        conf.conf.define("PLATFORM_MAX_TRAILER_PAGE_SIZE", "512");
+        conf.conf.define("SLOTS_FOR_IMAGE", "2");
         conf.conf.file("../../boot/bootutil/src/swap_status.c");
         conf.conf.file("../../boot/bootutil/src/swap_status_part.c");
         conf.conf.file("../../boot/bootutil/src/swap_status_misc.c");
@@ -375,6 +386,7 @@
     conf.file("../../boot/bootutil/src/fault_injection_hardening.c");
     conf.file("csupport/run.c");
     conf.conf.include("../../boot/bootutil/include");
+    conf.conf.include("../../boot/boot/bootutil/include/bootutil/fault_injection_hardening.h");
     conf.conf.include("csupport");
     conf.conf.include("../../boot/zephyr/include");
     conf.conf.debug(true);
diff --git a/sim/mcuboot-sys/csupport/devicetree.h b/sim/mcuboot-sys/csupport/devicetree.h
index 22a7fe6..3c96493 100644
--- a/sim/mcuboot-sys/csupport/devicetree.h
+++ b/sim/mcuboot-sys/csupport/devicetree.h
@@ -20,7 +20,8 @@
 #define FLASH_AREA_ID_image_3 5
 
 /*
- * PSoC6 area defines based on file:
+ * Flash area defines are calculated inside of FLASH_AREA_IMAGE_PRIMARY()
+ * and FLASH_AREA_IMAGE_SECONDARY(), file
  * boot/cypress/MCUBootApp/sysflash/sysflash.h
 */
 #define FLASH_AREA_IMAGE_0 1
diff --git a/sim/mcuboot-sys/csupport/run.c b/sim/mcuboot-sys/csupport/run.c
index fd6c3ca..07b09ad 100644
--- a/sim/mcuboot-sys/csupport/run.c
+++ b/sim/mcuboot-sys/csupport/run.c
@@ -43,7 +43,7 @@
         uint32_t size);
 extern int sim_flash_write(uint8_t flash_id, uint32_t offset, const uint8_t *src,
         uint32_t size);
-extern uint16_t sim_flash_align(uint8_t flash_id);
+extern uint32_t sim_flash_align(uint8_t flash_id);
 extern uint8_t sim_flash_erased_val(uint8_t flash_id);
 
 struct sim_context {
@@ -222,7 +222,7 @@
 #endif
 }
 
-size_t flash_area_align(const struct flash_area *area)
+uint32_t flash_area_align(const struct flash_area *area)
 {
     return (size_t)sim_flash_align(area->fa_device_id);
 }
@@ -245,7 +245,7 @@
 };
 
 int invoke_boot_go(struct sim_context *ctx, struct area_desc *adesc,
-                   struct boot_rsp *rsp)
+                   struct boot_rsp *rsp, int image_id)
 {
     int res;
     struct boot_loader_state *state;
@@ -257,14 +257,28 @@
     mbedtls_platform_set_calloc_free(calloc, free);
 #endif
 
-    // NOTE: cleared internally by context_boot_go
     state = malloc(sizeof(struct boot_loader_state));
 
     sim_set_flash_areas(adesc);
     sim_set_context(ctx);
 
     if (setjmp(ctx->boot_jmpbuf) == 0) {
-        res = context_boot_go(state, rsp);
+        boot_state_clear(state);
+
+#if BOOT_IMAGE_NUMBER > 1
+        if (image_id >= 0) {
+            memset(state->img_mask, 1, sizeof(state->img_mask));
+            state->img_mask[image_id] = 0;
+        }
+#else
+        (void) image_id;
+#endif /* BOOT_IMAGE_NUMBER > 1 */
+
+#if defined(MCUBOOT_RAM_LOAD)
+        res = context_boot_go_ram(state, rsp);
+#else
+        res = context_boot_go_flash(state, rsp);
+#endif
         sim_reset_flash_areas();
         sim_reset_context();
         free(state);
@@ -357,8 +371,8 @@
 
 // Align offset and length to sector size
 #ifdef MCUBOOT_SWAP_USING_STATUS
-    uint32_t sect_off = off / CY_FLASH_ALIGN * CY_FLASH_ALIGN;
-    len = ((off + len - 1) / CY_FLASH_ALIGN + 1) * CY_FLASH_ALIGN - sect_off;
+    uint32_t sect_off = off / MEMORY_ALIGN * MEMORY_ALIGN;
+    len = ((off + len - 1) / MEMORY_ALIGN + 1) * MEMORY_ALIGN - sect_off;
     off = sect_off;
     BOOT_LOG_SIM("%s: erase with aligment at area=%d, off=%x, len=%x", __func__, area->fa_id, off, len);
 #endif
@@ -476,5 +490,5 @@
 
 uint32_t boot_magic_sz(void)
 {
-    return BOOT_MAGIC_SZ;
+    return BOOT_MAGIC_ALIGN_SIZE;
 }
diff --git a/sim/mcuboot-sys/csupport/storage/flash_map.h b/sim/mcuboot-sys/csupport/storage/flash_map.h
index 7b20453..2438f70 100644
--- a/sim/mcuboot-sys/csupport/storage/flash_map.h
+++ b/sim/mcuboot-sys/csupport/storage/flash_map.h
@@ -124,7 +124,7 @@
 /*
  * Alignment restriction for flash writes.
  */
-size_t flash_area_align(const struct flash_area *);
+uint32_t flash_area_align(const struct flash_area *);
 
 /*
  * What is value is read from erased flash bytes.
diff --git a/sim/mcuboot-sys/src/api.rs b/sim/mcuboot-sys/src/api.rs
index 8d1140d..624b3e9 100644
--- a/sim/mcuboot-sys/src/api.rs
+++ b/sim/mcuboot-sys/src/api.rs
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2019 Linaro LTD
+// Copyright (c) 2017-2021 Linaro LTD
 // Copyright (c) 2018-2019 JUUL Labs
 //
 // SPDX-License-Identifier: Apache-2.0
@@ -20,7 +20,7 @@
 pub type FlashMap = HashMap<u8, FlashPtr>;
 
 pub struct FlashParamsStruct {
-    align: u16,
+    align: u32,
     erased_val: u8,
 }
 
@@ -146,7 +146,7 @@
 pub fn set_flash(dev_id: u8, dev: &mut dyn Flash) {
     THREAD_CTX.with(|ctx| {
         ctx.borrow_mut().flash_params.insert(dev_id, FlashParamsStruct {
-            align: dev.align() as u16,
+            align: dev.align() as u32,
             erased_val: dev.erased_val(),
         });
         unsafe {
@@ -272,7 +272,7 @@
 }
 
 #[no_mangle]
-pub extern fn sim_flash_align(id: u8) -> u16 {
+pub extern fn sim_flash_align(id: u8) -> u32 {
     THREAD_CTX.with(|ctx| {
         ctx.borrow().flash_params.get(&id).unwrap().align
     })
diff --git a/sim/mcuboot-sys/src/area.rs b/sim/mcuboot-sys/src/area.rs
index cfbebda..882152f 100644
--- a/sim/mcuboot-sys/src/area.rs
+++ b/sim/mcuboot-sys/src/area.rs
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2019 Linaro LTD
+// Copyright (c) 2017-2021 Linaro LTD
 // Copyright (c) 2018-2019 JUUL Labs
 // Copyright (c) 2019 Arm Limited
 //
diff --git a/sim/mcuboot-sys/src/c.rs b/sim/mcuboot-sys/src/c.rs
index 5c791b8..e9bac0a 100644
--- a/sim/mcuboot-sys/src/c.rs
+++ b/sim/mcuboot-sys/src/c.rs
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2019 Linaro LTD
+// Copyright (c) 2017-2021 Linaro LTD
 // Copyright (c) 2017-2019 JUUL Labs
 // Copyright (c) 2019-2021 Arm Limited
 //
@@ -64,7 +64,8 @@
 
 /// Invoke the bootloader on this flash device.
 pub fn boot_go(multiflash: &mut SimMultiFlash, areadesc: &AreaDesc,
-               counter: Option<&mut i32>, catch_asserts: bool) -> BootGoResult {
+               counter: Option<&mut i32>, image_index: Option<i32>,
+               catch_asserts: bool) -> BootGoResult {
     for (&dev_id, flash) in multiflash.iter_mut() {
         api::set_flash(dev_id, flash);
     }
@@ -83,9 +84,16 @@
         flash_dev_id: 0,
         image_off: 0,
     };
-    let result = unsafe {
-        raw::invoke_boot_go(&mut sim_ctx as *mut _, &areadesc.get_c() as *const _,
-            &mut rsp as *mut _) as i32
+    let result: i32 = unsafe {
+        match image_index {
+            None => raw::invoke_boot_go(&mut sim_ctx as *mut _,
+                                        &areadesc.get_c() as *const _,
+                                        &mut rsp as *mut _, -1) as i32,
+            Some(i) => raw::invoke_boot_go(&mut sim_ctx as *mut _,
+                                           &areadesc.get_c() as *const _,
+                                           &mut rsp as *mut _,
+                                           i as i32) as i32
+        }
     };
     let asserts = sim_ctx.c_asserts;
     if let Some(c) = counter {
@@ -151,7 +159,7 @@
         // be any way to get rid of this warning.  See https://github.com/rust-lang/rust/issues/34798
         // for information and tracking.
         pub fn invoke_boot_go(sim_ctx: *mut CSimContext, areadesc: *const CAreaDesc,
-            rsp: *mut BootRsp) -> libc::c_int;
+            rsp: *mut BootRsp, image_index: libc::c_int) -> libc::c_int;
 
         pub fn boot_trailer_sz(min_write_sz: u32) -> u32;
         pub fn boot_status_sz(min_write_sz: u32) -> u32;
diff --git a/sim/simflash/src/lib.rs b/sim/simflash/src/lib.rs
index e5ccb96..0c47c56 100644
--- a/sim/simflash/src/lib.rs
+++ b/sim/simflash/src/lib.rs
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2019 Linaro LTD
+// Copyright (c) 2017-2021 Linaro LTD
 // Copyright (c) 2017-2018 JUUL Labs
 //
 // SPDX-License-Identifier: Apache-2.0
diff --git a/sim/simflash/src/pdump.rs b/sim/simflash/src/pdump.rs
index 6243065..b2f403f 100644
--- a/sim/simflash/src/pdump.rs
+++ b/sim/simflash/src/pdump.rs
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Linaro LTD
+// Copyright (c) 2017,2021 Linaro LTD
 //
 // SPDX-License-Identifier: Apache-2.0
 
diff --git a/sim/src/caps.rs b/sim/src/caps.rs
index 3fbf4c3..5b1b8e5 100644
--- a/sim/src/caps.rs
+++ b/sim/src/caps.rs
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2019 Linaro LTD
+// Copyright (c) 2017-2021 Linaro LTD
 // Copyright (c) 2019 JUUL Labs
 // Copyright (c) 2019-2021 Arm Limited
 //
@@ -37,6 +37,11 @@
         (caps as u32) & (self as u32) != 0
     }
 
+    /// Does this build have ECDSA of some type enabled for signatures.
+    pub fn has_ecdsa() -> bool {
+        Caps::EcdsaP256.present() || Caps::EcdsaP224.present()
+    }
+
     /// Query for the number of images that have been configured into this
     /// MCUboot build.
     pub fn get_num_images() -> usize {
diff --git a/sim/src/depends.rs b/sim/src/depends.rs
index a67bcd8..229b3e2 100644
--- a/sim/src/depends.rs
+++ b/sim/src/depends.rs
@@ -1,4 +1,4 @@
-// Copyright (c) 2019 Linaro LTD
+// Copyright (c) 2019-2021 Linaro LTD
 //
 // SPDX-License-Identifier: Apache-2.0
 
diff --git a/sim/src/image.rs b/sim/src/image.rs
index 29ddedd..dbfb5fe 100644
--- a/sim/src/image.rs
+++ b/sim/src/image.rs
@@ -1,4 +1,4 @@
-// Copyright (c) 2019 Linaro LTD
+// Copyright (c) 2019-2021 Linaro LTD
 // Copyright (c) 2019-2020 JUUL Labs
 // Copyright (c) 2019-2021 Arm Limited
 //
@@ -54,6 +54,7 @@
     UpgradeInfo,
 };
 use crate::tlv::{ManifestGen, TlvGen, TlvFlags};
+use crate::utils::align_up;
 use typenum::{U32, U16};
 
 /// For testing, use a non-zero offset for the ram-load, to make sure the offset is getting used
@@ -219,10 +220,12 @@
             } else {
                 Box::new(BoringDep::new(image_num, deps))
             };
-            let primaries = install_image(&mut flash, &slots[0], 42784, &ram, &*dep, false);
+            let primaries = install_image(&mut flash, &slots[0],
+                42784, &ram, &*dep, false);
             let upgrades = match deps.depends[image_num] {
                 DepType::NoUpgrade => install_no_image(),
-                _ => install_image(&mut flash, &slots[1], 46928, &ram, &*dep, false)
+                _ => install_image(&mut flash, &slots[1],
+                    46928, &ram, &*dep, false)
             };
             OneImage {
                 slots,
@@ -270,8 +273,10 @@
         let ram = self.ram.clone(); // TODO: Avoid this clone.
         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], 32784, &ram, &dep, false);
-            let upgrades = install_image(&mut bad_flash, &slots[1], 41928, &ram, &dep, true);
+            let primaries = install_image(&mut bad_flash, &slots[0],
+                32784, &ram, &dep, false);
+            let upgrades = install_image(&mut bad_flash, &slots[1],
+                41928, &ram, &dep, true);
             OneImage {
                 slots,
                 primaries,
@@ -291,7 +296,8 @@
         let ram = self.ram.clone(); // TODO: Avoid this clone.
         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], 32784, &ram, &dep, false);
+            let primaries = install_image(&mut flash, &slots[0],
+                32784, &ram, &dep, false);
             let upgrades = install_no_image();
             OneImage {
                 slots,
@@ -313,7 +319,8 @@
         let images = self.slots.into_iter().enumerate().map(|(image_num, slots)| {
             let dep = BoringDep::new(image_num, &NO_DEPS);
             let primaries = install_no_image();
-            let upgrades = install_image(&mut flash, &slots[1], 32784, &ram, &dep, false);
+            let upgrades = install_image(&mut flash, &slots[1],
+                32784, &ram, &dep, false);
             OneImage {
                 slots,
                 primaries,
@@ -333,9 +340,13 @@
         match device {
             DeviceName::Stm32f4 => {
                 // STM style flash.  Large sectors, with a large scratch area.
-                let dev = SimFlash::new(vec![16 * 1024, 16 * 1024, 16 * 1024, 16 * 1024,
-                                        64 * 1024,
-                                        128 * 1024, 128 * 1024, 128 * 1024],
+                // The flash layout as described is not present in any real STM32F4 device, but it
+                // serves to exercise support for sectors of varying sizes inside a single slot,
+                // as long as they are compatible in both slots and all fit in the scratch.
+                let dev = SimFlash::new(vec![16 * 1024, 16 * 1024, 16 * 1024, 16 * 1024, 64 * 1024,
+                                        32 * 1024, 32 * 1024, 64 * 1024,
+                                        32 * 1024, 32 * 1024, 64 * 1024,
+                                        128 * 1024],
                                         align as usize, erased_val);
                 let dev_id = 0;
                 let mut areadesc = AreaDesc::new();
@@ -493,7 +504,7 @@
         if Caps::Bootstrap.present() {
             info!("Try bootstraping image in the primary");
 
-            if !c::boot_go(&mut flash, &self.areadesc, None, false).success() {
+            if !c::boot_go(&mut flash, &self.areadesc, None, None, false).success() {
                 warn!("Failed first boot");
                 fails += 1;
             }
@@ -674,7 +685,7 @@
         info!("Try norevert");
 
         // First do a normal upgrade...
-        if !c::boot_go(&mut flash, &self.areadesc, None, false).success() {
+        if !c::boot_go(&mut flash, &self.areadesc, None, None, false).success() {
             warn!("Failed first boot");
             fails += 1;
         }
@@ -707,7 +718,7 @@
             fails += 1;
         }
 
-        if !c::boot_go(&mut flash, &self.areadesc, None, false).success() {
+        if !c::boot_go(&mut flash, &self.areadesc, None, None, false).success() {
             warn!("Failed second boot");
             fails += 1;
         }
@@ -742,7 +753,7 @@
         info!("Try no downgrade");
 
         // First, do a normal upgrade.
-        if !c::boot_go(&mut flash, &self.areadesc, None, false).success() {
+        if !c::boot_go(&mut flash, &self.areadesc, None, None, false).success() {
             warn!("Failed first boot");
             fails += 1;
         }
@@ -784,7 +795,7 @@
         }
 
         // Run the bootloader...
-        if !c::boot_go(&mut flash, &self.areadesc, None, false).success() {
+        if !c::boot_go(&mut flash, &self.areadesc, None, None, false).success() {
             warn!("Failed first boot");
             fails += 1;
         }
@@ -838,7 +849,7 @@
         }
 
         // Run the bootloader...
-        if !c::boot_go(&mut flash, &self.areadesc, None, false).success() {
+        if !c::boot_go(&mut flash, &self.areadesc, None, None, false).success() {
             warn!("Failed first boot");
             fails += 1;
         }
@@ -878,7 +889,7 @@
         self.mark_upgrades(&mut flash, 1);
 
         // Run the bootloader...
-        if !c::boot_go(&mut flash, &self.areadesc, None, false).success() {
+        if !c::boot_go(&mut flash, &self.areadesc, None, None, false).success() {
             warn!("Failed first boot");
             fails += 1;
         }
@@ -925,7 +936,7 @@
         self.mark_permanent_upgrades(&mut flash, 1);
         self.mark_bad_status_with_rate(&mut flash, 0, 1.0);
 
-        let result = c::boot_go(&mut flash, &self.areadesc, None, true);
+        let result = c::boot_go(&mut flash, &self.areadesc, None, None, true);
         if !result.success() {
             warn!("Failed!");
             fails += 1;
@@ -951,7 +962,7 @@
 
         info!("validate primary slot enabled; \
                re-run of boot_go should just work");
-        if !c::boot_go(&mut flash, &self.areadesc, None, false).success() {
+        if !c::boot_go(&mut flash, &self.areadesc, None, None, false).success() {
             warn!("Failed!");
             fails += 1;
         }
@@ -983,7 +994,8 @@
             self.mark_bad_status_with_rate(&mut flash, 0, 0.5);
 
             // Should not fail, writing to bad regions does not assert
-            let asserts = c::boot_go(&mut flash, &self.areadesc, Some(&mut count), true).asserts();
+            let asserts = c::boot_go(&mut flash, &self.areadesc,
+                                     Some(&mut count), None, true).asserts();
             if asserts != 0 {
                 warn!("At least one assert() was called");
                 fails += 1;
@@ -992,7 +1004,8 @@
             self.reset_bad_status(&mut flash, 0);
 
             info!("Resuming an interrupted swap operation");
-            let asserts = c::boot_go(&mut flash, &self.areadesc, None, true).asserts();
+            let asserts = c::boot_go(&mut flash, &self.areadesc, None, None,
+                                     true).asserts();
 
             // This might throw no asserts, for large sector devices, where
             // a single failure writing is indistinguishable from no failure,
@@ -1019,7 +1032,8 @@
             self.mark_bad_status_with_rate(&mut flash, 0, 1.0);
 
             // This is expected to fail while writing to bad regions...
-            let asserts = c::boot_go(&mut flash, &self.areadesc, None, true).asserts();
+            let asserts = c::boot_go(&mut flash, &self.areadesc, None, None,
+                                     true).asserts();
             if asserts == 0 {
                 warn!("No assert() detected");
                 fails += 1;
@@ -1039,7 +1053,7 @@
         // Clone the flash so we can tell if unchanged.
         let mut flash = self.flash.clone();
 
-        let result = c::boot_go(&mut flash, &self.areadesc, None, true);
+        let result = c::boot_go(&mut flash, &self.areadesc, None, None, true);
 
         // Ensure the boot was successful.
         let resp = if let Some(resp) = result.resp() {
@@ -1073,7 +1087,8 @@
         // println!("Ram: {:#?}", self.ram);
 
         // Verify that the images area loaded into this.
-        let result = ram.invoke(|| c::boot_go(&mut flash, &self.areadesc, None, true));
+        let result = ram.invoke(|| c::boot_go(&mut flash, &self.areadesc, None,
+                                              None, true));
         if !result.success() {
             error!("Failed to execute ram-load");
             return true;
@@ -1101,6 +1116,50 @@
         return false;
     }
 
+    /// Test the split ram-loading.
+    pub fn run_split_ram_load(&self) -> bool {
+        if !Caps::RamLoad.present() {
+            return false;
+        }
+
+        // Clone the flash so we can tell if unchanged.
+        let mut flash = self.flash.clone();
+
+        // Setup ram based on the ram configuration we determined earlier for the images.
+        let ram = RamBlock::new(self.ram.total - RAM_LOAD_ADDR, RAM_LOAD_ADDR);
+
+        for (idx, _image) in (&self.images).iter().enumerate() {
+            // Verify that the images area loaded into this.
+            let result = ram.invoke(|| c::boot_go(&mut flash, &self.areadesc,
+                                                  None, Some(idx as i32), true));
+            if !result.success() {
+                error!("Failed to execute ram-load");
+                return true;
+            }
+        }
+
+        // Verify each image.
+        for image in &self.images {
+            let place = self.ram.lookup(&image.slots[0]);
+            let ram_image = ram.borrow_part(place.offset as usize - RAM_LOAD_ADDR as usize,
+                place.size as usize);
+            let src_sz = image.upgrades.size();
+            if src_sz > ram_image.len() {
+                error!("Image ended up too large, nonsensical");
+                return true;
+            }
+            let src_image = &image.upgrades.plain[0..src_sz];
+            let ram_image = &ram_image[0..src_sz];
+            if ram_image != src_image {
+                error!("Image not loaded correctly");
+                return true;
+            }
+
+        }
+
+        return false;
+    }
+
     /// Adds a new flash area that fails statistically
     fn mark_bad_status_with_rate(&self, flash: &mut SimMultiFlash, slot: usize,
                                  rate: f32) {
@@ -1150,7 +1209,10 @@
 
         let mut counter = stop.unwrap_or(0);
 
-        let (first_interrupted, count) = match c::boot_go(&mut flash, &self.areadesc, Some(&mut counter), false) {
+        let (first_interrupted, count) = match c::boot_go(&mut flash,
+                                                          &self.areadesc,
+                                                          Some(&mut counter),
+                                                          None, false) {
             x if x.interrupted() => (true, stop.unwrap()),
             x if x.success() => (false, -counter),
             x => panic!("Unknown return: {:?}", x),
@@ -1159,7 +1221,8 @@
         counter = 0;
         if first_interrupted {
             // fl.dump();
-            match c::boot_go(&mut flash, &self.areadesc, Some(&mut counter), false) {
+            match c::boot_go(&mut flash, &self.areadesc, Some(&mut counter),
+                             None, false) {
                 x if x.interrupted() => panic!("Shouldn't stop again"),
                 x if x.success() => (),
                 x => panic!("Unknown return: {:?}", x),
@@ -1175,7 +1238,7 @@
         // fl.write_file("image0.bin").unwrap();
         for i in 0 .. count {
             info!("Running boot pass {}", i + 1);
-            assert!(c::boot_go(&mut flash, &self.areadesc, None, false).success_no_asserts());
+            assert!(c::boot_go(&mut flash, &self.areadesc, None, None, false).success_no_asserts());
         }
         flash
     }
@@ -1185,7 +1248,8 @@
         let mut fails = 0;
 
         let mut counter = stop;
-        if !c::boot_go(&mut flash, &self.areadesc, Some(&mut counter), false).interrupted() {
+        if !c::boot_go(&mut flash, &self.areadesc, Some(&mut counter), None,
+                       false).interrupted() {
             warn!("Should have stopped test at interruption point");
             fails += 1;
         }
@@ -1197,7 +1261,7 @@
             fails += 1;
         }
 
-        if !c::boot_go(&mut flash, &self.areadesc, None, false).success() {
+        if !c::boot_go(&mut flash, &self.areadesc, None, None, false).success() {
             warn!("Should have finished test upgrade");
             fails += 1;
         }
@@ -1225,12 +1289,13 @@
 
         // Do Revert
         let mut counter = stop;
-        if !c::boot_go(&mut flash, &self.areadesc, Some(&mut counter), false).interrupted() {
+        if !c::boot_go(&mut flash, &self.areadesc, Some(&mut counter), None,
+                       false).interrupted() {
             warn!("Should have stopped revert at interruption point");
             fails += 1;
         }
 
-        if !c::boot_go(&mut flash, &self.areadesc, None, false).success() {
+        if !c::boot_go(&mut flash, &self.areadesc, None, None, false).success() {
             warn!("Should have finished revert upgrade");
             fails += 1;
         }
@@ -1257,7 +1322,7 @@
             fails += 1;
         }
 
-        if !c::boot_go(&mut flash, &self.areadesc, None, false).success() {
+        if !c::boot_go(&mut flash, &self.areadesc, None, None, false).success() {
             warn!("Should have finished 3rd boot");
             fails += 1;
         }
@@ -1286,7 +1351,8 @@
         for reset in &mut resets {
             let reset_counter = rng.gen_range(1 ..= remaining_ops / 2);
             let mut counter = reset_counter;
-            match c::boot_go(&mut flash, &self.areadesc, Some(&mut counter), false) {
+            match c::boot_go(&mut flash, &self.areadesc, Some(&mut counter),
+                             None, false) {
                 x if x.interrupted() => (),
                 x => panic!("Unknown return: {:?}", x),
             }
@@ -1294,7 +1360,7 @@
             *reset = reset_counter;
         }
 
-        match c::boot_go(&mut flash, &self.areadesc, None, false) {
+        match c::boot_go(&mut flash, &self.areadesc, None, None, false) {
             x if x.interrupted() => panic!("Should not be have been interrupted!"),
             x if x.success() => (),
             x => panic!("Unknown return: {:?}", x),
@@ -1613,14 +1679,13 @@
     }
 }
 
+/// Construct a TLV generator based on how MCUboot is currently configured.  The returned
+/// ManifestGen will generate the appropriate entries based on this configuration.
 fn make_tlv() -> TlvGen {
     if Caps::EcdsaP224.present() {
         panic!("Ecdsa P224 not supported in Simulator");
     }
-    let mut aes_key_size = 128;
-    if Caps::Aes256.present() {
-        aes_key_size = 256;
-    }
+    let aes_key_size = if Caps::Aes256.present() { 256 } else { 128 };
 
     if Caps::EncKw.present() {
         if Caps::RSA2048.present() {
@@ -1726,12 +1791,13 @@
 
     failed |= match magic {
         Some(v) => {
-            if v == 1 && &copy[24..] != MAGIC {
+            let magic_off = (c::boot_max_align() * 3) + (c::boot_magic_sz() - MAGIC.len());
+            if v == 1 && &copy[magic_off..] != MAGIC {
                 warn!("\"magic\" mismatch at {:#x}", offset);
                 true
             } else if v == 3 {
                 let expected = [erased_val; 16];
-                if copy[24..] != expected {
+                if copy[magic_off..] != expected {
                     warn!("\"magic\" mismatch at {:#x}", offset);
                     true
                 } else {
@@ -1746,8 +1812,9 @@
 
     failed |= match image_ok {
         Some(v) => {
-            if (v == 1 && copy[16] != v) || (v == 3 && copy[16] != erased_val) {
-                warn!("\"image_ok\" mismatch at {:#x} v={} val={:#x}", offset, v, copy[8]);
+            let image_ok_off = c::boot_max_align() * 2;
+            if (v == 1 && copy[image_ok_off] != v) || (v == 3 && copy[image_ok_off] != erased_val) {
+                warn!("\"image_ok\" mismatch at {:#x} v={} val={:#x}", offset, v, copy[image_ok_off]);
                 true
             } else {
                 false
@@ -1758,8 +1825,9 @@
 
     failed |= match copy_done {
         Some(v) => {
-            if (v == 1 && copy[8] != v) || (v == 3 && copy[8] != erased_val) {
-                warn!("\"copy_done\" mismatch at {:#x} v={} val={:#x}", offset, v, copy[0]);
+            let copy_done_off = c::boot_max_align();
+            if (v == 1 && copy[copy_done_off] != v) || (v == 3 && copy[copy_done_off] != erased_val) {
+                warn!("\"copy_done\" mismatch at {:#x} v={} val={:#x}", offset, v, copy[copy_done_off]);
                 true
             } else {
                 false
@@ -1860,11 +1928,18 @@
     pub dev_id: u8,
 }
 
+#[cfg(not(feature = "max-align-32"))]
 const MAGIC: &[u8] = &[0x77, 0xc2, 0x95, 0xf3,
                        0x60, 0xd2, 0xef, 0x7f,
                        0x35, 0x52, 0x50, 0x0f,
                        0x2c, 0xb6, 0x79, 0x80];
 
+#[cfg(feature = "max-align-32")]
+const MAGIC: &[u8] = &[0x20, 0x00, 0x2d, 0xe1,
+                       0x5d, 0x29, 0x41, 0x0b,
+                       0x8d, 0x77, 0x67, 0x9c,
+                       0x11, 0x0f, 0x1f, 0x8a];
+
 // Replicates defines found in bootutil.h
 const BOOT_MAGIC_GOOD: Option<u8> = Some(1);
 const BOOT_MAGIC_UNSET: Option<u8> = Some(3);
@@ -1882,8 +1957,9 @@
         // The write size is larger than the magic value.  Fill a buffer
         // with the erased value, put the MAGIC in it, and write it in its
         // entirety.
-        let mut buf = vec![dev.erased_val(); align];
-        buf[(offset % align)..].copy_from_slice(MAGIC);
+        let mut buf = vec![dev.erased_val(); c::boot_max_align()];
+        let magic_off = (offset % align) + (c::boot_magic_sz() - MAGIC.len());
+        buf[magic_off..].copy_from_slice(MAGIC);
         dev.write(offset - (offset % align), &buf).unwrap();
     } else {
         dev.write(offset, MAGIC).unwrap();
@@ -1917,11 +1993,11 @@
     }
 
     let dev = flash.get_mut(&slot.dev_id).unwrap();
-    let mut ok = [dev.erased_val(); 8];
+    let align = dev.align();
+    let mut ok = vec![dev.erased_val(); align];
     ok[0] = 1u8;
     let off = slot.trailer_off + c::boot_max_align() * 3;
-    let align = dev.align();
-    dev.write(off, &ok[..align]).unwrap();
+    dev.write(off, &ok).unwrap();
 }
 
 /// Writes the image_ok flag which, guess what, tells the bootloader
@@ -1975,16 +2051,16 @@
     }
 }
 
-#[cfg(not(feature = "large-write"))]
 #[cfg(not(feature = "swap-status"))]
+#[cfg(not(feature = "max-align-32"))]
 fn test_alignments() -> &'static [usize] {
     &[1, 2, 4, 8]
 }
 
-#[cfg(feature = "large-write")]
 #[cfg(not(feature = "swap-status"))]
+#[cfg(feature = "max-align-32")]
 fn test_alignments() -> &'static [usize] {
-    &[1, 2, 4, 8, 128, 512]
+    &[32]
 }
 
 #[cfg(feature = "swap-status")]
diff --git a/sim/src/lib.rs b/sim/src/lib.rs
index 69f13f1..eec7547 100644
--- a/sim/src/lib.rs
+++ b/sim/src/lib.rs
@@ -16,6 +16,7 @@
 mod depends;
 mod image;
 mod tlv;
+mod utils;
 pub mod testlog;
 
 pub use crate::{
@@ -52,8 +53,6 @@
 
 #[derive(Debug, Deserialize)]
 struct Args {
-    flag_help: bool,
-    flag_version: bool,
     flag_device: Option<DeviceName>,
     flag_align: Option<AlignArg>,
     cmd_sizes: bool,
diff --git a/sim/src/tlv.rs b/sim/src/tlv.rs
index 6680b4f..61d56a2 100644
--- a/sim/src/tlv.rs
+++ b/sim/src/tlv.rs
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020 Linaro LTD
+// Copyright (c) 2017-2021 Linaro LTD
 // Copyright (c) 2017-2020 JUUL Labs
 // Copyright (c) 2021 Arm Limited
 //
@@ -67,8 +67,8 @@
     PIC = 0x01,
     NON_BOOTABLE = 0x02,
     ENCRYPTED_AES128 = 0x04,
-    RAM_LOAD = 0x20,
     ENCRYPTED_AES256 = 0x08,
+    RAM_LOAD = 0x20,
 }
 
 /// A generator for manifests.  The format of the manifest can be either a
@@ -96,6 +96,11 @@
     /// corrupt the signature.
     fn corrupt_sig(&mut self);
 
+    /// Estimate the size of the TLV.  This can be called before the payload is added (but after
+    /// other information is added).  Some of the signature algorithms can generate variable sized
+    /// data, and therefore, this can slightly overestimate the size.
+    fn estimate_size(&self) -> usize;
+
     /// Construct the manifest for this payload.
     fn make_tlv(self: Box<Self>) -> Vec<u8>;
 
@@ -332,8 +337,67 @@
         self.gen_corrupted = true;
     }
 
+    fn estimate_size(&self) -> usize {
+        // Begin the estimate with the 4 byte header.
+        let mut estimate = 4;
+        // A very poor estimate.
+
+        // Estimate the size of the image hash.
+        if self.kinds.contains(&TlvKinds::SHA256) {
+            estimate += 4 + 32;
+        }
+
+        // Add an estimate in for each of the signature algorithms.
+        if self.kinds.contains(&TlvKinds::RSA2048) {
+            estimate += 4 + 32; // keyhash
+            estimate += 4 + 256; // RSA2048
+        }
+        if self.kinds.contains(&TlvKinds::RSA3072) {
+            estimate += 4 + 32; // keyhash
+            estimate += 4 + 384; // RSA3072
+        }
+        if self.kinds.contains(&TlvKinds::ECDSA256) {
+            estimate += 4 + 32; // keyhash
+
+            // ECDSA signatures are encoded as ASN.1 with the x and y values stored as signed
+            // integers.  As such, the size can vary by 2 bytes, if the 256-bit value has the high
+            // bit, it takes an extra 0 byte to avoid it being seen as a negative number.
+            estimate += 4 + 72; // ECDSA256 (varies)
+        }
+        if self.kinds.contains(&TlvKinds::ED25519) {
+            estimate += 4 + 32; // keyhash
+            estimate += 4 + 64; // ED25519 signature.
+        }
+
+        // Estimate encryption.
+        let flag = TlvFlags::ENCRYPTED_AES256 as u32;
+        let aes256 = (self.get_flags() & flag) == flag;
+
+        if self.kinds.contains(&TlvKinds::ENCRSA2048) {
+            estimate += 4 + 256;
+        }
+        if self.kinds.contains(&TlvKinds::ENCKW) {
+            estimate += 4 + if aes256 { 40 } else { 24 };
+        }
+        if self.kinds.contains(&TlvKinds::ENCEC256) {
+            estimate += 4 + if aes256 { 129 } else { 113 };
+        }
+        if self.kinds.contains(&TlvKinds::ENCX25519) {
+            estimate += 4 + if aes256 { 96 } else { 80 };
+        }
+
+        // Gather the size of the dependency information.
+        if self.protect_size() > 0 {
+            estimate += 4 + (16 * self.dependencies.len());
+        }
+
+        estimate
+    }
+
     /// Compute the TLV given the specified block of data.
     fn make_tlv(self: Box<Self>) -> Vec<u8> {
+        let size_estimate = self.estimate_size();
+
         let mut protected_tlv: Vec<u8> = vec![];
 
         if self.protect_size() > 0 {
@@ -663,6 +727,25 @@
         let mut size_buf = &mut result[npro_pos + 2 .. npro_pos + 4];
         size_buf.write_u16::<LittleEndian>(size).unwrap();
 
+        // ECDSA is stored as an ASN.1 integer.  For a 128-bit value, this maximally results in 33
+        // bytes of storage for each of the two values.  If the high bit is zero, it will take 32
+        // bytes, if the top 8 bits are zero, it will take 31 bits, and so on.  The smaller size
+        // will occur with decreasing likelihood.  We'll allow this to get a bit smaller, hopefully
+        // allowing the tests to pass with false failures rare.  For this case, we'll handle up to
+        // the top 16 bits of both numbers being all zeros (1 in 2^32).
+        if !Caps::has_ecdsa() {
+            if size_estimate != result.len() {
+                panic!("Incorrect size estimate: {} (actual {})", size_estimate, result.len());
+            }
+        } else {
+            if size_estimate < result.len() || size_estimate > result.len() + 6 {
+                panic!("Incorrect size estimate: {} (actual {})", size_estimate, result.len());
+            }
+        }
+        if size_estimate != result.len() {
+            log::warn!("Size off: {} actual {}", size_estimate, result.len());
+        }
+
         result
     }
 
diff --git a/sim/src/utils.rs b/sim/src/utils.rs
new file mode 100644
index 0000000..abbac3c
--- /dev/null
+++ b/sim/src/utils.rs
@@ -0,0 +1,11 @@
+// SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
+//
+// SPDX-License-Identifier: Apache-2.0
+
+//! Utility functions used throughout MCUboot
+
+pub fn align_up(num: u32, align: u32) -> u32 {
+    assert!(align.is_power_of_two());
+
+    (num + (align - 1)) & !(align - 1)
+}
diff --git a/sim/tests/core.rs b/sim/tests/core.rs
index 995c372..cbf31b4 100644
--- a/sim/tests/core.rs
+++ b/sim/tests/core.rs
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2019 Linaro LTD
+// Copyright (c) 2017-2021 Linaro LTD
 // Copyright (c) 2017-2019 JUUL Labs
 //
 // SPDX-License-Identifier: Apache-2.0
@@ -67,6 +67,7 @@
 sim_test!(direct_xip_first, make_no_upgrade_image(&NO_DEPS), run_direct_xip(), "");
 sim_test!(ram_load_first, make_no_upgrade_image(&NO_DEPS), run_ram_load(), "");
 
+sim_test!(ram_load_split, make_no_upgrade_image(&NO_DEPS), run_split_ram_load(), "");
 // Test various combinations of incorrect dependencies.
 test_shell!(dependency_combos, r, {
     // Only test setups with two images.