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;
+ }
}
}