Merge pull request #48 from d3zd3z/pr/overwrite

Add overwrite-only upgrade
diff --git a/Makefile b/Makefile
index a0c7587..eedae1f 100644
--- a/Makefile
+++ b/Makefile
@@ -21,6 +21,10 @@
 # verification only happens on upgrade.
 CFLAGS += -DBOOTUTIL_VALIDATE_SLOT0
 
+# Enable this option to not use the swapping code and just overwrite
+# the image on upgrade.
+#CFLAGS += -DBOOTUTIL_OVERWRITE_ONLY
+
 ##############################
 # End of configuration blocks.
 ##############################
diff --git a/boot/bootutil/include/bootutil/caps.h b/boot/bootutil/include/bootutil/caps.h
new file mode 100644
index 0000000..a0c324a
--- /dev/null
+++ b/boot/bootutil/include/bootutil/caps.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2017 Linaro Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef H_BOOTUTIL_CAPS_H_
+#define H_BOOTUTIL_CAPS_H_
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * The bootloader can be compile with different capabilities selected
+ * at compile time.  This function provides runtime access to these
+ * capabilities.  This is intended primarily for testing, although
+ * these will possibly be available at runtime to the application
+ * running within the bootloader.
+ */
+uint32_t bootutil_get_caps(void);
+
+#define BOOTUTIL_CAP_RSA2048            (1<<0)
+#define BOOTUTIL_CAP_ECDSA_P224         (1<<1)
+#define BOOTUTIL_CAP_ECDSA_P256         (1<<2)
+#define BOOTUTIL_CAP_SWAP_UPGRADE       (1<<3)
+#define BOOTUTIL_CAP_OVERWRITE_UPGRADE  (1<<4)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/boot/bootutil/src/Makefile b/boot/bootutil/src/Makefile
index 8a69d87..cd38b0f 100644
--- a/boot/bootutil/src/Makefile
+++ b/boot/bootutil/src/Makefile
@@ -3,3 +3,4 @@
 include $(ZEPHYR_BASE)/ext/lib/crypto/mbedtls/Makefile.include
 
 obj-y += loader.o bootutil_misc.o image_validate.o image_rsa.o image_ec256.o
+obj-y += caps.o
diff --git a/boot/bootutil/src/caps.c b/boot/bootutil/src/caps.c
new file mode 100644
index 0000000..ae67939
--- /dev/null
+++ b/boot/bootutil/src/caps.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2017 Linaro Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <bootutil/caps.h>
+
+uint32_t bootutil_get_caps(void)
+{
+        uint32_t res = 0;
+
+#ifdef BOOTUTIL_SIGN_RSA
+        res |= BOOTUTIL_CAP_RSA2048;
+#endif
+#ifdef BOOTUTIL_SIGN_EC
+        res |= BOOTUTIL_CAP_ECDSA_P224;
+#endif
+#ifdef BOOTUTIL_SIGN_EC256
+        res |= BOOTUTIL_CAP_ECDSA_P256;
+#endif
+#ifdef BOOTUTIL_OVERWRITE_ONLY
+        res |= BOOTUTIL_CAP_OVERWRITE_UPGRADE;
+#else
+        res |= BOOTUTIL_CAP_SWAP_UPGRADE;
+#endif
+
+        return res;
+}
diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c
index 89b4e13..e0867d6 100644
--- a/boot/bootutil/src/loader.c
+++ b/boot/bootutil/src/loader.c
@@ -644,6 +644,7 @@
  * @return                      The number of bytes comprised by the
  *                                  [first-sector, last-sector] range.
  */
+#ifndef BOOTUTIL_OVERWRITE_ONLY
 static uint32_t
 boot_copy_sz(int last_sector_idx, int *out_first_sector_idx)
 {
@@ -667,6 +668,7 @@
     *out_first_sector_idx = i + 1;
     return sz;
 }
+#endif /* not BOOTUTIL_OVERWRITE_ONLY */
 
 /**
  * Erases a region of flash.
@@ -787,6 +789,7 @@
  *
  * @return                      0 on success; nonzero on failure.
  */
+#ifndef BOOTUTIL_OVERWRITE_ONLY
 static void
 boot_swap_sectors(int idx, uint32_t sz, struct boot_status *bs)
 {
@@ -846,6 +849,7 @@
         assert(rc == 0);
     }
 }
+#endif /* not BOOTUTIL_OVERWRITE_ONLY */
 
 /**
  * Swaps the two images in flash.  If a prior copy operation was interrupted
@@ -859,6 +863,44 @@
  *
  * @return                      0 on success; nonzero on failure.
  */
+#ifdef BOOTUTIL_OVERWRITE_ONLY
+static int
+boot_copy_image(struct boot_status *bs)
+{
+    int sect_count;
+    int sect;
+    int rc;
+    uint32_t size = 0;
+    uint32_t this_size;
+
+    BOOT_LOG_INF("Image upgrade slot1 -> slot0");
+    BOOT_LOG_INF("Erasing slot0");
+
+    sect_count = boot_data.imgs[0].num_sectors;
+    for (sect = 0; sect < sect_count; sect++) {
+        this_size = boot_data.imgs[0].sectors[sect].fa_size;
+        rc = boot_erase_sector(FLASH_AREA_IMAGE_0,
+                               size,
+                               this_size);
+        assert(rc == 0);
+
+        size += this_size;
+    }
+
+    BOOT_LOG_INF("Copying slot 1 to slot 0: 0x%x bytes",
+                 size);
+    rc = boot_copy_sector(FLASH_AREA_IMAGE_1, FLASH_AREA_IMAGE_0,
+                          0, 0, size);
+
+    /* Erase slot 1 so that we don't do the upgrade on every boot.
+     * TODO: Perhaps verify slot 0's signature again? */
+    rc = boot_erase_sector(FLASH_AREA_IMAGE_1,
+                           0, boot_data.imgs[1].sectors[0].fa_size);
+    assert(rc == 0);
+
+    return 0;
+}
+#else
 static int
 boot_copy_image(struct boot_status *bs)
 {
@@ -881,6 +923,7 @@
 
     return 0;
 }
+#endif
 
 /**
  * Marks a test image in slot 0 as fully copied.
diff --git a/sim/build.rs b/sim/build.rs
index 2fd997e..1932b8e 100644
--- a/sim/build.rs
+++ b/sim/build.rs
@@ -10,6 +10,7 @@
     let mut conf = gcc::Config::new();
 
     conf.file("../boot/bootutil/src/loader.c");
+    conf.file("../boot/bootutil/src/caps.c");
     conf.file("../boot/bootutil/src/bootutil_misc.c");
     conf.file("csupport/run.c");
     conf.include("../boot/bootutil/include");
@@ -17,6 +18,7 @@
     conf.debug(true);
     conf.flag("-Wall");
     conf.define("__BOOTSIM__", None);
+    // conf.define("BOOTUTIL_OVERWRITE_ONLY", None);
     conf.compile("libbootutil.a");
     walk_dir("../boot").unwrap();
     walk_dir("csupport").unwrap();
diff --git a/sim/src/caps.rs b/sim/src/caps.rs
new file mode 100644
index 0000000..77be9de
--- /dev/null
+++ b/sim/src/caps.rs
@@ -0,0 +1,23 @@
+// Query the bootloader's capabilities.
+
+#[repr(u32)]
+#[derive(Copy, Clone, Eq, PartialEq)]
+#[allow(unused)]
+pub enum Caps {
+    RSA2048          = (1 << 0),
+    EcdsaP224        = (1 << 1),
+    EcdsaP256        = (1 << 2),
+    SwapUpgrade      = (1 << 3),
+    OverwriteUpgrade = (1 << 4),
+}
+
+impl Caps {
+    pub fn present(self) -> bool {
+        let caps = unsafe { bootutil_get_caps() };
+        (caps as u32) & (self as u32) != 0
+    }
+}
+
+extern "C" {
+    fn bootutil_get_caps() -> Caps;
+}
diff --git a/sim/src/main.rs b/sim/src/main.rs
index 0ceb441..d970ef2 100644
--- a/sim/src/main.rs
+++ b/sim/src/main.rs
@@ -22,9 +22,11 @@
 mod flash;
 pub mod api;
 mod pdump;
+mod caps;
 
 use flash::Flash;
 use area::{AreaDesc, FlashId};
+use caps::Caps;
 
 const USAGE: &'static str = "
 Mcuboot simulator
@@ -243,9 +245,11 @@
                 warn!("FAIL at step {} of {}", i, total_count);
                 bad += 1;
             }
-            if !verify_image(&fl3, slot1_base, &primary) {
-                warn!("Slot 1 FAIL at step {} of {}", i, total_count);
-                bad += 1;
+            if Caps::SwapUpgrade.present() {
+                if !verify_image(&fl3, slot1_base, &primary) {
+                    warn!("Slot 1 FAIL at step {} of {}", i, total_count);
+                    bad += 1;
+                }
             }
         }
         error!("{} out of {} failed {:.2}%",
@@ -256,23 +260,29 @@
         }
 
         let (fl4, total_counts) = try_random_fails(&flash, &areadesc, total_count, 5);
-        info!("Random fails at reset points={:?}", total_counts);
+        info!("Random interruptions at reset points={:?}", total_counts);
         let slot0_ok = verify_image(&fl4, slot0_base, &upgrade);
-        let slot1_ok = verify_image(&fl4, slot1_base, &primary);
-        if !slot0_ok || !slot1_ok {
-            error!("Image mismatch after random fails: slot0={} slot1={}",
+        let slot1_ok = if Caps::SwapUpgrade.present() {
+            verify_image(&fl4, slot1_base, &primary)
+        } else {
+            true
+        };
+        if !slot0_ok /* || !slot1_ok */ {
+            error!("Image mismatch after random interrupts: slot0={} slot1={}",
                    if slot0_ok { "ok" } else { "fail" },
                    if slot1_ok { "ok" } else { "fail" });
             self.failures += 1;
             return;
         }
 
-        for count in 2 .. 5 {
-            info!("Try revert: {}", count);
-            let fl2 = try_revert(&flash, &areadesc, count);
-            if !verify_image(&fl2, slot0_base, &primary) {
-                warn!("Revert failure on count {}", count);
-                failed = true;
+        if Caps::SwapUpgrade.present() {
+            for count in 2 .. 5 {
+                info!("Try revert: {}", count);
+                let fl2 = try_revert(&flash, &areadesc, count);
+                if !verify_image(&fl2, slot0_base, &primary) {
+                    warn!("Revert failure on count {}", count);
+                    failed = true;
+                }
             }
         }