Infineon: Add cyw20829 platform, shared slot feature, json memory map, psoc6 xip

Based in 1.8.0 release of MCUBoot library

This commit adds CYW20829 Infineon platform support with following capabilities:
1. Overwrite and swap upgrade mode support
2. Multi-image with up to 4 images
3. Hardware security counter is supported for CYW20829 platform

Add XIP support for PSOC6 platform - place BOOT slot in external memory and execute it in place using SMIF in XIP mode

and some new features for Infineon devices.

1. Shared upgrade slot feature - use one shared area for upgrade slots of multiple images
2. Memory map defined using JSON file - define memory regions for bootloader and user app in conventional way using JSON file
diff --git a/sim/Cargo.lock b/sim/Cargo.lock
deleted file mode 100644
index 11aaec7..0000000
--- a/sim/Cargo.lock
+++ /dev/null
@@ -1,667 +0,0 @@
-# This file is automatically @generated by Cargo.
-# It is not intended for manual editing.
-[[package]]
-name = "aes-ctr"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "92e60aeefd2a0243bd53a42e92444e039f67c3d7f0382c9813577696e7c10bf3"
-dependencies = [
- "aes-soft",
- "aesni",
- "ctr",
- "stream-cipher",
-]
-
-[[package]]
-name = "aes-soft"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4925647ee64e5056cf231608957ce7c81e12d6d6e316b9ce1404778cc1d35fa7"
-dependencies = [
- "block-cipher",
- "byteorder",
- "opaque-debug",
-]
-
-[[package]]
-name = "aesni"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d050d39b0b7688b3a3254394c3e30a9d66c41dcf9b05b0e2dbdc623f6505d264"
-dependencies = [
- "block-cipher",
- "opaque-debug",
- "stream-cipher",
-]
-
-[[package]]
-name = "aho-corasick"
-version = "0.7.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "743ad5a418686aad3b87fd14c43badd828cf26e214a00f92a384291cf22e1811"
-dependencies = [
- "memchr",
-]
-
-[[package]]
-name = "anyhow"
-version = "1.0.26"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7825f6833612eb2414095684fcf6c635becf3ce97fe48cf6421321e93bfbd53c"
-
-[[package]]
-name = "atty"
-version = "0.2.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
-dependencies = [
- "hermit-abi",
- "libc",
- "winapi",
-]
-
-[[package]]
-name = "base64"
-version = "0.12.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff"
-
-[[package]]
-name = "block-cipher"
-version = "0.7.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fa136449e765dc7faa244561ccae839c394048667929af599b5d931ebe7b7f10"
-dependencies = [
- "generic-array",
-]
-
-[[package]]
-name = "bootsim"
-version = "0.1.0"
-dependencies = [
- "aes-ctr",
- "base64",
- "byteorder",
- "docopt",
- "env_logger",
- "libc",
- "log",
- "mcuboot-sys",
- "pem",
- "rand",
- "ring",
- "serde",
- "serde_derive",
- "simflash",
- "untrusted",
-]
-
-[[package]]
-name = "bumpalo"
-version = "3.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f359dc14ff8911330a51ef78022d376f25ed00248912803b58f00cb1c27f742"
-
-[[package]]
-name = "byteorder"
-version = "1.3.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
-
-[[package]]
-name = "cc"
-version = "1.0.50"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd"
-
-[[package]]
-name = "cfg-if"
-version = "0.1.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
-
-[[package]]
-name = "ctr"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a3592740fd55aaf61dd72df96756bd0d11e6037b89dcf30ae2e1895b267692be"
-dependencies = [
- "stream-cipher",
-]
-
-[[package]]
-name = "docopt"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f525a586d310c87df72ebcd98009e57f1cc030c8c268305287a476beb653969"
-dependencies = [
- "lazy_static",
- "regex",
- "serde",
- "strsim",
-]
-
-[[package]]
-name = "env_logger"
-version = "0.7.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
-dependencies = [
- "atty",
- "humantime",
- "log",
- "regex",
- "termcolor",
-]
-
-[[package]]
-name = "generic-array"
-version = "0.14.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac746a5f3bbfdadd6106868134545e684693d54d9d44f6e9588a7d54af0bf980"
-dependencies = [
- "typenum",
- "version_check 0.9.2",
-]
-
-[[package]]
-name = "getrandom"
-version = "0.1.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb"
-dependencies = [
- "cfg-if",
- "libc",
- "wasi",
-]
-
-[[package]]
-name = "heck"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
-dependencies = [
- "unicode-segmentation",
-]
-
-[[package]]
-name = "hermit-abi"
-version = "0.1.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eff2656d88f158ce120947499e971d743c05dbcbed62e5bd2f38f1698bbc3772"
-dependencies = [
- "libc",
-]
-
-[[package]]
-name = "humantime"
-version = "1.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
-dependencies = [
- "quick-error",
-]
-
-[[package]]
-name = "js-sys"
-version = "0.3.35"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7889c7c36282151f6bf465be4700359318aef36baa951462382eae49e9577cf9"
-dependencies = [
- "wasm-bindgen",
-]
-
-[[package]]
-name = "lazy_static"
-version = "1.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
-
-[[package]]
-name = "libc"
-version = "0.2.66"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558"
-
-[[package]]
-name = "log"
-version = "0.4.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
-dependencies = [
- "cfg-if",
-]
-
-[[package]]
-name = "mcuboot-sys"
-version = "0.1.0"
-dependencies = [
- "cc",
- "libc",
- "log",
- "simflash",
-]
-
-[[package]]
-name = "memchr"
-version = "2.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3197e20c7edb283f87c071ddfc7a2cca8f8e0b888c242959846a6fce03c72223"
-
-[[package]]
-name = "nom"
-version = "4.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6"
-dependencies = [
- "memchr",
- "version_check 0.1.5",
-]
-
-[[package]]
-name = "once_cell"
-version = "1.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b631f7e854af39a1739f401cf34a8a013dfe09eac4fa4dba91e9768bd28168d"
-
-[[package]]
-name = "opaque-debug"
-version = "0.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
-
-[[package]]
-name = "pem"
-version = "0.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "59698ea79df9bf77104aefd39cc3ec990cb9693fb59c3b0a70ddf2646fdffb4b"
-dependencies = [
- "base64",
- "once_cell",
- "regex",
-]
-
-[[package]]
-name = "ppv-lite86"
-version = "0.2.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "237a5ed80e274dbc66f86bd59c1e25edc039660be53194b5fe0a482e0f2612ea"
-
-[[package]]
-name = "proc-macro2"
-version = "1.0.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3acb317c6ff86a4e579dfa00fc5e6cca91ecbb4e7eb2df0468805b674eb88548"
-dependencies = [
- "unicode-xid",
-]
-
-[[package]]
-name = "quick-error"
-version = "1.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
-
-[[package]]
-name = "quote"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
-dependencies = [
- "proc-macro2",
-]
-
-[[package]]
-name = "rand"
-version = "0.7.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
-dependencies = [
- "getrandom",
- "libc",
- "rand_chacha",
- "rand_core",
- "rand_hc",
- "rand_pcg",
-]
-
-[[package]]
-name = "rand_chacha"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
-dependencies = [
- "ppv-lite86",
- "rand_core",
-]
-
-[[package]]
-name = "rand_core"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
-dependencies = [
- "getrandom",
-]
-
-[[package]]
-name = "rand_hc"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
-dependencies = [
- "rand_core",
-]
-
-[[package]]
-name = "rand_pcg"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429"
-dependencies = [
- "rand_core",
-]
-
-[[package]]
-name = "regex"
-version = "1.3.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "322cf97724bea3ee221b78fe25ac9c46114ebb51747ad5babd51a2fc6a8235a8"
-dependencies = [
- "aho-corasick",
- "memchr",
- "regex-syntax",
- "thread_local",
-]
-
-[[package]]
-name = "regex-syntax"
-version = "0.6.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b28dfe3fe9badec5dbf0a79a9cccad2cfc2ab5484bdb3e44cbd1ae8b3ba2be06"
-
-[[package]]
-name = "ring"
-version = "0.16.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "741ba1704ae21999c00942f9f5944f801e977f54302af346b596287599ad1862"
-dependencies = [
- "cc",
- "lazy_static",
- "libc",
- "spin",
- "untrusted",
- "web-sys",
- "winapi",
-]
-
-[[package]]
-name = "serde"
-version = "1.0.104"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449"
-dependencies = [
- "serde_derive",
-]
-
-[[package]]
-name = "serde_derive"
-version = "1.0.104"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "simflash"
-version = "0.1.0"
-dependencies = [
- "log",
- "rand",
- "thiserror",
-]
-
-[[package]]
-name = "sourcefile"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4bf77cb82ba8453b42b6ae1d692e4cdc92f9a47beaf89a847c8be83f4e328ad3"
-
-[[package]]
-name = "spin"
-version = "0.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
-
-[[package]]
-name = "stream-cipher"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09f8ed9974042b8c3672ff3030a69fcc03b74c47c3d1ecb7755e8a3626011e88"
-dependencies = [
- "block-cipher",
- "generic-array",
-]
-
-[[package]]
-name = "strsim"
-version = "0.9.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c"
-
-[[package]]
-name = "syn"
-version = "1.0.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "af6f3550d8dff9ef7dc34d384ac6f107e5d31c8f57d9f28e0081503f547ac8f5"
-dependencies = [
- "proc-macro2",
- "quote",
- "unicode-xid",
-]
-
-[[package]]
-name = "termcolor"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f"
-dependencies = [
- "winapi-util",
-]
-
-[[package]]
-name = "thiserror"
-version = "1.0.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "318234ffa22e0920fe9a40d7b8369b5f649d490980cf7aadcf1eb91594869b42"
-dependencies = [
- "thiserror-impl",
-]
-
-[[package]]
-name = "thiserror-impl"
-version = "1.0.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cae2447b6282786c3493999f40a9be2a6ad20cb8bd268b0a0dbf5a065535c0ab"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "thread_local"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
-dependencies = [
- "lazy_static",
-]
-
-[[package]]
-name = "typenum"
-version = "1.11.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9"
-
-[[package]]
-name = "unicode-segmentation"
-version = "1.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0"
-
-[[package]]
-name = "unicode-xid"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
-
-[[package]]
-name = "untrusted"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "60369ef7a31de49bcb3f6ca728d4ba7300d9a1658f94c727d4cab8c8d9f4aece"
-
-[[package]]
-name = "version_check"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
-
-[[package]]
-name = "version_check"
-version = "0.9.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
-
-[[package]]
-name = "wasi"
-version = "0.9.0+wasi-snapshot-preview1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
-
-[[package]]
-name = "wasm-bindgen"
-version = "0.2.58"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5205e9afdf42282b192e2310a5b463a6d1c1d774e30dc3c791ac37ab42d2616c"
-dependencies = [
- "cfg-if",
- "wasm-bindgen-macro",
-]
-
-[[package]]
-name = "wasm-bindgen-backend"
-version = "0.2.58"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "11cdb95816290b525b32587d76419facd99662a07e59d3cdb560488a819d9a45"
-dependencies = [
- "bumpalo",
- "lazy_static",
- "log",
- "proc-macro2",
- "quote",
- "syn",
- "wasm-bindgen-shared",
-]
-
-[[package]]
-name = "wasm-bindgen-macro"
-version = "0.2.58"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "574094772ce6921576fb6f2e3f7497b8a76273b6db092be18fc48a082de09dc3"
-dependencies = [
- "quote",
- "wasm-bindgen-macro-support",
-]
-
-[[package]]
-name = "wasm-bindgen-macro-support"
-version = "0.2.58"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e85031354f25eaebe78bb7db1c3d86140312a911a106b2e29f9cc440ce3e7668"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "wasm-bindgen-backend",
- "wasm-bindgen-shared",
-]
-
-[[package]]
-name = "wasm-bindgen-shared"
-version = "0.2.58"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f5e7e61fc929f4c0dddb748b102ebf9f632e2b8d739f2016542b4de2965a9601"
-
-[[package]]
-name = "wasm-bindgen-webidl"
-version = "0.2.58"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ef012a0d93fc0432df126a8eaf547b2dce25a8ce9212e1d3cbeef5c11157975d"
-dependencies = [
- "anyhow",
- "heck",
- "log",
- "proc-macro2",
- "quote",
- "syn",
- "wasm-bindgen-backend",
- "weedle",
-]
-
-[[package]]
-name = "web-sys"
-version = "0.3.35"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aaf97caf6aa8c2b1dac90faf0db529d9d63c93846cca4911856f78a83cebf53b"
-dependencies = [
- "anyhow",
- "js-sys",
- "sourcefile",
- "wasm-bindgen",
- "wasm-bindgen-webidl",
-]
-
-[[package]]
-name = "weedle"
-version = "0.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3bb43f70885151e629e2a19ce9e50bd730fd436cfd4b666894c9ce4de9141164"
-dependencies = [
- "nom",
-]
-
-[[package]]
-name = "winapi"
-version = "0.3.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
-dependencies = [
- "winapi-i686-pc-windows-gnu",
- "winapi-x86_64-pc-windows-gnu",
-]
-
-[[package]]
-name = "winapi-i686-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
-
-[[package]]
-name = "winapi-util"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ccfbf554c6ad11084fb7517daca16cfdcaccbdadba4fc336f032a8b12c2ad80"
-dependencies = [
- "winapi",
-]
-
-[[package]]
-name = "winapi-x86_64-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
diff --git a/sim/Cargo.toml b/sim/Cargo.toml
index 02f0f73..b80dbb2 100644
--- a/sim/Cargo.toml
+++ b/sim/Cargo.toml
@@ -17,30 +17,39 @@
 swap-status = ["mcuboot-sys/swap-status"]
 validate-primary-slot = ["mcuboot-sys/validate-primary-slot"]
 enc-rsa = ["mcuboot-sys/enc-rsa"]
+enc-aes256-rsa = ["mcuboot-sys/enc-aes256-rsa"]
 enc-kw = ["mcuboot-sys/enc-kw"]
+enc-aes256-kw = ["mcuboot-sys/enc-aes256-kw"]
 enc-ec256 = ["mcuboot-sys/enc-ec256"]
+enc-ec256-mbedtls = ["mcuboot-sys/enc-ec256-mbedtls"]
+enc-aes256-ec256 = ["mcuboot-sys/enc-aes256-ec256"]
 enc-x25519 = ["mcuboot-sys/enc-x25519"]
+enc-aes256-x25519 = ["mcuboot-sys/enc-aes256-x25519"]
 bootstrap = ["mcuboot-sys/bootstrap"]
 multiimage = ["mcuboot-sys/multiimage"]
+ram-load = ["mcuboot-sys/ram-load"]
+direct-xip = ["mcuboot-sys/direct-xip"]
 large-write = []
 downgrade-prevention = ["mcuboot-sys/downgrade-prevention"]
 
 [dependencies]
 byteorder = "1.3"
 libc = "0.2"
-rand = { version = "0.7", features = ["small_rng"] }
+rand = { version = "0.8", features = ["small_rng"] }
 docopt = "1.1.0"
 serde = "1.0"
 serde_derive = "1.0"
 log = "0.4"
-env_logger = "0.7"
+env_logger = "0.9"
 simflash = { path = "simflash" }
 mcuboot-sys = { path = "mcuboot-sys" }
 ring = "0.16.11"
-untrusted = "0.7"
+untrusted = "0.9"
 pem = "0.8"
-aes-ctr = "0.4.0"
-base64 = "0.12.0"
+cipher = "0.3"
+aes = { version = "0.7.4", features = ["ctr"] }
+base64 = "0.13.0"
+typenum = "1.13.0"
 
 # The simulator runs very slowly without optimization.  A value of 1
 # compiles in about half the time, but runs about 5-6 times slower.  2
@@ -48,6 +57,8 @@
 # Use 2 in case that makes the code slightly more debuggable.
 [profile.test]
 opt-level = 2
+# debug = true
 
 [profile.dev]
 opt-level = 2
+# debug = true
diff --git a/sim/mcuboot-sys/Cargo.toml b/sim/mcuboot-sys/Cargo.toml
index ef09755..e3a00cb 100644
--- a/sim/mcuboot-sys/Cargo.toml
+++ b/sim/mcuboot-sys/Cargo.toml
@@ -30,34 +30,62 @@
 # Overwrite only upgrade
 overwrite-only = []
 
-swap-status = []
-
 swap-move = []
 
+swap-status = []
+
 # Disable validation of the primary slot
 validate-primary-slot = []
 
 # Encrypt image in the secondary slot using RSA-OAEP-2048
 enc-rsa = []
 
+# Encrypt  image in the secondary slot using AES-256-CTR and RSA-OAEP-2048
+enc-aes256-rsa = []
+
 # Encrypt image in the secondary slot using AES-KW-128
 enc-kw = []
 
+# Encrypt image in the secondary slot using AES-256-CTR and AES-KW-256
+enc-aes256-kw = []
+
 # Encrypt image in the secondary slot using ECIES-P256
 enc-ec256 = []
 
+# Encrypt image in the secondary slot using AES-256-CTR and ECIES-P256
+enc-aes256-ec256 = []
+
+# Encrypt image in the secondary slot using ECIES-P256 using Mbed TLS
+enc-ec256-mbedtls = []
+
 # Encrypt image in the secondary slot using ECIES-X25519
 enc-x25519 = []
 
+# Encrypt image in the secondary slot using AES-256-CTR and ECIES-X25519
+enc-aes256-x25519 = []
+
 # Allow bootstrapping an empty/invalid primary slot from a valid secondary slot
 bootstrap = []
 
 # Support multiple images (currently 2 instead of 1).
 multiimage = []
 
+# Support simulation of ram-loading.  No swaps are performed, and the
+# image is copied to RAM before loading it.
+ram-load = []
+
+# Support simulation of direct XIP.  No swaps are performed, the image
+# is directly executed out of whichever partition contains the most
+# appropriate image.
+direct-xip = []
+
 # 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 = []
+
 [build-dependencies]
 cc = "1.0.25"
 
diff --git a/sim/mcuboot-sys/build.rs b/sim/mcuboot-sys/build.rs
index a2206c9..1a08741 100644
--- a/sim/mcuboot-sys/build.rs
+++ b/sim/mcuboot-sys/build.rs
@@ -2,10 +2,11 @@
 
 extern crate cc;
 
+use std::collections::BTreeSet;
 use std::env;
 use std::fs;
 use std::io;
-use std::path::Path;
+use std::path::{Path, PathBuf};
 
 fn main() {
     // Feature flags.
@@ -20,37 +21,51 @@
     let validate_primary_slot =
                   env::var("CARGO_FEATURE_VALIDATE_PRIMARY_SLOT").is_ok();
     let enc_rsa = env::var("CARGO_FEATURE_ENC_RSA").is_ok();
+    let enc_aes256_rsa = env::var("CARGO_FEATURE_ENC_AES256_RSA").is_ok();
     let enc_kw = env::var("CARGO_FEATURE_ENC_KW").is_ok();
+    let enc_aes256_kw = env::var("CARGO_FEATURE_ENC_AES256_KW").is_ok();
     let enc_ec256 = env::var("CARGO_FEATURE_ENC_EC256").is_ok();
+    let enc_ec256_mbedtls = env::var("CARGO_FEATURE_ENC_EC256_MBEDTLS").is_ok();
+    let enc_aes256_ec256 = env::var("CARGO_FEATURE_ENC_AES256_EC256").is_ok();
     let enc_x25519 = env::var("CARGO_FEATURE_ENC_X25519").is_ok();
+    let enc_aes256_x25519 = env::var("CARGO_FEATURE_ENC_AES256_X25519").is_ok();
     let bootstrap = env::var("CARGO_FEATURE_BOOTSTRAP").is_ok();
     let multiimage = env::var("CARGO_FEATURE_MULTIIMAGE").is_ok();
     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 mut conf = cc::Build::new();
-    conf.define("__BOOTSIM__", None);
-    conf.define("MCUBOOT_HAVE_LOGGING", None);
-    conf.define("MCUBOOT_USE_FLASH_AREA_GET_SECTORS", None);
-    conf.define("MCUBOOT_HAVE_ASSERT_H", None);
-    if !swap_status {
-        conf.define("MCUBOOT_MAX_IMG_SECTORS", Some("128"));
-    }
-    conf.define("MCUBOOT_IMAGE_NUMBER", Some(if multiimage { "2" } else { "1" }));
+    let mut conf = CachedBuild::new();
+    conf.conf.define("__BOOTSIM__", None);
+    conf.conf.define("MCUBOOT_HAVE_LOGGING", None);
+    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"));
+    conf.conf.define("MCUBOOT_IMAGE_NUMBER", Some(if multiimage { "2" } else { "1" }));
 
     if downgrade_prevention && !overwrite_only {
         panic!("Downgrade prevention requires overwrite only");
     }
 
     if bootstrap {
-        conf.define("MCUBOOT_BOOTSTRAP", None);
+        conf.conf.define("MCUBOOT_BOOTSTRAP", None);
+        conf.conf.define("MCUBOOT_OVERWRITE_ONLY_FAST", None);
     }
 
     if validate_primary_slot {
-        conf.define("MCUBOOT_VALIDATE_PRIMARY_SLOT", None);
+        conf.conf.define("MCUBOOT_VALIDATE_PRIMARY_SLOT", None);
     }
 
     if downgrade_prevention {
-        conf.define("MCUBOOT_DOWNGRADE_PREVENTION", None);
+        conf.conf.define("MCUBOOT_DOWNGRADE_PREVENTION", None);
+    }
+
+    if ram_load {
+        conf.conf.define("MCUBOOT_RAM_LOAD", None);
+    }
+
+    if direct_xip {
+        conf.conf.define("MCUBOOT_DIRECT_XIP", None);
     }
 
     // Currently no more than one sig type can be used simultaneously.
@@ -60,35 +75,35 @@
     }
 
     if sig_rsa || sig_rsa3072 {
-        conf.define("MCUBOOT_SIGN_RSA", None);
+        conf.conf.define("MCUBOOT_SIGN_RSA", None);
         // The Kconfig style defines must be added here as well because
         // they are used internally by "config-rsa.h"
         if sig_rsa {
-            conf.define("MCUBOOT_SIGN_RSA_LEN", "2048");
-            conf.define("CONFIG_BOOT_SIGNATURE_TYPE_RSA_LEN", "2048");
+            conf.conf.define("MCUBOOT_SIGN_RSA_LEN", "2048");
+            conf.conf.define("CONFIG_BOOT_SIGNATURE_TYPE_RSA_LEN", "2048");
         } else {
-            conf.define("MCUBOOT_SIGN_RSA_LEN", "3072");
-            conf.define("CONFIG_BOOT_SIGNATURE_TYPE_RSA_LEN", "3072");
+            conf.conf.define("MCUBOOT_SIGN_RSA_LEN", "3072");
+            conf.conf.define("CONFIG_BOOT_SIGNATURE_TYPE_RSA_LEN", "3072");
         }
-        conf.define("MCUBOOT_USE_MBED_TLS", None);
+        conf.conf.define("MCUBOOT_USE_MBED_TLS", None);
 
-        conf.include("../../ext/mbedtls/crypto/include");
-        conf.file("../../ext/mbedtls/crypto/library/sha256.c");
+        conf.conf.include("../../ext/mbedtls/include");
+        conf.file("../../ext/mbedtls/library/sha256.c");
         conf.file("csupport/keys.c");
 
-        conf.file("../../ext/mbedtls/crypto/library/rsa.c");
-        conf.file("../../ext/mbedtls/crypto/library/bignum.c");
-        conf.file("../../ext/mbedtls/crypto/library/platform.c");
-        conf.file("../../ext/mbedtls/crypto/library/platform_util.c");
-        conf.file("../../ext/mbedtls/crypto/library/asn1parse.c");
+        conf.file("../../ext/mbedtls/library/rsa.c");
+        conf.file("../../ext/mbedtls/library/bignum.c");
+        conf.file("../../ext/mbedtls/library/platform.c");
+        conf.file("../../ext/mbedtls/library/platform_util.c");
+        conf.file("../../ext/mbedtls/library/asn1parse.c");
     } else if sig_ecdsa {
-        conf.define("MCUBOOT_SIGN_EC256", None);
-        conf.define("MCUBOOT_USE_TINYCRYPT", None);
+        conf.conf.define("MCUBOOT_SIGN_EC256", None);
+        conf.conf.define("MCUBOOT_USE_TINYCRYPT", None);
 
         if !enc_kw {
-            conf.include("../../ext/mbedtls-asn1/include");
+            conf.conf.include("../../ext/mbedtls/include");
         }
-        conf.include("../../ext/tinycrypt/lib/include");
+        conf.conf.include("../../ext/tinycrypt/lib/include");
 
         conf.file("csupport/keys.c");
 
@@ -97,115 +112,119 @@
         conf.file("../../ext/tinycrypt/lib/source/ecc.c");
         conf.file("../../ext/tinycrypt/lib/source/ecc_dsa.c");
         conf.file("../../ext/tinycrypt/lib/source/ecc_platform_specific.c");
-
-        conf.file("../../ext/mbedtls-asn1/src/platform_util.c");
-        conf.file("../../ext/mbedtls-asn1/src/asn1parse.c");
+        conf.file("../../ext/mbedtls/library/platform_util.c");
+        conf.file("../../ext/mbedtls/library/asn1parse.c");
     } else if sig_ecdsa_mbedtls {
-        conf.define("MCUBOOT_SIGN_EC256", None);
-        conf.define("MCUBOOT_USE_MBED_TLS", None);
+        conf.conf.define("MCUBOOT_SIGN_EC256", None);
+        conf.conf.define("MCUBOOT_USE_MBED_TLS", None);
 
-        conf.include("../../ext/mbedtls/crypto/include");
-        conf.file("../../ext/mbedtls/crypto/library/sha256.c");
+        conf.conf.include("../../ext/mbedtls/include");
+        conf.file("../../ext/mbedtls/library/sha256.c");
         conf.file("csupport/keys.c");
 
-        conf.file("../../ext/mbedtls/crypto/library/asn1parse.c");
-        conf.file("../../ext/mbedtls/crypto/library/bignum.c");
-        conf.file("../../ext/mbedtls/crypto/library/ecdsa.c");
-        conf.file("../../ext/mbedtls/crypto/library/ecp.c");
-        conf.file("../../ext/mbedtls/crypto/library/ecp_curves.c");
-        conf.file("../../ext/mbedtls/crypto/library/platform.c");
-        conf.file("../../ext/mbedtls/crypto/library/platform_util.c");
+        conf.file("../../ext/mbedtls/library/asn1parse.c");
+        conf.file("../../ext/mbedtls/library/bignum.c");
+        conf.file("../../ext/mbedtls/library/ecdsa.c");
+        conf.file("../../ext/mbedtls/library/ecp.c");
+        conf.file("../../ext/mbedtls/library/ecp_curves.c");
+        conf.file("../../ext/mbedtls/library/platform.c");
+        conf.file("../../ext/mbedtls/library/platform_util.c");
     } else if sig_ed25519 {
-        conf.define("MCUBOOT_SIGN_ED25519", None);
-        conf.define("MCUBOOT_USE_TINYCRYPT", None);
+        conf.conf.define("MCUBOOT_SIGN_ED25519", None);
+        conf.conf.define("MCUBOOT_USE_TINYCRYPT", None);
 
-        conf.include("../../ext/tinycrypt/lib/include");
-        conf.include("../../ext/tinycrypt-sha512/lib/include");
-        conf.include("../../ext/mbedtls-asn1/include");
+        conf.conf.include("../../ext/tinycrypt/lib/include");
+        conf.conf.include("../../ext/tinycrypt-sha512/lib/include");
+        conf.conf.include("../../ext/mbedtls/include");
         conf.file("../../ext/tinycrypt/lib/source/sha256.c");
         conf.file("../../ext/tinycrypt-sha512/lib/source/sha512.c");
         conf.file("../../ext/tinycrypt/lib/source/utils.c");
         conf.file("csupport/keys.c");
         conf.file("../../ext/fiat/src/curve25519.c");
-        conf.file("../../ext/mbedtls-asn1/src/platform_util.c");
-        conf.file("../../ext/mbedtls-asn1/src/asn1parse.c");
+        conf.file("../../ext/mbedtls/library/platform_util.c");
+        conf.file("../../ext/mbedtls/library/asn1parse.c");
     } else if !enc_ec256 && !enc_x25519 {
         // No signature type, only sha256 validation. The default
         // configuration file bundled with mbedTLS is sufficient.
         // When using ECIES-P256 rely on Tinycrypt.
-        conf.define("MCUBOOT_USE_MBED_TLS", None);
-        conf.include("../../ext/mbedtls/crypto/include");
-        conf.file("../../ext/mbedtls/crypto/library/sha256.c");
+        conf.conf.define("MCUBOOT_USE_MBED_TLS", None);
+        conf.conf.include("../../ext/mbedtls/include");
+        conf.file("../../ext/mbedtls/library/sha256.c");
+        conf.file("../../ext/mbedtls/library/platform_util.c");
     }
 
     if overwrite_only {
-        conf.define("MCUBOOT_OVERWRITE_ONLY", None);
-        conf.define("MCUBOOT_OVERWRITE_ONLY_FAST", None);
+        conf.conf.define("MCUBOOT_OVERWRITE_ONLY", None);
     }
 
     if swap_move {
-        conf.define("MCUBOOT_SWAP_USING_MOVE", None);
-        conf.file("../../boot/bootutil/src/swap_move.c");
+        conf.conf.define("MCUBOOT_SWAP_USING_MOVE", None);
+    } else if !overwrite_only {
+        conf.conf.define("CONFIG_BOOT_SWAP_USING_SCRATCH", None);
+        conf.conf.define("MCUBOOT_SWAP_USING_SCRATCH", None);
     }
-
     if swap_status {
-        conf.define("MCUBOOT_SWAP_USING_STATUS", None);
-        conf.define("MCUBOOT_LOG_LEVEL", "MCUBOOT_LOG_LEVEL_DEBUG");
-        conf.define("MCUBOOT_MAX_IMG_SECTORS", Some("2000"));
-        conf.define("CY_FLASH_ALIGN", "512");
-        conf.file("../../boot/bootutil/src/swap_status.c");
-        conf.file("../../boot/bootutil/src/swap_status_part.c");
-        conf.file("../../boot/bootutil/src/swap_status_misc.c");
-        conf.file("../../boot/bootutil/src/crc32c.c");
-//        conf.file("../../boot/cypress/cy_flash_pal/cy_my_support.c");
-        conf.include("../../boot/cypress/cy_flash_pal");
+        conf.conf.define("MCUBOOT_SWAP_USING_STATUS", None);
+        conf.conf.define("CY_FLASH_ALIGN", "512");
+        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");
+        conf.conf.file("../../boot/bootutil/src/crc32c.c");
     }
 
-    if enc_rsa {
-        conf.define("MCUBOOT_ENCRYPT_RSA", None);
-        conf.define("MCUBOOT_ENC_IMAGES", None);
-        conf.define("MCUBOOT_USE_MBED_TLS", None);
+    if enc_rsa || enc_aes256_rsa {
+        if enc_aes256_rsa {
+                conf.conf.define("MCUBOOT_AES_256", None);
+        }
+        conf.conf.define("MCUBOOT_ENCRYPT_RSA", None);
+        conf.conf.define("MCUBOOT_ENC_IMAGES", None);
+        conf.conf.define("MCUBOOT_USE_MBED_TLS", None);
 
         conf.file("../../boot/bootutil/src/encrypted.c");
         conf.file("csupport/keys.c");
 
-        conf.include("../../ext/mbedtls/crypto/include");
-        conf.file("../../ext/mbedtls/crypto/library/sha256.c");
+        conf.conf.include("../../ext/mbedtls/include");
+        conf.conf.include("../../ext/mbedtls/library");
+        conf.file("../../ext/mbedtls/library/sha256.c");
 
-        conf.file("../../ext/mbedtls/crypto/library/platform.c");
-        conf.file("../../ext/mbedtls/crypto/library/platform_util.c");
-        conf.file("../../ext/mbedtls/crypto/library/rsa.c");
-        conf.file("../../ext/mbedtls/crypto/library/rsa_internal.c");
-        conf.file("../../ext/mbedtls/crypto/library/md.c");
-        conf.file("../../ext/mbedtls/crypto/library/aes.c");
-        conf.file("../../ext/mbedtls/crypto/library/bignum.c");
-        conf.file("../../ext/mbedtls/crypto/library/asn1parse.c");
+        conf.file("../../ext/mbedtls/library/platform.c");
+        conf.file("../../ext/mbedtls/library/platform_util.c");
+        conf.file("../../ext/mbedtls/library/rsa.c");
+        conf.file("../../ext/mbedtls/library/rsa_alt_helpers.c");
+        conf.file("../../ext/mbedtls/library/md.c");
+        conf.file("../../ext/mbedtls/library/aes.c");
+        conf.file("../../ext/mbedtls/library/bignum.c");
+        conf.file("../../ext/mbedtls/library/asn1parse.c");
     }
 
-    if enc_kw {
-        conf.define("MCUBOOT_ENCRYPT_KW", None);
-        conf.define("MCUBOOT_ENC_IMAGES", None);
+    if enc_kw || enc_aes256_kw {
+        if enc_aes256_kw {
+            conf.conf.define("MCUBOOT_AES_256", None);
+        }
+        conf.conf.define("MCUBOOT_ENCRYPT_KW", None);
+        conf.conf.define("MCUBOOT_ENC_IMAGES", None);
 
         conf.file("../../boot/bootutil/src/encrypted.c");
         conf.file("csupport/keys.c");
 
         if sig_rsa || sig_rsa3072 {
-            conf.file("../../ext/mbedtls/crypto/library/sha256.c");
+            conf.file("../../ext/mbedtls/library/sha256.c");
         }
 
         /* Simulator uses Mbed-TLS to wrap keys */
-        conf.include("../../ext/mbedtls/crypto/include");
-        conf.file("../../ext/mbedtls/crypto/library/platform.c");
-        conf.file("../../ext/mbedtls/crypto/library/platform_util.c");
-        conf.file("../../ext/mbedtls/crypto/library/nist_kw.c");
-        conf.file("../../ext/mbedtls/crypto/library/cipher.c");
-        conf.file("../../ext/mbedtls/crypto/library/cipher_wrap.c");
-        conf.file("../../ext/mbedtls/crypto/library/aes.c");
+        conf.conf.include("../../ext/mbedtls/include");
+        conf.file("../../ext/mbedtls/library/platform.c");
+        conf.conf.include("../../ext/mbedtls/library");
+        conf.file("../../ext/mbedtls/library/platform_util.c");
+        conf.file("../../ext/mbedtls/library/nist_kw.c");
+        conf.file("../../ext/mbedtls/library/cipher.c");
+        conf.file("../../ext/mbedtls/library/cipher_wrap.c");
+        conf.file("../../ext/mbedtls/library/aes.c");
 
         if sig_ecdsa {
-            conf.define("MCUBOOT_USE_TINYCRYPT", None);
+            conf.conf.define("MCUBOOT_USE_TINYCRYPT", None);
 
-            conf.include("../../ext/tinycrypt/lib/include");
+            conf.conf.include("../../ext/tinycrypt/lib/include");
 
             conf.file("../../ext/tinycrypt/lib/source/utils.c");
             conf.file("../../ext/tinycrypt/lib/source/sha256.c");
@@ -220,16 +239,16 @@
     }
 
     if enc_ec256 {
-        conf.define("MCUBOOT_ENCRYPT_EC256", None);
-        conf.define("MCUBOOT_ENC_IMAGES", None);
-        conf.define("MCUBOOT_USE_TINYCRYPT", None);
-        conf.define("MCUBOOT_SWAP_SAVE_ENCTLV", None);
+        conf.conf.define("MCUBOOT_ENCRYPT_EC256", None);
+        conf.conf.define("MCUBOOT_ENC_IMAGES", None);
+        conf.conf.define("MCUBOOT_USE_TINYCRYPT", None);
+        conf.conf.define("MCUBOOT_SWAP_SAVE_ENCTLV", None);
 
         conf.file("../../boot/bootutil/src/encrypted.c");
         conf.file("csupport/keys.c");
 
-        conf.include("../../ext/mbedtls-asn1/include");
-        conf.include("../../ext/tinycrypt/lib/include");
+        conf.conf.include("../../ext/mbedtls/include");
+        conf.conf.include("../../ext/tinycrypt/lib/include");
 
         /* FIXME: fail with other signature schemes ? */
 
@@ -239,36 +258,59 @@
         conf.file("../../ext/tinycrypt/lib/source/ecc_dsa.c");
         conf.file("../../ext/tinycrypt/lib/source/ecc_platform_specific.c");
 
-        conf.file("../../ext/mbedtls-asn1/src/platform_util.c");
-        conf.file("../../ext/mbedtls-asn1/src/asn1parse.c");
+        conf.file("../../ext/mbedtls/library/platform_util.c");
+        conf.file("../../ext/mbedtls/library/asn1parse.c");
 
         conf.file("../../ext/tinycrypt/lib/source/aes_encrypt.c");
         conf.file("../../ext/tinycrypt/lib/source/aes_decrypt.c");
         conf.file("../../ext/tinycrypt/lib/source/ctr_mode.c");
         conf.file("../../ext/tinycrypt/lib/source/hmac.c");
         conf.file("../../ext/tinycrypt/lib/source/ecc_dh.c");
+    } else if enc_ec256_mbedtls || enc_aes256_ec256 {
+        if enc_aes256_ec256 {
+            conf.conf.define("MCUBOOT_AES_256", None);
+        }
+        conf.conf.define("MCUBOOT_ENCRYPT_EC256", None);
+        conf.conf.define("MCUBOOT_ENC_IMAGES", None);
+        conf.conf.define("MCUBOOT_USE_MBED_TLS", None);
+        conf.conf.define("MCUBOOT_SWAP_SAVE_ENCTLV", None);
+
+        conf.conf.include("../../ext/mbedtls/include");
+
+        conf.file("../../boot/bootutil/src/encrypted.c");
+        conf.file("../../ext/mbedtls/library/sha256.c");
+        conf.file("../../ext/mbedtls/library/asn1parse.c");
+        conf.file("../../ext/mbedtls/library/bignum.c");
+        conf.file("../../ext/mbedtls/library/ecdh.c");
+        conf.file("../../ext/mbedtls/library/md.c");
+        conf.file("../../ext/mbedtls/library/aes.c");
+        conf.file("../../ext/mbedtls/library/ecp.c");
+        conf.file("../../ext/mbedtls/library/ecp_curves.c");
+        conf.file("../../ext/mbedtls/library/platform.c");
+        conf.file("../../ext/mbedtls/library/platform_util.c");
+        conf.file("csupport/keys.c");
     }
 
     if enc_x25519 {
-        conf.define("MCUBOOT_ENCRYPT_X25519", None);
-        conf.define("MCUBOOT_ENC_IMAGES", None);
-        conf.define("MCUBOOT_USE_TINYCRYPT", None);
-        conf.define("MCUBOOT_SWAP_SAVE_ENCTLV", None);
+        conf.conf.define("MCUBOOT_ENCRYPT_X25519", None);
+        conf.conf.define("MCUBOOT_ENC_IMAGES", None);
+        conf.conf.define("MCUBOOT_USE_TINYCRYPT", None);
+        conf.conf.define("MCUBOOT_SWAP_SAVE_ENCTLV", None);
 
         conf.file("../../boot/bootutil/src/encrypted.c");
         conf.file("csupport/keys.c");
 
-        conf.include("../../ext/mbedtls-asn1/include");
-        conf.include("../../ext/tinycrypt/lib/include");
-        conf.include("../../ext/tinycrypt-sha512/lib/include");
+        conf.conf.include("../../ext/mbedtls/include");
+        conf.conf.include("../../ext/tinycrypt/lib/include");
+        conf.conf.include("../../ext/tinycrypt-sha512/lib/include");
 
         conf.file("../../ext/fiat/src/curve25519.c");
 
         conf.file("../../ext/tinycrypt/lib/source/utils.c");
         conf.file("../../ext/tinycrypt/lib/source/sha256.c");
 
-        conf.file("../../ext/mbedtls-asn1/src/platform_util.c");
-        conf.file("../../ext/mbedtls-asn1/src/asn1parse.c");
+        conf.file("../../ext/mbedtls/library/platform_util.c");
+        conf.file("../../ext/mbedtls/library/asn1parse.c");
 
         conf.file("../../ext/tinycrypt/lib/source/aes_encrypt.c");
         conf.file("../../ext/tinycrypt/lib/source/aes_decrypt.c");
@@ -276,24 +318,48 @@
         conf.file("../../ext/tinycrypt/lib/source/hmac.c");
     }
 
+    else if enc_aes256_x25519 {
+        conf.conf.define("MCUBOOT_AES_256", None);
+        conf.conf.define("MCUBOOT_ENCRYPT_X25519", None);
+        conf.conf.define("MCUBOOT_ENC_IMAGES", None);
+        conf.conf.define("MCUBOOT_USE_MBED_TLS", None);
+        conf.conf.define("MCUBOOT_SWAP_SAVE_ENCTLV", None);
+
+        conf.file("../../boot/bootutil/src/encrypted.c");
+        conf.file("csupport/keys.c");
+
+        conf.conf.include("../../ext/mbedtls/include");
+        conf.file("../../ext/fiat/src/curve25519.c");
+        conf.file("../../ext/mbedtls/library/asn1parse.c");
+        conf.file("../../ext/mbedtls/library/platform.c");
+        conf.file("../../ext/mbedtls/library/platform_util.c");
+        conf.file("../../ext/mbedtls/library/aes.c");
+        conf.file("../../ext/mbedtls/library/sha256.c");
+        conf.file("../../ext/mbedtls/library/md.c");
+        conf.file("../../ext/mbedtls/library/sha512.c");
+    }
+
     if sig_rsa && enc_kw {
-        conf.define("MBEDTLS_CONFIG_FILE", Some("<config-rsa-kw.h>"));
-    } else if sig_rsa || sig_rsa3072 || enc_rsa {
-        conf.define("MBEDTLS_CONFIG_FILE", Some("<config-rsa.h>"));
-    } else if sig_ecdsa_mbedtls {
-        conf.define("MBEDTLS_CONFIG_FILE", Some("<config-ecdsa.h>"));
+        conf.conf.define("MBEDTLS_CONFIG_FILE", Some("<config-rsa-kw.h>"));
+    } else if sig_rsa || sig_rsa3072 || enc_rsa || enc_aes256_rsa {
+        conf.conf.define("MBEDTLS_CONFIG_FILE", Some("<config-rsa.h>"));
+    } else if sig_ecdsa_mbedtls || enc_ec256_mbedtls || enc_aes256_ec256 {
+        conf.conf.define("MBEDTLS_CONFIG_FILE", Some("<config-ec.h>"));
     } else if (sig_ecdsa || enc_ec256) && !enc_kw {
-        conf.define("MBEDTLS_CONFIG_FILE", Some("<config-asn1.h>"));
+        conf.conf.define("MBEDTLS_CONFIG_FILE", Some("<config-asn1.h>"));
     } else if sig_ed25519 || enc_x25519 {
-        conf.define("MBEDTLS_CONFIG_FILE", Some("<config-asn1.h>"));
-    } else if enc_kw {
-        conf.define("MBEDTLS_CONFIG_FILE", Some("<config-kw.h>"));
+        conf.conf.define("MBEDTLS_CONFIG_FILE", Some("<config-asn1.h>"));
+    } else if enc_kw || enc_aes256_kw {
+        conf.conf.define("MBEDTLS_CONFIG_FILE", Some("<config-kw.h>"));
+    } else if enc_aes256_x25519 {
+        conf.conf.define("MBEDTLS_CONFIG_FILE", Some("<config-ed25519.h>"));
     }
 
     conf.file("../../boot/bootutil/src/image_validate.c");
     if sig_rsa || sig_rsa3072 {
         conf.file("../../boot/bootutil/src/image_rsa.c");
     } else if sig_ecdsa || sig_ecdsa_mbedtls {
+        conf.conf.include("../../ext/mbedtls/include");
         conf.file("../../boot/bootutil/src/image_ec256.c");
     } else if sig_ed25519 {
         conf.file("../../boot/bootutil/src/image_ed25519.c");
@@ -301,32 +367,33 @@
     conf.file("../../boot/bootutil/src/loader.c");
     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/caps.c");
     conf.file("../../boot/bootutil/src/bootutil_misc.c");
     conf.file("../../boot/bootutil/src/bootutil_public.c");
     conf.file("../../boot/bootutil/src/tlv.c");
     conf.file("../../boot/bootutil/src/fault_injection_hardening.c");
     conf.file("csupport/run.c");
-    conf.include("../../boot/bootutil/include");
-    conf.include("csupport");
-    conf.include("../../boot/zephyr/include");
-    conf.debug(true);
-    conf.flag("-Wall");
-    conf.flag("-Werror");
+    conf.conf.include("../../boot/bootutil/include");
+    conf.conf.include("csupport");
+    conf.conf.include("../../boot/zephyr/include");
+    conf.conf.debug(true);
+    conf.conf.flag("-Wall");
+    conf.conf.flag("-Werror");
 
     // FIXME: travis-ci still uses gcc 4.8.4 which defaults to std=gnu90.
     // It has incomplete std=c11 and std=c99 support but std=c99 was checked
     // to build correctly so leaving it here to updated in the future...
-    conf.flag("-std=c99");
+    conf.conf.flag("-std=c99");
 
-    conf.compile("libbootutil.a");
+    conf.conf.compile("libbootutil.a");
 
     walk_dir("../../boot").unwrap();
     walk_dir("../../ext/tinycrypt/lib/source").unwrap();
     walk_dir("../../ext/mbedtls-asn1").unwrap();
     walk_dir("csupport").unwrap();
-    walk_dir("../../ext/mbedtls/crypto/include").unwrap();
-    walk_dir("../../ext/mbedtls/crypto/library").unwrap();
+    walk_dir("../../ext/mbedtls/include").unwrap();
+    walk_dir("../../ext/mbedtls/library").unwrap();
 }
 
 // Output the names of all files within a directory so that Cargo knows when to rebuild.
@@ -347,3 +414,30 @@
 
     Ok(())
 }
+
+/// Wrap the cc::Build type so that we can make sure that files are only added a single time.
+/// Other methods can be passed through as needed.
+struct CachedBuild {
+    conf: cc::Build,
+    seen: BTreeSet<PathBuf>,
+}
+
+impl CachedBuild {
+    fn new() -> CachedBuild {
+        CachedBuild {
+            conf: cc::Build::new(),
+            seen: BTreeSet::new(),
+        }
+    }
+
+    /// Works like `file` in the Build, but doesn't add a file if the same path has already been
+    /// given.
+    fn file<P: AsRef<Path>>(&mut self, p: P) -> &mut CachedBuild {
+        let p = p.as_ref();
+        if !self.seen.contains(p) {
+            self.conf.file(p);
+            self.seen.insert(p.to_owned());
+        }
+        self
+    }
+}
diff --git a/sim/mcuboot-sys/csupport/devicetree.h b/sim/mcuboot-sys/csupport/devicetree.h
index 73c7c83..22a7fe6 100644
--- a/sim/mcuboot-sys/csupport/devicetree.h
+++ b/sim/mcuboot-sys/csupport/devicetree.h
@@ -9,6 +9,8 @@
 #ifndef __DEVICETREE_H__
 #define __DEVICETREE_H__
 
+#define FLASH_AREA_ERROR             255u
+
 #define FLASH_AREA_ID(x) FLASH_AREA_ID_##x
 
 #define FLASH_AREA_ID_image_0 1
@@ -17,11 +19,16 @@
 #define FLASH_AREA_ID_image_2 4
 #define FLASH_AREA_ID_image_3 5
 
-#define FLASH_AREA_IMAGE_0     FLASH_AREA_ID(image_0)
-#define FLASH_AREA_IMAGE_1     FLASH_AREA_ID(image_1)
-#define FLASH_AREA_IMAGE_2     FLASH_AREA_ID(image_2)
-#define FLASH_AREA_IMAGE_3     FLASH_AREA_ID(image_3)
+/*
+ * PSoC6 area defines based on file:
+ * boot/cypress/MCUBootApp/sysflash/sysflash.h
+*/
+#define FLASH_AREA_IMAGE_0 1
+#define FLASH_AREA_IMAGE_1 2
+#define FLASH_AREA_IMAGE_2 4
+#define FLASH_AREA_IMAGE_3 5
+#define FLASH_AREA_IMAGE_SWAP_STATUS 7
 
-#define FLASH_AREA_IMAGE_SWAP_STATUS FLASH_AREA_ID(image_scratch)
+#define BOOT_MAX_SWAP_STATUS_SECTORS 64
 
 #endif /*__DEVICETREE_H__*/
diff --git a/sim/mcuboot-sys/csupport/keys.c b/sim/mcuboot-sys/csupport/keys.c
index 8011629..f9325be 100644
--- a/sim/mcuboot-sys/csupport/keys.c
+++ b/sim/mcuboot-sys/csupport/keys.c
@@ -256,11 +256,20 @@
 #endif
 
 #if defined(MCUBOOT_ENCRYPT_KW)
+#if defined(MCUBOOT_AES_256)
+unsigned char enc_key[] = {
+  0xE4, 0x5C, 0x51, 0x46, 0xD2, 0x1C, 0x82, 0x35, 0xCC, 0x1A, 0x19, 0xAF,
+  0xA1, 0xF2, 0xAA, 0x20, 0xC8, 0x8C, 0x7F, 0x40, 0x6C, 0xDB, 0x22, 0xAA,
+  0x6A, 0xB5, 0xCB, 0xAA, 0xF8, 0xB1, 0x5B, 0xB4
+};
+static unsigned int enc_key_len = 32;
+#else
 unsigned char enc_key[] = {
   0xd1, 0x5a, 0x04, 0x95, 0xc4, 0xc2, 0xa8, 0xff, 0x30, 0x78, 0xce, 0x49,
   0xb5, 0xfc, 0xb2, 0xdd
 };
 static unsigned int enc_key_len = 16;
+#endif
 const struct bootutil_key bootutil_enc_key = {
     .key = enc_key,
     .len = &enc_key_len,
diff --git a/sim/mcuboot-sys/csupport/run.c b/sim/mcuboot-sys/csupport/run.c
index fd21bfd..fd6c3ca 100644
--- a/sim/mcuboot-sys/csupport/run.c
+++ b/sim/mcuboot-sys/csupport/run.c
@@ -22,7 +22,9 @@
 #include "mbedtls/nist_kw.h"
 #endif
 
+#define BOOT_LOG_LEVEL BOOT_LOG_LEVEL_ERROR
 #include <bootutil/bootutil_log.h>
+#include "bootutil/crypto/common.h"
 
 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
 
@@ -90,15 +92,15 @@
         return -6;
     }
 
-    if (mbedtls_asn1_get_mpi(p, end, &ctx->N) != 0) {
+    if (mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(N)) != 0) {
         return -7;
     }
 
-    if (mbedtls_asn1_get_mpi(p, end, &ctx->E) != 0) {
+    if (mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(E)) != 0) {
         return -8;
     }
 
-    ctx->len = mbedtls_mpi_size(&ctx->N);
+    ctx->MBEDTLS_CONTEXT_MEMBER(len) = mbedtls_mpi_size(&ctx->MBEDTLS_CONTEXT_MEMBER(N));
 
     if (*p != end) {
         return -9;
@@ -140,7 +142,12 @@
 
     mbedtls_platform_set_calloc_free(calloc, free);
 
+#if MBEDTLS_VERSION_NUMBER >= 0x03000000
+    mbedtls_rsa_init(&ctx);
+    mbedtls_rsa_set_padding(&ctx, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
+#else
     mbedtls_rsa_init(&ctx, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
+#endif
 
     cp = (uint8_t *)pubkey;
     cpend = cp + pubkey_len;
@@ -150,8 +157,13 @@
         goto done;
     }
 
+#if MBEDTLS_VERSION_NUMBER >= 0x03000000
+    rc = mbedtls_rsa_rsaes_oaep_encrypt(&ctx, fake_rng, NULL,
+            NULL, 0, seckey_len, seckey, encbuf);
+#else
     rc = mbedtls_rsa_rsaes_oaep_encrypt(&ctx, fake_rng, NULL, MBEDTLS_RSA_PUBLIC,
             NULL, 0, seckey_len, seckey, encbuf);
+#endif
     if (rc) {
         goto done;
     }
@@ -173,6 +185,15 @@
 int kw_encrypt_(const uint8_t *kek, const uint8_t *seckey, uint8_t *encbuf)
 {
 #ifdef MCUBOOT_ENCRYPT_KW
+#ifdef MCUBOOT_AES_256
+    int key_len = 256;
+    int out_size = 40;
+    int in_len = 32;
+#else
+    int key_len = 128;
+    int out_size = 24;
+    int in_len = 16;
+#endif
     mbedtls_nist_kw_context kw;
     size_t olen;
     int rc;
@@ -181,13 +202,13 @@
 
     mbedtls_nist_kw_init(&kw);
 
-    rc = mbedtls_nist_kw_setkey(&kw, MBEDTLS_CIPHER_ID_AES, kek, 128, 1);
+    rc = mbedtls_nist_kw_setkey(&kw, MBEDTLS_CIPHER_ID_AES, kek, key_len, 1);
     if (rc) {
         goto done;
     }
 
-    rc = mbedtls_nist_kw_wrap(&kw, MBEDTLS_KW_MODE_KW, seckey, 16, encbuf,
-            &olen, 24);
+    rc = mbedtls_nist_kw_wrap(&kw, MBEDTLS_KW_MODE_KW, seckey, in_len, encbuf,
+            &olen, out_size);
 
 done:
     mbedtls_nist_kw_free(&kw);
@@ -201,9 +222,9 @@
 #endif
 }
 
-uint16_t flash_area_align(const struct flash_area *area)
+size_t flash_area_align(const struct flash_area *area)
 {
-    return sim_flash_align(area->fa_device_id);
+    return (size_t)sim_flash_align(area->fa_device_id);
 }
 
 uint8_t flash_area_erased_val(const struct flash_area *area)
@@ -223,14 +244,16 @@
     uint32_t num_slots;
 };
 
-int invoke_boot_go(struct sim_context *ctx, struct area_desc *adesc)
+int invoke_boot_go(struct sim_context *ctx, struct area_desc *adesc,
+                   struct boot_rsp *rsp)
 {
     int res;
-    struct boot_rsp rsp;
     struct boot_loader_state *state;
 
 #if defined(MCUBOOT_SIGN_RSA) || \
-    (defined(MCUBOOT_SIGN_EC256) && defined(MCUBOOT_USE_MBED_TLS))
+    (defined(MCUBOOT_SIGN_EC256) && defined(MCUBOOT_USE_MBED_TLS)) ||\
+    (defined(MCUBOOT_ENCRYPT_EC256) && defined(MCUBOOT_USE_MBED_TLS)) ||\
+    (defined(MCUBOOT_ENCRYPT_X25519) && defined(MCUBOOT_USE_MBED_TLS))
     mbedtls_platform_set_calloc_free(calloc, free);
 #endif
 
@@ -241,7 +264,7 @@
     sim_set_context(ctx);
 
     if (setjmp(ctx->boot_jmpbuf) == 0) {
-        res = context_boot_go(state, &rsp);
+        res = context_boot_go(state, rsp);
         sim_reset_flash_areas();
         sim_reset_context();
         free(state);
@@ -261,53 +284,30 @@
     return malloc(size);
 }
 
-void os_free(void *mem)
-{
-    free(mem);
-}
-
-void *os_realloc(void *ptr, size_t size)
-{
-    return realloc(ptr, size);
-}
-
 int flash_area_id_from_multi_image_slot(int image_index, int slot)
 {
     switch (slot) {
     case 0: return FLASH_AREA_IMAGE_PRIMARY(image_index);
     case 1: return FLASH_AREA_IMAGE_SECONDARY(image_index);
     case 2: return FLASH_AREA_IMAGE_SCRATCH;
-
-    // case 7: return FLASH_AREA_IMAGE_SWAP_STATUS;
     }
 
-    printf("Image flash area ID not found, image=%d, slot=%d\n", image_index, slot);
+    printf("Image flash area ID not found\n");
     return -1; /* flash_area_open will fail on that */
 }
 
-int flash_area_id_from_image_slot(int slot)
-{
-    return flash_area_id_from_multi_image_slot(0, slot);
-}
-
 int flash_area_open(uint8_t id, const struct flash_area **area)
 {
     uint32_t i;
     struct area_desc *flash_areas;
 
-    // BOOT_LOG_SIM("%s: area id=%d, num_slots=%d", __func__, id, sim_get_flash_areas()->num_slots);
-
     flash_areas = sim_get_flash_areas();
     for (i = 0; i < flash_areas->num_slots; i++) {
-        // BOOT_LOG_SIM(" * flash_areas->slots[%d].id=%d", i, flash_areas->slots[i].id);
         if (flash_areas->slots[i].id == id)
-        {
-            // BOOT_LOG_SIM(" * found, i=%d, id=%d", i, id);
             break;
-        }
     }
     if (i == flash_areas->num_slots) {
-        printf("Unsupported area id=%d\n", id);
+        printf("Unsupported area\n");
         abort();
     }
 
@@ -354,6 +354,15 @@
         ctx->jumped++;
         longjmp(ctx->boot_jmpbuf, 1);
     }
+
+// 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;
+    off = sect_off;
+    BOOT_LOG_SIM("%s: erase with aligment at area=%d, off=%x, len=%x", __func__, area->fa_id, off, len);
+#endif
+
     return sim_flash_erase(area->fa_device_id, area->fa_off + off, len);
 }
 
@@ -363,22 +372,20 @@
     struct area *slot;
     struct area_desc *flash_areas;
 
-    // BOOT_LOG_SIM("%s: idx=%d", __func__, idx);
-
     flash_areas = sim_get_flash_areas();
     for (i = 0; i < flash_areas->num_slots; i++) {
         if (flash_areas->slots[i].id == idx)
             break;
     }
     if (i == flash_areas->num_slots) {
-        printf("flash_area_to_sectors: Unsupported area = %d\n", idx);
+        printf("Unsupported area\n");
         abort();
     }
 
     slot = &flash_areas->slots[i];
 
     if (slot->num_areas > (uint32_t)*cnt) {
-        printf("Too many areas in slot: %d > %d\n", slot->num_areas, *cnt);
+        printf("Too many areas in slot\n");
         abort();
     }
 
@@ -395,22 +402,20 @@
     struct area *slot;
     struct area_desc *flash_areas;
 
-    // BOOT_LOG_SIM("%s: area id=%d", __func__, fa_id);
-
     flash_areas = sim_get_flash_areas();
     for (i = 0; i < flash_areas->num_slots; i++) {
         if (flash_areas->slots[i].id == fa_id)
             break;
     }
     if (i == flash_areas->num_slots) {
-        printf("flash_area_get_sectors: Unsupported area = %d\n", fa_id);
+        printf("Unsupported area\n");
         abort();
     }
 
     slot = &flash_areas->slots[i];
 
     if (slot->num_areas > *count) {
-        printf("Too many areas in slot: %d > %d\n", slot->num_areas, *count);
+        printf("Too many areas in slot\n");
         abort();
     }
 
@@ -433,10 +438,20 @@
         return 1;
     }
 
-    printf("Unsupported image area ID=%d\n", area_id);
+    printf("Unsupported image area ID\n");
     abort();
 }
 
+uint8_t flash_area_get_device_id(const struct flash_area *fa)
+{
+    return fa->fa_device_id;
+}
+
+int flash_area_id_from_image_slot(int slot) {
+    /* For single image cases, just use the first image. */
+    return flash_area_id_from_multi_image_slot(0, slot);
+}
+
 void sim_assert(int x, const char *assertion, const char *file, unsigned int line, const char *function)
 {
     if (!(x)) {
@@ -463,28 +478,3 @@
 {
     return BOOT_MAGIC_SZ;
 }
-
-void mbedtls_platform_zeroize( void *buf, size_t len )
-{
-    memset( buf, 0, len );
-}
-
-int flash_area_read_is_empty(const struct flash_area *fa, uint32_t off,
-        void *dst, uint32_t len)
-{
-    uint8_t *mem_dest;
-    int rc;
-
-    mem_dest = (uint8_t *)dst;
-    rc = flash_area_read(fa, off, dst, len);
-    if (rc) {
-        return -1;
-    }
-
-    for (uint8_t i = 0; i < len; i++) {
-        if (mem_dest[i] != flash_area_erased_val(fa)) {
-            return 0;
-        }
-    }
-    return 1;
-}
diff --git a/sim/mcuboot-sys/csupport/storage/flash_map.h b/sim/mcuboot-sys/csupport/storage/flash_map.h
index 2a6fd56..7b20453 100644
--- a/sim/mcuboot-sys/csupport/storage/flash_map.h
+++ b/sim/mcuboot-sys/csupport/storage/flash_map.h
@@ -42,6 +42,7 @@
  * and match the target offset specified in download script.
  */
 #include <inttypes.h>
+#include <stddef.h>
 
 /**
  * @brief Structure describing an area on a flash device.
@@ -123,7 +124,7 @@
 /*
  * Alignment restriction for flash writes.
  */
-uint16_t flash_area_align(const struct flash_area *);
+size_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 a6acd53..8d1140d 100644
--- a/sim/mcuboot-sys/src/api.rs
+++ b/sim/mcuboot-sys/src/api.rs
@@ -26,6 +26,38 @@
 
 pub type FlashParams = HashMap<u8, FlashParamsStruct>;
 
+/// The `boot_rsp` structure used by boot_go.
+#[repr(C)]
+#[derive(Debug)]
+pub struct BootRsp {
+    pub br_hdr: *const ImageHeader,
+    pub flash_dev_id: u8,
+    pub image_off: u32,
+}
+
+// TODO: Don't duplicate this image header declaration.
+#[repr(C)]
+#[derive(Debug)]
+pub struct ImageHeader {
+    magic: u32,
+    load_addr: u32,
+    hdr_size: u16,
+    protect_tlv_size: u16,
+    img_size: u32,
+    flags: u32,
+    ver: ImageVersion,
+    _pad2: u32,
+}
+
+#[repr(C)]
+#[derive(Debug)]
+pub struct ImageVersion {
+    pub major: u8,
+    pub minor: u8,
+    pub revision: u16,
+    pub build_num: u32,
+}
+
 pub struct CAreaDescPtr {
    pub ptr: *const CAreaDesc,
 }
@@ -89,9 +121,20 @@
     }
 }
 
+/// This struct describes the RAM layout of the current device.  It will be stashed, per test
+/// thread, and queried by the C code.
+#[repr(C)]
+#[derive(Debug, Default)]
+pub struct BootsimRamInfo {
+    pub start: u32,
+    pub size: u32,
+    pub base: usize,
+}
+
 thread_local! {
     pub static THREAD_CTX: RefCell<FlashContext> = RefCell::new(FlashContext::new());
     pub static SIM_CTX: RefCell<CSimContextPtr> = RefCell::new(CSimContextPtr::new());
+    pub static RAM_CTX: RefCell<BootsimRamInfo> = RefCell::new(BootsimRamInfo::default());
 }
 
 /// Set the flash device to be used by the simulation.  The pointer is unsafely stashed away.
@@ -165,6 +208,32 @@
 }
 
 #[no_mangle]
+pub extern "C" fn bootsim_get_ram_info() -> *const BootsimRamInfo {
+    RAM_CTX.with(|ctx| {
+        if ctx.borrow().base == 0 {
+            // Option is messier to get a pointer out of, so just check if the base has been set to
+            // anything.
+            panic!("ram info not set, but being used");
+        }
+        ctx.as_ptr()
+    })
+}
+
+/// Store a copy of this RAM info.
+pub fn set_ram_info(info: BootsimRamInfo) {
+    RAM_CTX.with(|ctx| {
+        ctx.replace(info);
+    });
+}
+
+/// Clear out the ram info.
+pub fn clear_ram_info() {
+    RAM_CTX.with(|ctx| {
+        ctx.borrow_mut().base = 0;
+    });
+}
+
+#[no_mangle]
 pub extern fn sim_flash_erase(dev_id: u8, offset: u32, size: u32) -> libc::c_int {
     let mut rc: libc::c_int = -19;
     THREAD_CTX.with(|ctx| {
diff --git a/sim/mcuboot-sys/src/area.rs b/sim/mcuboot-sys/src/area.rs
index f151fe4..cfbebda 100644
--- a/sim/mcuboot-sys/src/area.rs
+++ b/sim/mcuboot-sys/src/area.rs
@@ -189,8 +189,8 @@
     ImageScratch = 3,
     Image2 = 4,
     Image3 = 5,
-    //ImageSwapStatus = 7,
-    //ImageSwapStatus = 3,
+//    Not_used = 6,
+    ImageSwapStatus = 7,
 }
 
 impl Default for FlashId {
diff --git a/sim/mcuboot-sys/src/c.rs b/sim/mcuboot-sys/src/c.rs
index 5f518f5..5c791b8 100644
--- a/sim/mcuboot-sys/src/c.rs
+++ b/sim/mcuboot-sys/src/c.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-2021 Arm Limited
 //
 // SPDX-License-Identifier: Apache-2.0
 
@@ -10,9 +10,61 @@
 use simflash::SimMultiFlash;
 use crate::api;
 
+/// The result of an invocation of `boot_go`.  This is intentionally opaque so that we can provide
+/// accessors for everything we need from this.
+#[derive(Debug)]
+pub enum BootGoResult {
+    /// This run was stopped by the flash simulation mechanism.
+    Stopped,
+    /// The bootloader ran to completion with the following data.
+    Normal {
+        result: i32,
+        asserts: u8,
+
+        resp: api::BootRsp,
+    },
+}
+
+impl BootGoResult {
+    /// Was this run interrupted.
+    pub fn interrupted(&self) -> bool {
+        matches!(self, BootGoResult::Stopped)
+    }
+
+    /// Was this boot run successful (returned 0)
+    pub fn success(&self) -> bool {
+        matches!(self, BootGoResult::Normal { result: 0, .. })
+    }
+
+    /// Success, but also no asserts.
+    pub fn success_no_asserts(&self) -> bool {
+        matches!(self, BootGoResult::Normal {
+            result: 0,
+            asserts: 0,
+            ..
+        })
+    }
+
+    /// Get the asserts count.  An interrupted run will be considered to have no asserts.
+    pub fn asserts(&self) -> u8 {
+        match self {
+            BootGoResult::Normal { asserts, .. } => *asserts,
+            _ => 0,
+        }
+    }
+
+    /// Retrieve the 'resp' field that is filled in.
+    pub fn resp(&self) -> Option<&api::BootRsp> {
+        match self {
+            BootGoResult::Normal { resp, .. } => Some(resp),
+            _ => None,
+        }
+    }
+}
+
 /// Invoke the bootloader on this flash device.
 pub fn boot_go(multiflash: &mut SimMultiFlash, areadesc: &AreaDesc,
-               counter: Option<&mut i32>, catch_asserts: bool) -> (i32, u8) {
+               counter: Option<&mut i32>, catch_asserts: bool) -> BootGoResult {
     for (&dev_id, flash) in multiflash.iter_mut() {
         api::set_flash(dev_id, flash);
     }
@@ -26,8 +78,14 @@
         c_catch_asserts: if catch_asserts { 1 } else { 0 },
         boot_jmpbuf: [0; 16],
     };
+    let mut rsp = api::BootRsp {
+        br_hdr: std::ptr::null(),
+        flash_dev_id: 0,
+        image_off: 0,
+    };
     let result = unsafe {
-        raw::invoke_boot_go(&mut sim_ctx as *mut _, &areadesc.get_c() as *const _) as i32
+        raw::invoke_boot_go(&mut sim_ctx as *mut _, &areadesc.get_c() as *const _,
+            &mut rsp as *mut _) as i32
     };
     let asserts = sim_ctx.c_asserts;
     if let Some(c) = counter {
@@ -36,7 +94,11 @@
     for &dev_id in multiflash.keys() {
         api::clear_flash(dev_id);
     }
-    (result, asserts)
+    if result == -0x13579 {
+        BootGoResult::Stopped
+    } else {
+        BootGoResult::Normal { result, asserts, resp: rsp }
+    }
 }
 
 pub fn boot_trailer_sz(align: u32) -> u32 {
@@ -67,9 +129,12 @@
     }
 }
 
-pub fn kw_encrypt(kek: &[u8], seckey: &[u8]) -> Result<[u8; 24], &'static str> {
+pub fn kw_encrypt(kek: &[u8], seckey: &[u8], keylen: u32) -> Result<Vec<u8>, &'static str> {
     unsafe {
-        let mut encbuf = [0u8; 24];
+        let mut encbuf = vec![0u8; 24];
+        if keylen == 32 {
+            encbuf = vec![0u8; 40];
+        }
         if raw::kw_encrypt_(kek.as_ptr(), seckey.as_ptr(), encbuf.as_mut_ptr()) == 0 {
             return Ok(encbuf);
         }
@@ -79,13 +144,14 @@
 
 mod raw {
     use crate::area::CAreaDesc;
-    use crate::api::CSimContext;
+    use crate::api::{BootRsp, CSimContext};
 
     extern "C" {
         // This generates a warning about `CAreaDesc` not being foreign safe.  There doesn't appear to
         // 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) -> libc::c_int;
+        pub fn invoke_boot_go(sim_ctx: *mut CSimContext, areadesc: *const CAreaDesc,
+            rsp: *mut BootRsp) -> 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/mcuboot-sys/src/lib.rs b/sim/mcuboot-sys/src/lib.rs
index 8acb246..bc3fc49 100644
--- a/sim/mcuboot-sys/src/lib.rs
+++ b/sim/mcuboot-sys/src/lib.rs
@@ -10,3 +10,43 @@
 pub mod api;
 
 pub use crate::area::{AreaDesc, FlashId};
+
+/// For testing the ram load feature, we need to emulate a block of RAM and be able to pass that
+/// down to the C code.  The call down to boot_go should go through this object so that the buffer
+/// itself is managed properly.
+pub struct RamBlock {
+    ram: Vec<u8>,
+    offset: u32, // 32-bit offset.
+}
+
+impl RamBlock {
+    pub fn new(size: u32, offset: u32) -> RamBlock {
+        RamBlock {
+            ram: vec![0; size as usize],
+            offset: offset,
+        }
+    }
+
+    /// Borrow the RAM buffer, with 'offset' being the beginning of the buffer.
+    pub fn borrow(&self) -> &[u8] {
+        &self.ram
+    }
+
+    /// Borrow a piece of the ram, with 'offset' being the beginning of the buffer.
+    pub fn borrow_part(&self, base: usize, size: usize) -> &[u8] {
+        &self.ram[base..base+size]
+    }
+
+    pub fn invoke<F, R>(&self, act: F) -> R
+        where F: FnOnce() -> R
+    {
+        api::set_ram_info(api::BootsimRamInfo {
+            start: self.offset,
+            size: self.ram.len() as u32,
+            base: &self.ram[0] as *const u8 as usize - self.offset as usize,
+        });
+        let result = act();
+        api::clear_ram_info();
+        result
+    }
+}
diff --git a/sim/simflash/src/lib.rs b/sim/simflash/src/lib.rs
index c52f53e..e5ccb96 100644
--- a/sim/simflash/src/lib.rs
+++ b/sim/simflash/src/lib.rs
@@ -66,8 +66,6 @@
 
     fn align(&self) -> usize;
     fn erased_val(&self) -> u8;
-
-    fn set_erase_by_sector(&mut self, enable: bool);
 }
 
 fn ebounds<T: AsRef<str>>(message: T) -> FlashError {
@@ -96,7 +94,6 @@
     align: usize,
     verify_writes: bool,
     erased_val: u8,
-    erase_by_sector: bool,
 }
 
 impl SimFlash {
@@ -133,11 +130,11 @@
 
     // Scan the sector map, and return the base and offset within a sector for this given byte.
     // Returns None if the value is outside of the device.
-    fn get_sector(&self, offset: usize) -> Option<(usize, usize, usize)> {
+    fn get_sector(&self, offset: usize) -> Option<(usize, usize)> {
         let mut offset = offset;
         for (sector, &size) in self.sectors.iter().enumerate() {
             if offset < size {
-                return Some((sector, offset, size));
+                return Some((sector, offset));
             }
             offset -= size;
         }
@@ -153,21 +150,8 @@
     /// strict, and make sure that the passed arguments are exactly at a sector boundary, otherwise
     /// return an error.
     fn erase(&mut self, offset: usize, len: usize) -> Result<()> {
-        let (_start, mut slen, ssize) = self.get_sector(offset).ok_or_else(|| ebounds("start"))?;
-        let (end, mut elen, _) = self.get_sector(offset + len - 1).ok_or_else(|| ebounds("end"))?;
-
-        let mut offset = offset;
-        let mut len = len;
-
-        if self.erase_by_sector {
-            // info!("erase_by_sector: {:#X}/{:#X} -> {:#X}/{:#X}", offset, len, offset - slen, ssize);
-
-            offset = offset - slen;
-            len = ssize;
-
-            slen = 0;
-            elen = self.sectors[end] - 1;
-        }
+        let (_start, slen) = self.get_sector(offset).ok_or_else(|| ebounds("start"))?;
+        let (end, elen) = self.get_sector(offset + len - 1).ok_or_else(|| ebounds("end"))?;
 
         if slen != 0 {
             bail!(ebounds("offset not at start of sector"));
@@ -283,10 +267,6 @@
     fn erased_val(&self) -> u8 {
         self.erased_val
     }
-
-    fn set_erase_by_sector(&mut self, enable: bool) {
-        self.erase_by_sector = enable;
-    }
 }
 
 /// It is possible to iterate over the sectors in the device, each element returning this.
@@ -339,6 +319,10 @@
             let mut f2 = SimFlash::new(vec![16 * 1024, 16 * 1024, 16 * 1024, 64 * 1024,
                                     128 * 1024, 128 * 1024, 128 * 1024], 1, erased_val);
             test_device(&mut f2, erased_val);
+
+            // PSoC style, uniform sectors.
+            let mut f3 = SimFlash::new(vec![512usize; 1024], 512, erased_val);
+            test_device(&mut f3, erased_val);
         }
     }
 
diff --git a/sim/src/caps.rs b/sim/src/caps.rs
index c626ee6..3fbf4c3 100644
--- a/sim/src/caps.rs
+++ b/sim/src/caps.rs
@@ -1,6 +1,6 @@
 // Copyright (c) 2017-2019 Linaro LTD
 // Copyright (c) 2019 JUUL Labs
-// Copyright (c) 2019 Arm Limited
+// Copyright (c) 2019-2021 Arm Limited
 //
 // SPDX-License-Identifier: Apache-2.0
 
@@ -25,7 +25,10 @@
     DowngradePrevention  = (1 << 12),
     EncX25519            = (1 << 13),
     Bootstrap            = (1 << 14),
-    SwapUsingStatus      = (1 << 15),
+    Aes256               = (1 << 15),
+    RamLoad              = (1 << 16),
+    DirectXip            = (1 << 17),
+    SwapUsingStatus      = (1 << 18),
 }
 
 impl Caps {
@@ -39,6 +42,12 @@
     pub fn get_num_images() -> usize {
         (unsafe { bootutil_get_num_images() }) as usize
     }
+
+    /// Query if this configuration performs some kind of upgrade by writing to flash.
+    pub fn modifies_flash() -> bool {
+        // All other configurations perform upgrades by writing to flash.
+        !(Self::RamLoad.present() || Self::DirectXip.present())
+    }
 }
 
 extern "C" {
diff --git a/sim/src/image.rs b/sim/src/image.rs
index 6bd14c5..29ddedd 100644
--- a/sim/src/image.rs
+++ b/sim/src/image.rs
@@ -1,6 +1,6 @@
 // Copyright (c) 2019 Linaro LTD
 // Copyright (c) 2019-2020 JUUL Labs
-// Copyright (c) 2019 Arm Limited
+// Copyright (c) 2019-2021 Arm Limited
 //
 // SPDX-License-Identifier: Apache-2.0
 
@@ -19,22 +19,26 @@
     rngs::SmallRng,
 };
 use std::{
-    collections::HashSet,
+    collections::{BTreeMap, HashSet},
     io::{Cursor, Write},
     mem,
     slice,
 };
-use aes_ctr::{
+use aes::{
+    Aes128,
     Aes128Ctr,
-    stream_cipher::{
-        generic_array::GenericArray,
-        NewStreamCipher,
-        SyncStreamCipher,
-    },
+    Aes256,
+    Aes256Ctr,
+    NewBlockCipher,
 };
+use cipher::{
+    FromBlockCipher,
+    generic_array::GenericArray,
+    StreamCipher,
+    };
 
 use simflash::{Flash, SimFlash, SimMultiFlash};
-use mcuboot_sys::{c, AreaDesc, FlashId};
+use mcuboot_sys::{c, AreaDesc, FlashId, RamBlock};
 use crate::{
     ALL_DEVICES,
     DeviceName,
@@ -50,6 +54,11 @@
     UpgradeInfo,
 };
 use crate::tlv::{ManifestGen, TlvGen, TlvFlags};
+use typenum::{U32, U16};
+
+/// For testing, use a non-zero offset for the ram-load, to make sure the offset is getting used
+/// properly, but the value is not really that important.
+const RAM_LOAD_ADDR: u32 = 1024;
 
 /// A builder for Images.  This describes a single run of the simulator,
 /// capturing the configuration of a particular set of devices, including
@@ -59,6 +68,7 @@
     flash: SimMultiFlash,
     areadesc: AreaDesc,
     slots: Vec<[SlotInfo; 2]>,
+    ram: RamData,
 }
 
 /// Images represents the state of a simulation for a given set of images.
@@ -69,6 +79,7 @@
     areadesc: AreaDesc,
     images: Vec<OneImage>,
     total_count: Option<i32>,
+    ram: RamData,
 }
 
 /// When doing multi-image, there is an instance of this information for
@@ -83,10 +94,34 @@
 /// is just the unencrypted payload.  For encrypted images, we store both
 /// the encrypted and the plaintext.
 struct ImageData {
+    size: usize,
     plain: Vec<u8>,
     cipher: Option<Vec<u8>>,
 }
 
+/// For the RamLoad test cases, we need a contiguous area of RAM to load these images into.  For
+/// multi-image builds, these may not correspond with the offsets.  This has to be computed early,
+/// before images are built, because each image contains the offset where the image is to be loaded
+/// in the header, which is contained within the signature.
+#[derive(Clone, Debug)]
+struct RamData {
+    places: BTreeMap<SlotKey, SlotPlace>,
+    total: u32,
+}
+
+/// Every slot is indexed by this key.
+#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
+struct SlotKey {
+    dev_id: u8,
+    base_off: usize,
+}
+
+#[derive(Clone, Debug)]
+struct SlotPlace {
+    offset: u32,
+    size: u32,
+}
+
 impl ImagesBuilder {
     /// Construct a new image builder for the given device.  Returns
     /// Some(builder) if is possible to test this configuration, or None if
@@ -148,10 +183,13 @@
             slots.push([primary, secondary]);
         }
 
+        let ram = RamData::new(&slots);
+
         Ok(ImagesBuilder {
             flash,
             areadesc,
             slots,
+            ram,
         })
     }
 
@@ -174,16 +212,17 @@
     pub fn make_no_upgrade_image(self, deps: &DepTest) -> Images {
         let num_images = self.num_images();
         let mut flash = self.flash;
+        let ram = self.ram.clone();  // TODO: This is wasteful.
         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], 42784, &*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, &*dep, false)
+                _ => install_image(&mut flash, &slots[1], 46928, &ram, &*dep, false)
             };
             OneImage {
                 slots,
@@ -196,6 +235,7 @@
             areadesc: self.areadesc,
             images,
             total_count: None,
+            ram: self.ram,
         }
     }
 
@@ -205,6 +245,11 @@
             mark_upgrade(&mut images.flash, &image.slots[1]);
         }
 
+        // The count is meaningless if no flash operations are performed.
+        if !Caps::modifies_flash() {
+            return images;
+        }
+
         // upgrades without fails, counts number of flash operations
         let total_count = match images.run_basic_upgrade(permanent) {
             Some(v)  => v,
@@ -222,10 +267,11 @@
 
     pub fn make_bad_secondary_slot_image(self) -> Images {
         let mut bad_flash = self.flash;
+        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, &dep, false);
-            let upgrades = install_image(&mut bad_flash, &slots[1], 41928, &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,
@@ -236,14 +282,16 @@
             areadesc: self.areadesc,
             images,
             total_count: None,
+            ram: self.ram,
         }
     }
 
     pub fn make_erased_secondary_image(self) -> Images {
         let mut flash = self.flash;
+        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, &dep, false);
+            let primaries = install_image(&mut flash, &slots[0], 32784, &ram, &dep, false);
             let upgrades = install_no_image();
             OneImage {
                 slots,
@@ -255,15 +303,17 @@
             areadesc: self.areadesc,
             images,
             total_count: None,
+            ram: self.ram,
         }
     }
 
     pub fn make_bootstrap_image(self) -> Images {
         let mut flash = self.flash;
+        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_no_image();
-            let upgrades = install_image(&mut flash, &slots[1], 32784, &dep, false);
+            let upgrades = install_image(&mut flash, &slots[1], 32784, &ram, &dep, false);
             OneImage {
                 slots,
                 primaries,
@@ -274,15 +324,14 @@
             areadesc: self.areadesc,
             images,
             total_count: None,
+            ram: self.ram,
         }
     }
 
     /// Build the Flash and area descriptor for a given device.
     pub fn make_device(device: DeviceName, align: usize, erased_val: u8) -> (SimMultiFlash, AreaDesc, &'static [Caps]) {
-        info!(" +++ Make new device...");
         match device {
             DeviceName::Stm32f4 => {
-                info!("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,
@@ -300,7 +349,6 @@
                 (flash, areadesc, &[Caps::SwapUsingMove, Caps::SwapUsingStatus])
             }
             DeviceName::K64f => {
-                info!("DeviceName::K64f");
                 // NXP style flash.  Small sectors, one small sector for scratch.
                 let dev = SimFlash::new(vec![4096; 128], align as usize, erased_val);
 
@@ -316,7 +364,6 @@
                 (flash, areadesc, &[Caps::SwapUsingStatus])
             }
             DeviceName::K64fBig => {
-                info!("DeviceName::K64fBig");
                 // Simulating an STM style flash on top of an NXP style flash.  Underlying flash device
                 // uses small sectors, but we tell the bootloader they are large.
                 let dev = SimFlash::new(vec![4096; 128], align as usize, erased_val);
@@ -333,7 +380,6 @@
                 (flash, areadesc, &[Caps::SwapUsingMove, Caps::SwapUsingStatus])
             }
             DeviceName::Nrf52840 => {
-                info!("DeviceName::Nrf52840");
                 // Simulating the flash on the nrf52840 with partitions set up so that the scratch size
                 // does not divide into the image size.
                 let dev = SimFlash::new(vec![4096; 128], align as usize, erased_val);
@@ -350,7 +396,6 @@
                 (flash, areadesc, &[Caps::SwapUsingStatus])
             }
             DeviceName::Nrf52840UnequalSlots => {
-                info!("DeviceName::Nrf52840UnequalSlots");
                 let dev = SimFlash::new(vec![4096; 128], align as usize, erased_val);
 
                 let dev_id = 0;
@@ -364,7 +409,6 @@
                 (flash, areadesc, &[Caps::SwapUsingScratch, Caps::OverwriteUpgrade, Caps::SwapUsingStatus])
             }
             DeviceName::Nrf52840SpiFlash => {
-                info!("DeviceName::Nrf52840SpiFlash");
                 // Simulate nrf52840 with external SPI flash. The external SPI flash
                 // has a larger sector size so for now store scratch on that flash.
                 let dev0 = SimFlash::new(vec![4096; 128], align as usize, erased_val);
@@ -384,7 +428,6 @@
                 (flash, areadesc, &[Caps::SwapUsingMove, Caps::SwapUsingStatus])
             }
             DeviceName::K64fMulti => {
-                info!("DeviceName::K64fMulti");
                 // NXP style flash, but larger, to support multiple images.
                 let dev = SimFlash::new(vec![4096; 256], align as usize, erased_val);
 
@@ -401,32 +444,21 @@
                 flash.insert(dev_id, dev);
                 (flash, areadesc, &[Caps::SwapUsingStatus])
             }
-            DeviceName::PSoC6Multi => {
-                info!("DeviceName::PSoC6Multi");
-                // NXP style flash, but larger, to support multiple images.
+            DeviceName::PSoC6 => {
+            // PSoC style flash of 512K, single-image case
+                let dev = SimFlash::new(vec![512; 1024], align as usize, erased_val);
 
+                let dev_id = 0;
                 let mut areadesc = AreaDesc::new();
+                areadesc.add_flash_sectors(dev_id, &dev);
+                areadesc.add_image(0x018000, 0x010000, FlashId::Image0, dev_id);
+                areadesc.add_image(0x028000, 0x010000, FlashId::Image1, dev_id);
+                areadesc.add_image(0x039800, 0x001000, FlashId::ImageScratch, dev_id);
+                areadesc.add_image(0x038000, 0x001800, FlashId::ImageSwapStatus, dev_id);
+
                 let mut flash = SimMultiFlash::new();
-
-                // let dev0 = SimFlash::new(vec![4096; 256], align as usize, 0);
-                let mut dev0 = SimFlash::new(vec![512; 1024], align as usize, 0);
-                dev0.set_verify_writes(false);
-                dev0.set_erase_by_sector(true);
-
-                areadesc.add_flash_sectors(0, &dev0);
-                areadesc.add_image(0x020000, 0x020000, FlashId::Image0, 0);
-                areadesc.add_image(0x040000, 0x020000, FlashId::Image1, 0);
-                areadesc.add_image(0x060000, 0x008000, FlashId::ImageScratch, 0);
-                flash.insert(0, dev0);
-
-                // let dev1 = SimFlash::new(vec![4096; 256], align as usize, erased_val);
-                // areadesc.add_flash_sectors(1, &dev1);
-                // areadesc.add_image(0x080000, 0x020000, FlashId::Image2, 0);
-                // areadesc.add_image(0x0a0000, 0x020000, FlashId::Image3, 1);
-                // flash.insert(1, dev1);
-
-                // (flash, areadesc, &[])
-                (flash, areadesc, &[Caps::SwapUsingScratch, Caps::SwapUsingMove])
+                flash.insert(dev_id, dev);
+                (flash, areadesc, &[Caps::SwapUsingMove])
             }
         }
     }
@@ -461,8 +493,7 @@
         if Caps::Bootstrap.present() {
             info!("Try bootstraping image in the primary");
 
-            let (result, _) = c::boot_go(&mut flash, &self.areadesc, None, false);
-            if result != 0 {
+            if !c::boot_go(&mut flash, &self.areadesc, None, false).success() {
                 warn!("Failed first boot");
                 fails += 1;
             }
@@ -490,17 +521,21 @@
     /// 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 {
+        if !Caps::modifies_flash() {
+            return false;
+        }
+
         let (flash, _) = self.try_upgrade(None, true);
 
         self.verify_dep_images(&flash, deps)
     }
 
     fn is_swap_upgrade(&self) -> bool {
-        Caps::SwapUsingScratch.present() || Caps::SwapUsingMove.present() || Caps::SwapUsingStatus.present()
+        Caps::SwapUsingScratch.present() || Caps::SwapUsingMove.present()
     }
 
     pub fn run_basic_revert(&self) -> bool {
-        if Caps::OverwriteUpgrade.present() {
+        if Caps::OverwriteUpgrade.present() || !Caps::modifies_flash() {
             return false;
         }
 
@@ -522,6 +557,10 @@
     }
 
     pub fn run_perm_with_fails(&self) -> bool {
+        if !Caps::modifies_flash() {
+            return false;
+        }
+
         let mut fails = 0;
         let total_flash_ops = self.total_count.unwrap();
 
@@ -563,6 +602,10 @@
     }
 
     pub fn run_perm_with_random_fails(&self, total_fails: usize) -> bool {
+        if !Caps::modifies_flash() {
+            return false;
+        }
+
         let mut fails = 0;
         let total_flash_ops = self.total_count.unwrap();
         let (flash, total_counts) = self.try_random_fails(total_flash_ops, total_fails);
@@ -601,7 +644,7 @@
     }
 
     pub fn run_revert_with_fails(&self) -> bool {
-        if Caps::OverwriteUpgrade.present() {
+        if Caps::OverwriteUpgrade.present() || !Caps::modifies_flash() {
             return false;
         }
 
@@ -621,7 +664,7 @@
     }
 
     pub fn run_norevert(&self) -> bool {
-        if Caps::OverwriteUpgrade.present() {
+        if Caps::OverwriteUpgrade.present() || !Caps::modifies_flash() {
             return false;
         }
 
@@ -631,8 +674,7 @@
         info!("Try norevert");
 
         // First do a normal upgrade...
-        let (result, _) = c::boot_go(&mut flash, &self.areadesc, None, false);
-        if result != 0 {
+        if !c::boot_go(&mut flash, &self.areadesc, None, false).success() {
             warn!("Failed first boot");
             fails += 1;
         }
@@ -665,8 +707,7 @@
             fails += 1;
         }
 
-        let (result, _) = c::boot_go(&mut flash, &self.areadesc, None, false);
-        if result != 0 {
+        if !c::boot_go(&mut flash, &self.areadesc, None, false).success() {
             warn!("Failed second boot");
             fails += 1;
         }
@@ -701,8 +742,7 @@
         info!("Try no downgrade");
 
         // First, do a normal upgrade.
-        let (result, _) = c::boot_go(&mut flash, &self.areadesc, None, false);
-        if result != 0 {
+        if !c::boot_go(&mut flash, &self.areadesc, None, false).success() {
             warn!("Failed first boot");
             fails += 1;
         }
@@ -723,6 +763,11 @@
     // image_ok set while there is no image on the secondary slot, so no revert
     // should ever happen...
     pub fn run_norevert_newimage(&self) -> bool {
+        if !Caps::modifies_flash() {
+            info!("Skipping run_norevert_newimage, as configuration doesn't modify flash");
+            return false;
+        }
+
         let mut flash = self.flash.clone();
         let mut fails = 0;
 
@@ -739,8 +784,7 @@
         }
 
         // Run the bootloader...
-        let (result, _) = c::boot_go(&mut flash, &self.areadesc, None, false);
-        if result != 0 {
+        if !c::boot_go(&mut flash, &self.areadesc, None, false).success() {
             warn!("Failed first boot");
             fails += 1;
         }
@@ -777,6 +821,12 @@
 
         info!("Try upgrade image with bad signature");
 
+        // Only perform this test if an upgrade is expected to happen.
+        if !Caps::modifies_flash() {
+            info!("Skipping upgrade image with bad signature");
+            return false;
+        }
+
         self.mark_upgrades(&mut flash, 0);
         self.mark_permanent_upgrades(&mut flash, 0);
         self.mark_upgrades(&mut flash, 1);
@@ -788,8 +838,7 @@
         }
 
         // Run the bootloader...
-        let (result, _) = c::boot_go(&mut flash, &self.areadesc, None, false);
-        if result != 0 {
+        if !c::boot_go(&mut flash, &self.areadesc, None, false).success() {
             warn!("Failed first boot");
             fails += 1;
         }
@@ -815,6 +864,10 @@
     // Should detect there is a leftover trailer in an otherwise erased
     // secondary slot and erase its trailer.
     pub fn run_secondary_leftover_trailer(&self) -> bool {
+        if !Caps::modifies_flash() {
+            return false;
+        }
+
         let mut flash = self.flash.clone();
         let mut fails = 0;
 
@@ -825,8 +878,7 @@
         self.mark_upgrades(&mut flash, 1);
 
         // Run the bootloader...
-        let (result, _) = c::boot_go(&mut flash, &self.areadesc, None, false);
-        if result != 0 {
+        if !c::boot_go(&mut flash, &self.areadesc, None, false).success() {
             warn!("Failed first boot");
             fails += 1;
         }
@@ -861,7 +913,7 @@
     /// allowing for fails in the status area. This should run to the end
     /// and warn that write fails were detected...
     pub fn run_with_status_fails_complete(&self) -> bool {
-        if !Caps::ValidatePrimarySlot.present() {
+        if !Caps::ValidatePrimarySlot.present() || !Caps::modifies_flash() {
             return false;
         }
 
@@ -873,15 +925,15 @@
         self.mark_permanent_upgrades(&mut flash, 1);
         self.mark_bad_status_with_rate(&mut flash, 0, 1.0);
 
-        let (result, asserts) = c::boot_go(&mut flash, &self.areadesc, None, true);
-        if result != 0 {
+        let result = c::boot_go(&mut flash, &self.areadesc, None, true);
+        if !result.success() {
             warn!("Failed!");
             fails += 1;
         }
 
         // Failed writes to the marked "bad" region don't assert anymore.
         // Any detected assert() is happening in another part of the code.
-        if asserts != 0 {
+        if result.asserts() != 0 {
             warn!("At least one assert() was called");
             fails += 1;
         }
@@ -899,8 +951,7 @@
 
         info!("validate primary slot enabled; \
                re-run of boot_go should just work");
-        let (result, _) = c::boot_go(&mut flash, &self.areadesc, None, false);
-        if result != 0 {
+        if !c::boot_go(&mut flash, &self.areadesc, None, false).success() {
             warn!("Failed!");
             fails += 1;
         }
@@ -916,7 +967,7 @@
     /// allowing for fails in the status area. This should run to the end
     /// and warn that write fails were detected...
     pub fn run_with_status_fails_with_reset(&self) -> bool {
-        if Caps::OverwriteUpgrade.present() {
+        if Caps::OverwriteUpgrade.present() || !Caps::modifies_flash() {
             false
         } else if Caps::ValidatePrimarySlot.present() {
 
@@ -932,7 +983,7 @@
             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);
+            let asserts = c::boot_go(&mut flash, &self.areadesc, Some(&mut count), true).asserts();
             if asserts != 0 {
                 warn!("At least one assert() was called");
                 fails += 1;
@@ -941,7 +992,7 @@
             self.reset_bad_status(&mut flash, 0);
 
             info!("Resuming an interrupted swap operation");
-            let (_, asserts) = c::boot_go(&mut flash, &self.areadesc, None, true);
+            let asserts = c::boot_go(&mut flash, &self.areadesc, None, true).asserts();
 
             // This might throw no asserts, for large sector devices, where
             // a single failure writing is indistinguishable from no failure,
@@ -968,7 +1019,7 @@
             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);
+            let asserts = c::boot_go(&mut flash, &self.areadesc, None, true).asserts();
             if asserts == 0 {
                 warn!("No assert() detected");
                 fails += 1;
@@ -978,6 +1029,78 @@
         }
     }
 
+    /// Test the direct XIP configuration.  With this mode, flash images are never moved, and the
+    /// bootloader merely selects which partition is the proper one to boot.
+    pub fn run_direct_xip(&self) -> bool {
+        if !Caps::DirectXip.present() {
+            return false;
+        }
+
+        // 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);
+
+        // Ensure the boot was successful.
+        let resp = if let Some(resp) = result.resp() {
+            resp
+        } else {
+            panic!("Boot didn't return a valid result");
+        };
+
+        // This configuration should always try booting from the first upgrade slot.
+        if let Some((offset, _, dev_id)) = self.areadesc.find(FlashId::Image1) {
+            assert_eq!(offset, resp.image_off as usize);
+            assert_eq!(dev_id, resp.flash_dev_id);
+        } else {
+            panic!("Unable to find upgrade image");
+        }
+        false
+    }
+
+    /// Test the ram-loading.
+    pub fn run_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);
+
+        // 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));
+        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) {
@@ -1028,18 +1151,18 @@
         let mut counter = stop.unwrap_or(0);
 
         let (first_interrupted, count) = match c::boot_go(&mut flash, &self.areadesc, Some(&mut counter), false) {
-            (-0x13579, _) => (true, stop.unwrap()),
-            (0, _) => (false, -counter),
-            (x, _) => panic!("Unknown return: {}", x),
+            x if x.interrupted() => (true, stop.unwrap()),
+            x if x.success() => (false, -counter),
+            x => panic!("Unknown return: {:?}", x),
         };
 
         counter = 0;
         if first_interrupted {
             // fl.dump();
             match c::boot_go(&mut flash, &self.areadesc, Some(&mut counter), false) {
-                (-0x13579, _) => panic!("Shouldn't stop again"),
-                (0, _) => (),
-                (x, _) => panic!("Unknown return: {}", x),
+                x if x.interrupted() => panic!("Shouldn't stop again"),
+                x if x.success() => (),
+                x => panic!("Unknown return: {:?}", x),
             }
         }
 
@@ -1052,7 +1175,7 @@
         // fl.write_file("image0.bin").unwrap();
         for i in 0 .. count {
             info!("Running boot pass {}", i + 1);
-            assert_eq!(c::boot_go(&mut flash, &self.areadesc, None, false), (0, 0));
+            assert!(c::boot_go(&mut flash, &self.areadesc, None, false).success_no_asserts());
         }
         flash
     }
@@ -1062,8 +1185,7 @@
         let mut fails = 0;
 
         let mut counter = stop;
-        let (x, _) = c::boot_go(&mut flash, &self.areadesc, Some(&mut counter), false);
-        if x != -0x13579 {
+        if !c::boot_go(&mut flash, &self.areadesc, Some(&mut counter), false).interrupted() {
             warn!("Should have stopped test at interruption point");
             fails += 1;
         }
@@ -1075,8 +1197,7 @@
             fails += 1;
         }
 
-        let (x, _) = c::boot_go(&mut flash, &self.areadesc, None, false);
-        if x != 0 {
+        if !c::boot_go(&mut flash, &self.areadesc, None, false).success() {
             warn!("Should have finished test upgrade");
             fails += 1;
         }
@@ -1104,14 +1225,12 @@
 
         // Do Revert
         let mut counter = stop;
-        let (x, _) = c::boot_go(&mut flash, &self.areadesc, Some(&mut counter), false);
-        if x != -0x13579 {
+        if !c::boot_go(&mut flash, &self.areadesc, Some(&mut counter), false).interrupted() {
             warn!("Should have stopped revert at interruption point");
             fails += 1;
         }
 
-        let (x, _) = c::boot_go(&mut flash, &self.areadesc, None, false);
-        if x != 0 {
+        if !c::boot_go(&mut flash, &self.areadesc, None, false).success() {
             warn!("Should have finished revert upgrade");
             fails += 1;
         }
@@ -1138,8 +1257,7 @@
             fails += 1;
         }
 
-        let (x, _) = c::boot_go(&mut flash, &self.areadesc, None, false);
-        if x != 0 {
+        if !c::boot_go(&mut flash, &self.areadesc, None, false).success() {
             warn!("Should have finished 3rd boot");
             fails += 1;
         }
@@ -1166,20 +1284,20 @@
         let mut resets = vec![0i32; count];
         let mut remaining_ops = total_ops;
         for reset in &mut resets {
-            let reset_counter = rng.gen_range(1, remaining_ops / 2);
+            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) {
-                (0, _) | (-0x13579, _) => (),
-                (x, _) => panic!("Unknown return: {}", x),
+                x if x.interrupted() => (),
+                x => panic!("Unknown return: {:?}", x),
             }
             remaining_ops -= reset_counter;
             *reset = reset_counter;
         }
 
         match c::boot_go(&mut flash, &self.areadesc, None, false) {
-            (-0x13579, _) => panic!("Should not be have been interrupted!"),
-            (0, _) => (),
-            (x, _) => panic!("Unknown return: {}", x),
+            x if x.interrupted() => panic!("Should not be have been interrupted!"),
+            x if x.success() => (),
+            x => panic!("Unknown return: {:?}", x),
         }
 
         (flash, resets)
@@ -1266,6 +1384,40 @@
     }
 }
 
+impl RamData {
+    // TODO: This is not correct. The second slot of each image should be at the same address as
+    // the primary.
+    fn new(slots: &[[SlotInfo; 2]]) -> RamData {
+        let mut addr = RAM_LOAD_ADDR;
+        let mut places = BTreeMap::new();
+        // println!("Setup:-------------");
+        for imgs in slots {
+            for si in imgs {
+                // println!("Setup: si: {:?}", si);
+                let offset = addr;
+                let size = si.len as u32;
+                places.insert(SlotKey {
+                    dev_id: si.dev_id,
+                    base_off: si.base_off,
+                }, SlotPlace { offset, size });
+                // println!("  load: offset: {}, size: {}", offset, size);
+            }
+            addr += imgs[0].len as u32;
+        }
+        RamData {
+            places,
+            total: addr,
+        }
+    }
+
+    /// Lookup the ram data associated with a given flash partition.  We just panic if not present,
+    /// because all slots used should be in the map.
+    fn lookup(&self, slot: &SlotInfo) -> &SlotPlace {
+        self.places.get(&SlotKey{dev_id: slot.dev_id, base_off: slot.base_off})
+            .expect("RamData should contain all slots")
+    }
+}
+
 /// Show the flash layout.
 #[allow(dead_code)]
 fn show_flash(flash: &dyn Flash) {
@@ -1280,6 +1432,7 @@
 /// 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,
+                 ram: &RamData,
                  deps: &dyn Depender, bad_sig: bool) -> ImageData {
     let offset = slot.base_off;
     let slot_len = slot.len;
@@ -1294,10 +1447,17 @@
 
     const HDR_SIZE: usize = 32;
 
+    let place = ram.lookup(&slot);
+    let load_addr = if Caps::RamLoad.present() {
+        place.offset
+    } else {
+        0
+    };
+
     // Generate a boot header.  Note that the size doesn't include the header.
     let header = ImageHeader {
         magic: tlv.get_magic(),
-        load_addr: 0,
+        load_addr,
         hdr_size: HDR_SIZE as u16,
         protect_tlv_size: tlv.protect_size(),
         img_size: len as u32,
@@ -1329,17 +1489,27 @@
     tlv.add_bytes(&b_img);
 
     // Generate encrypted images
-    let flag = TlvFlags::ENCRYPTED as u32;
-    let is_encrypted = (tlv.get_flags() & flag) == flag;
+    let flag = TlvFlags::ENCRYPTED_AES128 as u32 | TlvFlags::ENCRYPTED_AES256 as u32;
+    let is_encrypted = (tlv.get_flags() & flag) != 0;
     let mut b_encimg = vec![];
     if is_encrypted {
+        let flag = TlvFlags::ENCRYPTED_AES256 as u32;
+        let aes256 = (tlv.get_flags() & flag) == flag;
         tlv.generate_enc_key();
         let enc_key = tlv.get_enc_key();
-        let key = GenericArray::from_slice(enc_key.as_slice());
         let nonce = GenericArray::from_slice(&[0; 16]);
-        let mut cipher = Aes128Ctr::new(&key, &nonce);
         b_encimg = b_img.clone();
-        cipher.apply_keystream(&mut b_encimg);
+        if aes256 {
+            let key: &GenericArray<u8, U32> = GenericArray::from_slice(enc_key.as_slice());
+            let block = Aes256::new(&key);
+            let mut cipher = Aes256Ctr::from_block_cipher(block, &nonce);
+            cipher.apply_keystream(&mut b_encimg);
+        } else {
+            let key: &GenericArray<u8, U16> = GenericArray::from_slice(enc_key.as_slice());
+            let block = Aes128::new(&key);
+            let mut cipher = Aes128Ctr::from_block_cipher(block, &nonce);
+            cipher.apply_keystream(&mut b_encimg);
+        }
     }
 
     // Build the TLV itself.
@@ -1357,6 +1527,7 @@
 
     // Pad the buffer to a multiple of the flash alignment.
     let align = dev.align();
+    let image_sz = buf.len();
     while buf.len() % align != 0 {
         buf.push(dev.erased_val());
     }
@@ -1399,6 +1570,7 @@
         dev.read(offset, &mut copy).unwrap();
 
         ImageData {
+            size: image_sz,
             plain: copy,
             cipher: enc_copy,
         }
@@ -1425,6 +1597,7 @@
         }
 
         ImageData {
+            size: image_sz,
             plain: copy,
             cipher: enc_copy,
         }
@@ -1434,6 +1607,7 @@
 /// Install no image.  This is used when no upgrade happens.
 fn install_no_image() -> ImageData {
     ImageData {
+        size: 0,
         plain: vec![],
         cipher: None,
     }
@@ -1443,32 +1617,36 @@
     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;
+    }
 
     if Caps::EncKw.present() {
         if Caps::RSA2048.present() {
-            TlvGen::new_rsa_kw()
+            TlvGen::new_rsa_kw(aes_key_size)
         } else if Caps::EcdsaP256.present() {
-            TlvGen::new_ecdsa_kw()
+            TlvGen::new_ecdsa_kw(aes_key_size)
         } else {
-            TlvGen::new_enc_kw()
+            TlvGen::new_enc_kw(aes_key_size)
         }
     } else if Caps::EncRsa.present() {
         if Caps::RSA2048.present() {
-            TlvGen::new_sig_enc_rsa()
+            TlvGen::new_sig_enc_rsa(aes_key_size)
         } else {
-            TlvGen::new_enc_rsa()
+            TlvGen::new_enc_rsa(aes_key_size)
         }
     } else if Caps::EncEc256.present() {
         if Caps::EcdsaP256.present() {
-            TlvGen::new_ecdsa_ecies_p256()
+            TlvGen::new_ecdsa_ecies_p256(aes_key_size)
         } else {
-            TlvGen::new_ecies_p256()
+            TlvGen::new_ecies_p256(aes_key_size)
         }
     } else if Caps::EncX25519.present() {
         if Caps::Ed25519.present() {
-            TlvGen::new_ed25519_ecies_x25519()
+            TlvGen::new_ed25519_ecies_x25519(aes_key_size)
         } else {
-            TlvGen::new_ecies_x25519()
+            TlvGen::new_ecies_x25519(aes_key_size)
         }
     } else {
         // The non-encrypted configuration.
@@ -1499,6 +1677,10 @@
             _ => panic!("Invalid slot requested"),
         }
     }
+
+    fn size(&self) -> usize {
+        self.size
+    }
 }
 
 /// Verify that given image is present in the flash at the given offset.
@@ -1691,6 +1873,7 @@
 const BOOT_FLAG_UNSET: Option<u8> = Some(3);
 
 /// Write out the magic so that the loader tries doing an upgrade.
+#[cfg(not(feature = "swap-status"))]
 pub fn mark_upgrade(flash: &mut SimMultiFlash, slot: &SlotInfo) {
     let dev = flash.get_mut(&slot.dev_id).unwrap();
     let align = dev.align();
@@ -1707,8 +1890,24 @@
     }
 }
 
+/// Write out the magic so that the loader tries doing an upgrade.
+#[cfg(feature = "swap-status")]
+pub fn mark_upgrade(flash: &mut SimMultiFlash, slot: &SlotInfo) {
+    let dev = flash.get_mut(&slot.dev_id).unwrap();
+    let align = dev.align();
+    let offset = slot.trailer_off + c::boot_max_align() * 4;
+    let mask = align - 1;
+    let sector_off = offset & !mask;
+    let mut buf = vec![dev.erased_val(); align];
+    dev.read(sector_off, &mut buf).unwrap();
+    buf[(offset & mask)..].copy_from_slice(MAGIC);
+    dev.erase(sector_off, align).unwrap();
+    dev.write(sector_off, &buf).unwrap();
+}
+
 /// Writes the image_ok flag which, guess what, tells the bootloader
 /// the this image is ok (not a test, and no revert is to be performed).
+#[cfg(not(feature = "swap-status"))]
 fn mark_permanent_upgrade(flash: &mut SimMultiFlash, slot: &SlotInfo) {
     // Overwrite mode always is permanent, and only the magic is used in
     // the trailer.  To avoid problems with large write sizes, don't try to
@@ -1725,9 +1924,32 @@
     dev.write(off, &ok[..align]).unwrap();
 }
 
+/// Writes the image_ok flag which, guess what, tells the bootloader
+/// the this image is ok (not a test, and no revert is to be performed).
+#[cfg(feature = "swap-status")]
+fn mark_permanent_upgrade(flash: &mut SimMultiFlash, slot: &SlotInfo) {
+    // Overwrite mode always is permanent, and only the magic is used in
+    // the trailer.  To avoid problems with large write sizes, don't try to
+    // set anything in this case.
+    if Caps::OverwriteUpgrade.present() {
+        return;
+    }
+    
+    let dev = flash.get_mut(&slot.dev_id).unwrap();
+    let align:usize = dev.align();
+    let mask:usize = align - 1;
+    let ok_off:usize = slot.trailer_off + c::boot_max_align() * 3;
+    let sector_off:usize = ok_off & !mask;
+    let mut buf = vec![dev.erased_val(); align];
+    dev.read(sector_off, &mut buf).unwrap();
+    buf[ok_off & mask] = 1u8;
+    dev.erase(sector_off, align).unwrap();
+    dev.write(sector_off, &buf[..align]).unwrap();
+}
+
 // Drop some pseudo-random gibberish onto the data.
 fn splat(data: &mut [u8], seed: usize) {
-    let mut seed_block = [0u8; 16];
+    let mut seed_block = [0u8; 32];
     let mut buf = Cursor::new(&mut seed_block[..]);
     buf.write_u32::<LittleEndian>(0x135782ea).unwrap();
     buf.write_u32::<LittleEndian>(0x92184728).unwrap();
@@ -1754,11 +1976,18 @@
 }
 
 #[cfg(not(feature = "large-write"))]
+#[cfg(not(feature = "swap-status"))]
 fn test_alignments() -> &'static [usize] {
     &[1, 2, 4, 8]
 }
 
 #[cfg(feature = "large-write")]
+#[cfg(not(feature = "swap-status"))]
 fn test_alignments() -> &'static [usize] {
     &[1, 2, 4, 8, 128, 512]
 }
+
+#[cfg(feature = "swap-status")]
+fn test_alignments() -> &'static [usize] {
+    &[512]
+}
diff --git a/sim/src/lib.rs b/sim/src/lib.rs
index 4203c0e..69f13f1 100644
--- a/sim/src/lib.rs
+++ b/sim/src/lib.rs
@@ -63,8 +63,10 @@
 
 #[derive(Copy, Clone, Debug, Deserialize)]
 pub enum DeviceName {
-    Stm32f4, K64f, K64fBig, K64fMulti, Nrf52840, Nrf52840SpiFlash,
-    Nrf52840UnequalSlots, PSoC6Multi,
+    Stm32f4,
+    K64f, K64fBig, K64fMulti,
+    Nrf52840, Nrf52840SpiFlash, Nrf52840UnequalSlots,
+    PSoC6
 }
 
 pub static ALL_DEVICES: &[DeviceName] = &[
@@ -75,7 +77,7 @@
     DeviceName::Nrf52840,
     DeviceName::Nrf52840SpiFlash,
     DeviceName::Nrf52840UnequalSlots,
-    DeviceName::PSoC6Multi,
+    DeviceName::PSoC6
 ];
 
 impl fmt::Display for DeviceName {
@@ -88,7 +90,7 @@
             DeviceName::Nrf52840 => "nrf52840",
             DeviceName::Nrf52840SpiFlash => "Nrf52840SpiFlash",
             DeviceName::Nrf52840UnequalSlots => "Nrf52840UnequalSlots",
-            DeviceName::PSoC6Multi => "psoc6multi",
+            DeviceName::PSoC6 => "PSoC6"
         };
         f.write_str(name)
     }
diff --git a/sim/src/tlv.rs b/sim/src/tlv.rs
index b6c3c96..6680b4f 100644
--- a/sim/src/tlv.rs
+++ b/sim/src/tlv.rs
@@ -1,5 +1,6 @@
 // Copyright (c) 2017-2020 Linaro LTD
 // Copyright (c) 2017-2020 JUUL Labs
+// Copyright (c) 2021 Arm Limited
 //
 // SPDX-License-Identifier: Apache-2.0
 
@@ -16,6 +17,8 @@
 use byteorder::{
     LittleEndian, WriteBytesExt,
 };
+use cipher::FromBlockCipher;
+use crate::caps::Caps;
 use crate::image::ImageVersion;
 use log::info;
 use ring::{digest, rand, agreement, hkdf, hmac};
@@ -27,15 +30,19 @@
     ECDSA_P256_SHA256_ASN1_SIGNING,
     Ed25519KeyPair,
 };
-use aes_ctr::{
+use aes::{
+    Aes128,
     Aes128Ctr,
-    stream_cipher::{
-        generic_array::GenericArray,
-        NewStreamCipher,
-        SyncStreamCipher,
-    },
+    Aes256,
+    Aes256Ctr,
+    NewBlockCipher
+};
+use cipher::{
+    generic_array::GenericArray,
+    StreamCipher,
 };
 use mcuboot_sys::c;
+use typenum::{U16, U32};
 
 #[repr(u16)]
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
@@ -49,7 +56,7 @@
     RSA3072 = 0x23,
     ED25519 = 0x24,
     ENCRSA2048 = 0x30,
-    ENCKW128 = 0x31,
+    ENCKW = 0x31,
     ENCEC256 = 0x32,
     ENCX25519 = 0x33,
     DEPENDENCY = 0x40,
@@ -59,8 +66,9 @@
 pub enum TlvFlags {
     PIC = 0x01,
     NON_BOOTABLE = 0x02,
-    ENCRYPTED = 0x04,
+    ENCRYPTED_AES128 = 0x04,
     RAM_LOAD = 0x20,
+    ENCRYPTED_AES256 = 0x08,
 }
 
 /// A generator for manifests.  The format of the manifest can be either a
@@ -115,8 +123,6 @@
     version: ImageVersion,
 }
 
-const AES_KEY_LEN: usize = 16;
-
 impl TlvGen {
     /// Construct a new tlv generator that will only contain a hash of the data.
     #[allow(dead_code)]
@@ -160,81 +166,126 @@
     }
 
     #[allow(dead_code)]
-    pub fn new_enc_rsa() -> TlvGen {
+    pub fn new_enc_rsa(aes_key_size: u32) -> TlvGen {
+        let flag = if aes_key_size == 256 {
+            TlvFlags::ENCRYPTED_AES256 as u32
+        } else {
+            TlvFlags::ENCRYPTED_AES128 as u32
+        };
         TlvGen {
-            flags: TlvFlags::ENCRYPTED as u32,
+            flags: flag,
             kinds: vec![TlvKinds::SHA256, TlvKinds::ENCRSA2048],
             ..Default::default()
         }
     }
 
     #[allow(dead_code)]
-    pub fn new_sig_enc_rsa() -> TlvGen {
+    pub fn new_sig_enc_rsa(aes_key_size: u32) -> TlvGen {
+        let flag = if aes_key_size == 256 {
+            TlvFlags::ENCRYPTED_AES256 as u32
+        } else {
+            TlvFlags::ENCRYPTED_AES128 as u32
+        };
         TlvGen {
-            flags: TlvFlags::ENCRYPTED as u32,
+            flags: flag,
             kinds: vec![TlvKinds::SHA256, TlvKinds::RSA2048, TlvKinds::ENCRSA2048],
             ..Default::default()
         }
     }
 
     #[allow(dead_code)]
-    pub fn new_enc_kw() -> TlvGen {
+    pub fn new_enc_kw(aes_key_size: u32) -> TlvGen {
+        let flag = if aes_key_size == 256 {
+            TlvFlags::ENCRYPTED_AES256 as u32
+        } else {
+            TlvFlags::ENCRYPTED_AES128 as u32
+        };
         TlvGen {
-            flags: TlvFlags::ENCRYPTED as u32,
-            kinds: vec![TlvKinds::SHA256, TlvKinds::ENCKW128],
+            flags: flag,
+            kinds: vec![TlvKinds::SHA256, TlvKinds::ENCKW],
             ..Default::default()
         }
     }
 
     #[allow(dead_code)]
-    pub fn new_rsa_kw() -> TlvGen {
+    pub fn new_rsa_kw(aes_key_size: u32) -> TlvGen {
+        let flag = if aes_key_size == 256 {
+            TlvFlags::ENCRYPTED_AES256 as u32
+        } else {
+            TlvFlags::ENCRYPTED_AES128 as u32
+        };
         TlvGen {
-            flags: TlvFlags::ENCRYPTED as u32,
-            kinds: vec![TlvKinds::SHA256, TlvKinds::RSA2048, TlvKinds::ENCKW128],
+            flags: flag,
+            kinds: vec![TlvKinds::SHA256, TlvKinds::RSA2048, TlvKinds::ENCKW],
             ..Default::default()
         }
     }
 
     #[allow(dead_code)]
-    pub fn new_ecdsa_kw() -> TlvGen {
+    pub fn new_ecdsa_kw(aes_key_size: u32) -> TlvGen {
+        let flag = if aes_key_size == 256 {
+            TlvFlags::ENCRYPTED_AES256 as u32
+        } else {
+            TlvFlags::ENCRYPTED_AES128 as u32
+        };
         TlvGen {
-            flags: TlvFlags::ENCRYPTED as u32,
-            kinds: vec![TlvKinds::SHA256, TlvKinds::ECDSA256, TlvKinds::ENCKW128],
+            flags: flag,
+            kinds: vec![TlvKinds::SHA256, TlvKinds::ECDSA256, TlvKinds::ENCKW],
             ..Default::default()
         }
     }
 
     #[allow(dead_code)]
-    pub fn new_ecies_p256() -> TlvGen {
+    pub fn new_ecies_p256(aes_key_size: u32) -> TlvGen {
+        let flag = if aes_key_size == 256 {
+            TlvFlags::ENCRYPTED_AES256 as u32
+        } else {
+            TlvFlags::ENCRYPTED_AES128 as u32
+        };
         TlvGen {
-            flags: TlvFlags::ENCRYPTED as u32,
+            flags: flag,
             kinds: vec![TlvKinds::SHA256, TlvKinds::ENCEC256],
             ..Default::default()
         }
     }
 
     #[allow(dead_code)]
-    pub fn new_ecdsa_ecies_p256() -> TlvGen {
+    pub fn new_ecdsa_ecies_p256(aes_key_size: u32) -> TlvGen {
+        let flag = if aes_key_size == 256 {
+            TlvFlags::ENCRYPTED_AES256 as u32
+        } else {
+            TlvFlags::ENCRYPTED_AES128 as u32
+        };
         TlvGen {
-            flags: TlvFlags::ENCRYPTED as u32,
+            flags: flag,
             kinds: vec![TlvKinds::SHA256, TlvKinds::ECDSA256, TlvKinds::ENCEC256],
             ..Default::default()
         }
     }
 
     #[allow(dead_code)]
-    pub fn new_ecies_x25519() -> TlvGen {
+    pub fn new_ecies_x25519(aes_key_size: u32) -> TlvGen {
+        let flag = if aes_key_size == 256 {
+            TlvFlags::ENCRYPTED_AES256 as u32
+        } else {
+            TlvFlags::ENCRYPTED_AES128 as u32
+        };
         TlvGen {
-            flags: TlvFlags::ENCRYPTED as u32,
+            flags: flag,
             kinds: vec![TlvKinds::SHA256, TlvKinds::ENCX25519],
             ..Default::default()
         }
     }
 
     #[allow(dead_code)]
-    pub fn new_ed25519_ecies_x25519() -> TlvGen {
+    pub fn new_ed25519_ecies_x25519(aes_key_size: u32) -> TlvGen {
+        let flag = if aes_key_size == 256 {
+            TlvFlags::ENCRYPTED_AES256 as u32
+        } else {
+            TlvFlags::ENCRYPTED_AES128 as u32
+        };
         TlvGen {
-            flags: TlvFlags::ENCRYPTED as u32,
+            flags: flag,
             kinds: vec![TlvKinds::SHA256, TlvKinds::ED25519, TlvKinds::ENCX25519],
             ..Default::default()
         }
@@ -248,7 +299,12 @@
 
     /// Retrieve the header flags for this configuration.  This can be called at any time.
     fn get_flags(&self) -> u32 {
-        self.flags
+        // For the RamLoad case, add in the flag for this feature.
+        if Caps::RamLoad.present() {
+            self.flags | (TlvFlags::RAM_LOAD as u32)
+        } else {
+            self.flags
+        }
     }
 
     /// Add bytes to the covered hash.
@@ -479,20 +535,28 @@
             result.extend_from_slice(&encbuf);
         }
 
-        if self.kinds.contains(&TlvKinds::ENCKW128) {
-            let key_bytes = base64::decode(
-                include_str!("../../enc-aes128kw.b64").trim()).unwrap();
-
+        if self.kinds.contains(&TlvKinds::ENCKW) {
+            let flag = TlvFlags::ENCRYPTED_AES256 as u32;
+            let aes256 = (self.get_flags() & flag) == flag;
+            let key_bytes = if aes256 {
+                base64::decode(
+                    include_str!("../../enc-aes256kw.b64").trim()).unwrap()
+            } else {
+                base64::decode(
+                    include_str!("../../enc-aes128kw.b64").trim()).unwrap()
+            };
             let cipherkey = self.get_enc_key();
             let cipherkey = cipherkey.as_slice();
-            let encbuf = match c::kw_encrypt(&key_bytes, cipherkey) {
+            let keylen = if aes256 { 32 } else { 16 };
+            let encbuf = match c::kw_encrypt(&key_bytes, cipherkey, keylen) {
                 Ok(v) => v,
                 Err(_) => panic!("Failed to encrypt secret key"),
             };
 
-            assert!(encbuf.len() == 24);
-            result.write_u16::<LittleEndian>(TlvKinds::ENCKW128 as u16).unwrap();
-            result.write_u16::<LittleEndian>(24).unwrap();
+            let size = if aes256 { 40 } else { 24 };
+            assert!(encbuf.len() == size);
+            result.write_u16::<LittleEndian>(TlvKinds::ENCKW as u16).unwrap();
+            result.write_u16::<LittleEndian>(size as u16).unwrap();
             result.extend_from_slice(&encbuf);
         }
 
@@ -503,7 +567,6 @@
                 pem::parse(include_bytes!("../../enc-x25519-pub.pem").as_ref()).unwrap()
             };
             assert_eq!(key_bytes.tag, "PUBLIC KEY");
-
             let rng = rand::SystemRandom::new();
             let alg = if self.kinds.contains(&TlvKinds::ENCEC256) {
                 &agreement::ECDH_P256
@@ -535,15 +598,19 @@
                 }
             }
 
+            let flag = TlvFlags::ENCRYPTED_AES256 as u32;
+            let aes256 = (self.get_flags() & flag) == flag;
+
             let derived_key = match agreement::agree_ephemeral(
                 pk, &peer_pubk, ring::error::Unspecified, |shared| {
                     let salt = hkdf::Salt::new(hkdf::HKDF_SHA256, &[]);
                     let prk = salt.extract(&shared);
-                    let okm = match prk.expand(&[b"MCUBoot_ECIES_v1"], OkmLen(48)) {
+                    let okm_len = if aes256 { 64 } else { 48 };
+                    let okm = match prk.expand(&[b"MCUBoot_ECIES_v1"], OkmLen(okm_len)) {
                         Ok(okm) => okm,
                         Err(_) => panic!("Failed building HKDF OKM"),
                     };
-                    let mut buf = [0u8; 48];
+                    let mut buf = if aes256 { vec![0u8; 64] } else { vec![0u8; 48] };
                     match okm.fill(&mut buf) {
                         Ok(_) => Ok(buf),
                         Err(_) => panic!("Failed generating HKDF output"),
@@ -554,13 +621,22 @@
                 Err(_) => panic!("Failed building HKDF"),
             };
 
-            let key = GenericArray::from_slice(&derived_key[..16]);
             let nonce = GenericArray::from_slice(&[0; 16]);
-            let mut cipher = Aes128Ctr::new(&key, &nonce);
             let mut cipherkey = self.get_enc_key();
-            cipher.apply_keystream(&mut cipherkey);
+            if aes256 {
+                let key: &GenericArray<u8, U32> = GenericArray::from_slice(&derived_key[..32]);
+                let block = Aes256::new(&key);
+                let mut cipher = Aes256Ctr::from_block_cipher(block, &nonce);
+                cipher.apply_keystream(&mut cipherkey);
+            } else {
+                let key: &GenericArray<u8, U16> = GenericArray::from_slice(&derived_key[..16]);
+                let block = Aes128::new(&key);
+                let mut cipher = Aes128Ctr::from_block_cipher(block, &nonce);
+                cipher.apply_keystream(&mut cipherkey);
+            }
 
-            let key = hmac::Key::new(hmac::HMAC_SHA256, &derived_key[16..]);
+            let size = if aes256 { 32 } else { 16 };
+            let key = hmac::Key::new(hmac::HMAC_SHA256, &derived_key[size..]);
             let tag = hmac::sign(&key, &cipherkey);
 
             let mut buf = vec![];
@@ -569,13 +645,15 @@
             buf.append(&mut cipherkey);
 
             if self.kinds.contains(&TlvKinds::ENCEC256) {
-                assert!(buf.len() == 113);
+                let size = if aes256 { 129 } else { 113 };
+                assert!(buf.len() == size);
                 result.write_u16::<LittleEndian>(TlvKinds::ENCEC256 as u16).unwrap();
-                result.write_u16::<LittleEndian>(113).unwrap();
+                result.write_u16::<LittleEndian>(size as u16).unwrap();
             } else {
-                assert!(buf.len() == 80);
+                let size = if aes256 { 96 } else { 80 };
+                assert!(buf.len() == size);
                 result.write_u16::<LittleEndian>(TlvKinds::ENCX25519 as u16).unwrap();
-                result.write_u16::<LittleEndian>(80).unwrap();
+                result.write_u16::<LittleEndian>(size as u16).unwrap();
             }
             result.extend_from_slice(&buf);
         }
@@ -590,7 +668,13 @@
 
     fn generate_enc_key(&mut self) {
         let rng = rand::SystemRandom::new();
-        let mut buf = vec![0u8; AES_KEY_LEN];
+        let flag = TlvFlags::ENCRYPTED_AES256 as u32;
+        let aes256 = (self.get_flags() & flag) == flag;
+        let mut buf = if aes256 {
+            vec![0u8; 32]
+        } else {
+            vec![0u8; 16]
+        };
         if rng.fill(&mut buf).is_err() {
             panic!("Error generating encrypted key");
         }
@@ -599,7 +683,7 @@
     }
 
     fn get_enc_key(&self) -> Vec<u8> {
-        if self.enc_key.len() != AES_KEY_LEN {
+        if self.enc_key.len() != 32 && self.enc_key.len() != 16 {
             panic!("No random key was generated");
         }
         self.enc_key.clone()
diff --git a/sim/tests/core.rs b/sim/tests/core.rs
index 4e2d9c1..995c372 100644
--- a/sim/tests/core.rs
+++ b/sim/tests/core.rs
@@ -22,9 +22,11 @@
 
 /// A single test, after setting up logging and such.  Within the $body,
 /// $arg will be bound to each device.
+/// The "$skip_feature" allows to set a feature for which this test will be skipped.
 macro_rules! test_shell {
-    ($name:ident, $arg: ident, $body:expr) => {
+    ($name:ident, $arg:ident, $body:expr, $skip_feature:expr) => {
         #[test]
+        #[cfg_attr(feature = $skip_feature, ignore)]
         fn $name() {
             testlog::setup();
             ImagesBuilder::each_device(|$arg| {
@@ -36,28 +38,34 @@
 
 /// A typical test calls a particular constructor, and runs a given test on
 /// that constructor.
+/// The "$skip_feature" allows to set a feature for which this test will be skipped.
 macro_rules! sim_test {
-    ($name:ident, $maker:ident($($margs:expr),*), $test:ident($($targs:expr),*)) => {
+    ($name:ident, $maker:ident($($margs:expr),*), $test:ident($($targs:expr),*), $skip_feature:expr) => {
         test_shell!($name, r, {
             let image = r.$maker($($margs),*);
             dump_image(&image, stringify!($name));
             assert!(!image.$test($($targs),*));
-        });
+        }, $skip_feature);
     };
 }
 
-sim_test!(bad_secondary_slot, make_bad_secondary_slot_image(), run_signfail_upgrade());
-sim_test!(secondary_trailer_leftover, make_erased_secondary_image(), run_secondary_leftover_trailer());
-sim_test!(bootstrap, make_bootstrap_image(), run_bootstrap());
-sim_test!(norevert_newimage, make_no_upgrade_image(&NO_DEPS), run_norevert_newimage());
-sim_test!(basic_revert, make_image(&NO_DEPS, true), run_basic_revert());
-sim_test!(revert_with_fails, make_image(&NO_DEPS, false), run_revert_with_fails());
-sim_test!(perm_with_fails, make_image(&NO_DEPS, true), run_perm_with_fails());
-sim_test!(perm_with_random_fails, make_image(&NO_DEPS, true), run_perm_with_random_fails(5));
-sim_test!(norevert, make_image(&NO_DEPS, true), run_norevert());
-sim_test!(status_write_fails_complete, make_image(&NO_DEPS, true), run_with_status_fails_complete());
-sim_test!(status_write_fails_with_reset, make_image(&NO_DEPS, true), run_with_status_fails_with_reset());
-sim_test!(downgrade_prevention, make_image(&REV_DEPS, true), run_nodowngrade());
+sim_test!(bad_secondary_slot, make_bad_secondary_slot_image(), run_signfail_upgrade(), "");
+sim_test!(secondary_trailer_leftover, make_erased_secondary_image(), run_secondary_leftover_trailer(), "");
+sim_test!(bootstrap, make_bootstrap_image(), run_bootstrap(), "");
+sim_test!(norevert_newimage, make_no_upgrade_image(&NO_DEPS), run_norevert_newimage(), "");
+sim_test!(basic_revert, make_image(&NO_DEPS, true), run_basic_revert(), "");
+sim_test!(revert_with_fails, make_image(&NO_DEPS, false), run_revert_with_fails(), "");
+sim_test!(perm_with_fails, make_image(&NO_DEPS, true), run_perm_with_fails(), "");
+sim_test!(perm_with_random_fails, make_image(&NO_DEPS, true), run_perm_with_random_fails(5), "");
+sim_test!(norevert, make_image(&NO_DEPS, true), run_norevert(), "");
+sim_test!(status_write_fails_complete, make_image(&NO_DEPS, true), run_with_status_fails_complete(), "");
+
+sim_test!(status_write_fails_with_reset, make_image(&NO_DEPS, true),
+          run_with_status_fails_with_reset(), "swap-status");
+sim_test!(downgrade_prevention, make_image(&REV_DEPS, true), run_nodowngrade(), "");
+
+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(), "");
 
 // Test various combinations of incorrect dependencies.
 test_shell!(dependency_combos, r, {
@@ -71,7 +79,7 @@
         dump_image(&image, "dependency_combos");
         assert!(!image.run_check_deps(&dep));
     }
-});
+}, "");
 
 /// These are the variants of dependencies we will test.
 pub static TEST_DEPS: &[DepTest] = &[