Merge pull request #13 from d3zd3z/doc

Update documentation for Zephyr
diff --git a/Makefile b/Makefile
index 525e91e..1c726bb 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,35 @@
-BOARD ?= qemu_x86
+# Makefile for building mcuboot as a Zephyr project.
+
+# Configuration choices.
+
+#####################
+# Signature algorithm
+#####################
+# Choose one of RSA or ECDSA P-256 blocks, and uncomment the config
+# lines there, and comment out any other blocks.
+
+# RSA
 CONF_FILE = boot/zephyr/prj.conf
+CFLAGS += -DBOOTUTIL_SIGN_RSA
+
+# ECDSA P-256
+#CONF_FILE = boot/zephyr/prj-p256.conf
+#CFLAGS += -DBOOTUTIL_SIGN_EC256
+
+# Enable this option to have the bootloader verify the signature of
+# the primary image upon every boot.  Without it, signature
+# verification only happens on upgrade.
+CFLAGS += -DBOOTUTIL_VALIDATE_SLOT0
+
+##############################
+# End of configuration blocks.
+##############################
+
+# The board should be set to one of the targets supported by
+# mcuboot/Zephyr.  These can be found in ``boot/zephyr/targets``
+BOARD ?= qemu_x86
+
+# The source to the Zephyr-specific code lives here.
 SOURCE_DIR = boot/zephyr
 
 # Needed for mbedtls config-boot.h file.
diff --git a/README.md b/README.md
index 031eb59..825174f 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,44 @@
 # mcuboot
-MCU boot loader
+
+## Overview
+
+MCUBoot is a secure bootloader for 32-bit MCUs.   The goal of MCUBoot is to 
+define a common infrastructure for the bootloader, system flash layout on 
+microcontroller systems, and to provide a secure bootloader that enables 
+easy software upgrade.
+
+MCUboot is operating system and hardware independent, and relies on 
+hardware porting layers from the operating system it works with.  Currently
+mcuboot works with both the Apache Mynewt, and Zephyr operating systems, but
+more ports are planned in the future.
+
+## Roadmap
+
+The MCUBoot project was originally taken from the Apache Mynewt operating system,
+which had secure boot and software upgrade functionality instrinsic to it.  Currently
+development is heads down on a first release of MCUboot that works across both the 
+Zephyr operating system and Apache Mynewt operating system.
+
+For more information on what's being planned, and worked on, please visit: 
+
+https://runtimeco.atlassian.net/projects/MCUB/summary
+
+## Browsing 
+
+Information and documentation on the bootloader is stored within the source, and on confluence:
+
+https://runtimeco.atlassian.net/wiki/discover/all-updates
+
+For more information in the source, here are some pointers: 
+
+- [boot/bootutil](https://github.com/runtimeco/mcuboot/tree/master/boot/bootutil): The core of the bootloader itself.
+- [boot/boot\_serial](https://github.com/runtimeco/mcuboot/tree/master/boot/boot_serial): Support for serial upgrade within the bootloader itself.
+- [boot/zephyr](https://github.com/runtimeco/mcuboot/tree/master/boot/zephyr): Port of the bootloader to Zephyr
+- [imgtool](https://github.com/runtimeco/mcuboot/tree/master/imgtool): A tool to securely sign firmware images for booting by mcuboot.
+- [sim](https://github.com/runtimeco/mcuboot/tree/master/sim): A bootloader simulator for testing and regression
+
+## Joining 
+
+Developers welcome!  To join in the discussion, please join the developer mailing list: 
+
+https://runtimeco.mobilize.io/registrations/groups/9881
diff --git a/apps/boot/README.md b/apps/boot/README.md
new file mode 100644
index 0000000..ef924d5
--- /dev/null
+++ b/apps/boot/README.md
@@ -0,0 +1,6 @@
+# mcuboot - apps/boot
+
+This sample app implements a boot loader for the Mynewt OS (apache.mynewt.org).
+This app requires the following Mynewt repositories:
+    * @mcuboot (this one)
+    * @apache-mynewt-core
diff --git a/apps/boot/pkg.yml b/apps/boot/pkg.yml
new file mode 100644
index 0000000..c3af3e8
--- /dev/null
+++ b/apps/boot/pkg.yml
@@ -0,0 +1,35 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+#
+
+pkg.name: apps/boot
+pkg.type: app
+pkg.description: Boot loader application.
+pkg.author: "Apache Mynewt <dev@mynewt.incubator.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+    - loader
+
+pkg.deps:
+    - "@mcuboot/boot/bootutil"
+    - "@apache-mynewt-core/kernel/os"
+    - "@apache-mynewt-core/sys/console/stub"
+
+pkg.deps.BOOT_SERIAL.OVERWRITE:
+    - "@apache-mynewt-core/sys/console/full"
+    - "@mcuboot/boot/boot_serial"
diff --git a/apps/boot/src/boot.c b/apps/boot/src/boot.c
new file mode 100755
index 0000000..fbc4b7d
--- /dev/null
+++ b/apps/boot/src/boot.c
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 <assert.h>
+#include <stddef.h>
+#include <inttypes.h>
+#include "syscfg/syscfg.h"
+#include <flash_map/flash_map.h>
+#include <os/os.h>
+#include <bsp/bsp.h>
+#include <hal/hal_bsp.h>
+#include <hal/hal_system.h>
+#include <hal/hal_flash.h>
+#if MYNEWT_VAL(BOOT_SERIAL)
+#include <hal/hal_gpio.h>
+#include <boot_serial/boot_serial.h>
+#include <sysinit/sysinit.h>
+#endif
+#include <console/console.h>
+#include "bootutil/image.h"
+#include "bootutil/bootutil.h"
+
+#define BOOT_AREA_DESC_MAX  (256)
+#define AREA_DESC_MAX       (BOOT_AREA_DESC_MAX)
+
+#if MYNEWT_VAL(BOOT_SERIAL)
+#define BOOT_SER_CONS_INPUT         128
+#endif
+
+int
+main(void)
+{
+    struct boot_rsp rsp;
+    int rc;
+
+#if MYNEWT_VAL(BOOT_SERIAL)
+    sysinit();
+#else
+    flash_map_init();
+    hal_bsp_init();
+#endif
+
+#if MYNEWT_VAL(BOOT_SERIAL)
+    /*
+     * Configure a GPIO as input, and compare it against expected value.
+     * If it matches, await for download commands from serial.
+     */
+    hal_gpio_init_in(BOOT_SERIAL_DETECT_PIN, BOOT_SERIAL_DETECT_PIN_CFG);
+    if (hal_gpio_read(BOOT_SERIAL_DETECT_PIN) == BOOT_SERIAL_DETECT_PIN_VAL) {
+        boot_serial_start(BOOT_SER_CONS_INPUT);
+        assert(0);
+    }
+#endif
+    rc = boot_go(&rsp);
+    assert(rc == 0);
+
+    hal_system_start((void *)(rsp.br_image_addr + rsp.br_hdr->ih_hdr_size));
+
+    return 0;
+}
diff --git a/apps/boot/syscfg.yml b/apps/boot/syscfg.yml
new file mode 100644
index 0000000..215dc5d
--- /dev/null
+++ b/apps/boot/syscfg.yml
@@ -0,0 +1,32 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+#
+
+# Package: apps/boot
+
+syscfg.defs:
+    BOOT_LOADER:
+        description: 'TBD'
+        value: 1
+    BOOT_SERIAL:
+        description: 'TBD'
+        value: 0
+
+syscfg.vals:
+    SYSINIT_CONSTRAIN_INIT: 0
+    OS_SCHEDULING: 0
+    OS_CPUTIME_TIMER_NUM: -1
diff --git a/boot/bootutil/include/bootutil/bootutil_log.h b/boot/bootutil/include/bootutil/bootutil_log.h
new file mode 100644
index 0000000..6dca9b3
--- /dev/null
+++ b/boot/bootutil/include/bootutil/bootutil_log.h
@@ -0,0 +1,86 @@
+/*
+ * 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_LOG_H_
+#define H_BOOTUTIL_LOG_H_
+
+#include "ignore.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * When building for targets running Zephyr, delegate to its native
+ * logging subsystem.
+ *
+ * In this case:
+ *
+ * - BOOT_LOG_LEVEL determines SYS_LOG_LEVEL,
+ * - BOOT_LOG_ERR() and friends are SYS_LOG_ERR() etc.
+ * - SYS_LOG_DOMAIN is unconditionally set to "MCUBOOT"
+ */
+#ifdef __ZEPHYR__
+
+#define BOOT_LOG_LEVEL_OFF	SYS_LOG_LEVEL_OFF
+#define BOOT_LOG_LEVEL_ERROR	SYS_LOG_LEVEL_ERROR
+#define BOOT_LOG_LEVEL_WARNING	SYS_LOG_LEVEL_WARNING
+#define BOOT_LOG_LEVEL_INFO	SYS_LOG_LEVEL_INFO
+#define BOOT_LOG_LEVEL_DEBUG	SYS_LOG_LEVEL_DEBUG
+
+/* Treat BOOT_LOG_LEVEL equivalently to SYS_LOG_LEVEL. */
+#ifndef BOOT_LOG_LEVEL
+#define BOOT_LOG_LEVEL CONFIG_SYS_LOG_DEFAULT_LEVEL
+#elif (BOOT_LOG_LEVEL < CONFIG_SYS_LOG_OVERRIDE_LEVEL)
+#undef BOOT_LOG_LEVEL
+#define BOOT_LOG_LEVEL CONFIG_SYS_LOG_OVERRIDE_LEVEL
+#endif
+
+#define SYS_LOG_LEVEL BOOT_LOG_LEVEL
+
+#undef SYS_LOG_DOMAIN
+#define SYS_LOG_DOMAIN "MCUBOOT"
+
+#define BOOT_LOG_ERR(...) SYS_LOG_ERR(__VA_ARGS__)
+#define BOOT_LOG_WRN(...) SYS_LOG_WRN(__VA_ARGS__)
+#define BOOT_LOG_INF(...) SYS_LOG_INF(__VA_ARGS__)
+#define BOOT_LOG_DBG(...) SYS_LOG_DBG(__VA_ARGS__)
+
+#include <logging/sys_log.h>
+
+/*
+ * In other environments, logging calls are no-ops.
+ */
+#else  /* !defined(__ZEPHYR__) */
+
+#define BOOT_LOG_LEVEL_OFF	0
+#define BOOT_LOG_LEVEL_ERROR	1
+#define BOOT_LOG_LEVEL_WARNING	2
+#define BOOT_LOG_LEVEL_INFO	3
+#define BOOT_LOG_LEVEL_DEBUG	4
+
+#define BOOT_LOG_ERR(...) IGNORE(__VA_ARGS__)
+#define BOOT_LOG_WRN(...) IGNORE(__VA_ARGS__)
+#define BOOT_LOG_INF(...) IGNORE(__VA_ARGS__)
+#define BOOT_LOG_DBG(...) IGNORE(__VA_ARGS__)
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/boot/bootutil/include/bootutil/ignore.h b/boot/bootutil/include/bootutil/ignore.h
new file mode 100644
index 0000000..46282a0
--- /dev/null
+++ b/boot/bootutil/include/bootutil/ignore.h
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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_IGNORE_
+#define H_IGNORE_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * These macros prevent the "set but not used" warnings for log writes below
+ * the log level.
+ */
+
+#define IGN_1(X) ((void)(X))
+#define IGN_2(X, ...) ((void)(X));IGN_1(__VA_ARGS__)
+#define IGN_3(X, ...) ((void)(X));IGN_2(__VA_ARGS__)
+#define IGN_4(X, ...) ((void)(X));IGN_3(__VA_ARGS__)
+#define IGN_5(X, ...) ((void)(X));IGN_4(__VA_ARGS__)
+#define IGN_6(X, ...) ((void)(X));IGN_5(__VA_ARGS__)
+#define IGN_7(X, ...) ((void)(X));IGN_6(__VA_ARGS__)
+#define IGN_8(X, ...) ((void)(X));IGN_7(__VA_ARGS__)
+#define IGN_9(X, ...) ((void)(X));IGN_8(__VA_ARGS__)
+#define IGN_10(X, ...) ((void)(X));IGN_9(__VA_ARGS__)
+#define IGN_11(X, ...) ((void)(X));IGN_10(__VA_ARGS__)
+#define IGN_12(X, ...) ((void)(X));IGN_11(__VA_ARGS__)
+#define IGN_13(X, ...) ((void)(X));IGN_12(__VA_ARGS__)
+#define IGN_14(X, ...) ((void)(X));IGN_13(__VA_ARGS__)
+#define IGN_15(X, ...) ((void)(X));IGN_14(__VA_ARGS__)
+#define IGN_16(X, ...) ((void)(X));IGN_15(__VA_ARGS__)
+#define IGN_17(X, ...) ((void)(X));IGN_16(__VA_ARGS__)
+#define IGN_18(X, ...) ((void)(X));IGN_17(__VA_ARGS__)
+#define IGN_19(X, ...) ((void)(X));IGN_18(__VA_ARGS__)
+#define IGN_20(X, ...) ((void)(X));IGN_19(__VA_ARGS__)
+
+#define GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, \
+                  _13, _14, _15, _16, _17, _18, _19, _20, NAME, ...) NAME
+#define IGNORE(...) \
+    GET_MACRO(__VA_ARGS__, IGN_20, IGN_19, IGN_18, IGN_17, IGN_16, IGN_15, \
+              IGN_14, IGN_13, IGN_12, IGN_11, IGN_10, IGN_9, IGN_8, IGN_7, \
+              IGN_6, IGN_5, IGN_4, IGN_3, IGN_2, IGN_1)(__VA_ARGS__)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/boot/bootutil/src/Makefile b/boot/bootutil/src/Makefile
index 820d7a6..2ee4452 100644
--- a/boot/bootutil/src/Makefile
+++ b/boot/bootutil/src/Makefile
@@ -1,5 +1,3 @@
 # Makefile for Zephyr build
 
-ccflags-y += -DBOOTUTIL_SIGN_RSA
-
-obj-y += loader.o bootutil_misc.o image_validate.o image_rsa.o
+obj-y += loader.o bootutil_misc.o image_validate.o image_rsa.o image_ec256.o
diff --git a/boot/bootutil/src/image_ec256.c b/boot/bootutil/src/image_ec256.c
index f59a8f0..1e7354e 100644
--- a/boot/bootutil/src/image_ec256.c
+++ b/boot/bootutil/src/image_ec256.c
@@ -122,7 +122,7 @@
     if (rc) {
         return -1;
     }
-    if (cp + len != end) {
+    if (cp + len > end) {
         return -2;
     }
     rc = tinycrypt_read_bigint(r, &cp, end);
diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c
index 3aadd82..e94b205 100644
--- a/boot/bootutil/src/loader.c
+++ b/boot/bootutil/src/loader.c
@@ -35,6 +35,9 @@
 #include "bootutil/image.h"
 #include "bootutil_priv.h"
 
+#define BOOT_LOG_LEVEL BOOT_LOG_LEVEL_INFO
+#include "bootutil/bootutil_log.h"
+
 #define BOOT_MAX_IMG_SECTORS        120
 
 /** Number of image slots in flash; currently limited to two. */
@@ -150,6 +153,15 @@
 #define BOOT_SWAP_TRANS_TABLE_SIZE   \
     (sizeof boot_swap_trans_table / sizeof boot_swap_trans_table[0])
 
+#define BOOT_LOG_SWAP_STATE(area, state)                            \
+    BOOT_LOG_INF("%s: magic=%s, copy_done=0x%x, image_ok=0x%x",     \
+                 (area),                                            \
+                 ((state)->magic == BOOT_MAGIC_GOOD ? "good" :      \
+                  (state)->magic == BOOT_MAGIC_UNSET ? "unset" :    \
+                  "bad"),                                           \
+                 (state)->copy_done,                                \
+                 (state)->image_ok)
+
 /**
  * Determines where in flash the most recent boot status is stored.  The boot
  * status is necessary for completing a swap that was interrupted by a boot
@@ -166,6 +178,7 @@
     struct boot_swap_state state_slot1;
     int rc;
     int i;
+    uint8_t source;
 
     rc = boot_read_swap_state_img(0, &state_slot0);
     assert(rc == 0);
@@ -176,6 +189,10 @@
     rc = boot_read_swap_state_scratch(&state_scratch);
     assert(rc == 0);
 
+    BOOT_LOG_SWAP_STATE("Image 0", &state_slot0);
+    BOOT_LOG_SWAP_STATE("Image 1", &state_slot1);
+    BOOT_LOG_SWAP_STATE("Scratch", &state_scratch);
+
     for (i = 0; i < BOOT_STATUS_TABLES_COUNT; i++) {
         table = boot_status_tables + i;
 
@@ -185,11 +202,17 @@
              table->bst_magic_scratch   == state_scratch.magic) &&
             (table->bst_copy_done_slot0 == 0    ||
              table->bst_copy_done_slot0 == state_slot0.copy_done)) {
-
-            return table->bst_status_source;
+            source = table->bst_status_source;
+            BOOT_LOG_INF("Boot source: %s",
+                         source == BOOT_STATUS_SOURCE_NONE ? "none" :
+                         source == BOOT_STATUS_SOURCE_SCRATCH ? "scratch" :
+                         source == BOOT_STATUS_SOURCE_SLOT0 ? "slot 0" :
+                         "BUG; can't happen");
+            return source;
         }
     }
 
+    BOOT_LOG_INF("Boot source: none");
     return BOOT_STATUS_SOURCE_NONE;
 }
 
@@ -545,13 +568,13 @@
 }
 
 static int
-boot_validate_slot1(void)
+boot_validate_slot(int slot)
 {
     const struct flash_area *fap;
     int rc;
     
-    if (boot_data.imgs[1].hdr.ih_magic == 0xffffffff ||
-        boot_data.imgs[1].hdr.ih_flags & IMAGE_F_NON_BOOTABLE) {
+    if (boot_data.imgs[slot].hdr.ih_magic == 0xffffffff ||
+        boot_data.imgs[slot].hdr.ih_flags & IMAGE_F_NON_BOOTABLE) {
 
         /* No bootable image in slot 1; continue booting from slot 0. */
         return -1;
@@ -560,13 +583,14 @@
     /* Image in slot 1 is invalid.  Erase the image and continue booting
      * from slot 0.
      */
-    rc = flash_area_open(FLASH_AREA_IMAGE_1, &fap);
+    rc = flash_area_open(flash_area_id_from_image_slot(slot), &fap);
     if (rc != 0) {
         return BOOT_EFLASH;
     }
 
-    if (boot_data.imgs[1].hdr.ih_magic != IMAGE_MAGIC ||
-        boot_image_check(&boot_data.imgs[1].hdr, fap) != 0) {
+    if ((boot_data.imgs[slot].hdr.ih_magic != IMAGE_MAGIC ||
+	 boot_image_check(&boot_data.imgs[slot].hdr, fap) != 0) &&
+	slot == 1) {
 
         /* Image in slot 1 is invalid.  Erase the image and continue booting
          * from slot 0.
@@ -602,7 +626,7 @@
     }
 
     /* Boot loader wants to switch to slot 1.  Ensure image is valid. */
-    rc = boot_validate_slot1();
+    rc = boot_validate_slot(1);
     if (rc != 0) {
         return BOOT_SWAP_TYPE_FAIL;
     }
@@ -1039,6 +1063,12 @@
 
     switch (swap_type) {
     case BOOT_SWAP_TYPE_NONE:
+#ifdef BOOTUTIL_VALIDATE_SLOT0
+        rc = boot_validate_slot(0);
+        if (rc != 0) {
+            return BOOT_EBADIMAGE;
+        }
+#endif
         slot = 0;
         break;
 
diff --git a/boot/zephyr/flash_map.c b/boot/zephyr/flash_map.c
index 2736e94..502e30d 100644
--- a/boot/zephyr/flash_map.c
+++ b/boot/zephyr/flash_map.c
@@ -26,9 +26,8 @@
 #include <hal/hal_flash.h>
 #include <sysflash/sysflash.h>
 
-#define SYS_LOG_DOMAIN "BOOTLOADER"
-#define SYS_LOG_LEVEL SYS_LOG_LEVEL_INFO
-#include <logging/sys_log.h>
+#define BOOT_LOG_LEVEL BOOT_LOG_LEVEL_INFO
+#include "bootutil/bootutil_log.h"
 
 extern struct device *boot_flash_device;
 
@@ -62,7 +61,7 @@
 {
 	int i;
 
-	SYS_LOG_DBG("%s: area %d", __func__, id);
+	BOOT_LOG_DBG("%s: area %d", __func__, id);
 
 	for (i = 0; i < ARRAY_SIZE(part_map); i++) {
 		if (id == part_map[i].fa_id)
@@ -85,23 +84,28 @@
 int flash_area_read(const struct flash_area *area, uint32_t off, void *dst,
 		    uint32_t len)
 {
-	SYS_LOG_DBG("%s: area=%d, off=%x, len=%x", __func__,
-			area->fa_id, off, len);
+	BOOT_LOG_DBG("%s: area=%d, off=%x, len=%x", __func__,
+		     area->fa_id, off, len);
 	return flash_read(boot_flash_device, area->fa_off + off, dst, len);
 }
 
 int flash_area_write(const struct flash_area *area, uint32_t off, const void *src,
 		     uint32_t len)
 {
-	SYS_LOG_DBG("%s: area=%d, off=%x, len=%x", __func__,
-			area->fa_id, off, len);
-	return flash_write(boot_flash_device, area->fa_off + off, src, len);
+	int rc = 0;
+
+	BOOT_LOG_DBG("%s: area=%d, off=%x, len=%x", __func__,
+		     area->fa_id, off, len);
+	flash_write_protection_set(boot_flash_device, false);
+	rc = flash_write(boot_flash_device, area->fa_off + off, src, len);
+	flash_write_protection_set(boot_flash_device, true);
+	return rc;
 }
 
 int flash_area_erase(const struct flash_area *area, uint32_t off, uint32_t len)
 {
-	SYS_LOG_DBG("%s: area=%d, off=%x, len=%x", __func__,
-			area->fa_id, off, len);
+	BOOT_LOG_DBG("%s: area=%d, off=%x, len=%x", __func__,
+		     area->fa_id, off, len);
 	return flash_erase(boot_flash_device, area->fa_off + off, len);
 }
 
@@ -128,8 +132,10 @@
 int flash_area_to_sectors(int idx, int *cnt, struct flash_area *ret)
 {
 	uint32_t off;
+	uint32_t len;
+	uint32_t max_cnt = *cnt;
 
-	SYS_LOG_DBG("%s: lookup area %d", __func__, idx);
+	BOOT_LOG_DBG("%s: lookup area %d", __func__, idx);
 	/*
 	 * This simple layout has uniform slots, so just fill in the
 	 * right one.
@@ -140,13 +146,34 @@
 	if (*cnt < 1)
 		return -1;
 
-	off = (idx - FLASH_AREA_IMAGE_0 + 1) * FLASH_AREA_IMAGE_0_OFFSET;
+	switch (idx) {
+	case FLASH_AREA_IMAGE_0:
+		off = FLASH_AREA_IMAGE_0_OFFSET;
+		len = FLASH_AREA_IMAGE_0_SIZE;
+		break;
+	case FLASH_AREA_IMAGE_1:
+		off = FLASH_AREA_IMAGE_1_OFFSET;
+		len = FLASH_AREA_IMAGE_1_SIZE;
+		break;
+	case FLASH_AREA_IMAGE_SCRATCH:
+		off = FLASH_AREA_IMAGE_SCRATCH_OFFSET;
+		len = FLASH_AREA_IMAGE_SCRATCH_SIZE;
+		break;
+	default:
+		SYS_LOG_ERR("%s: unknown flash area %d", __func__, idx);
+		return -1;
+	}
 
-	ret->fa_id = idx;
-	ret->fa_device_id = 0;
-	ret->pad16 = 0;
-	ret->fa_off = off;
-	ret->fa_size = FLASH_AREA_IMAGE_0_SIZE;
+	*cnt = 0;
+	while (len > 0 && *cnt < max_cnt) {
+		ret[*cnt].fa_id = idx;
+		ret[*cnt].fa_device_id = 0;
+		ret[*cnt].pad16 = 0;
+		ret[*cnt].fa_off = off + (FLASH_AREA_IMAGE_SCRATCH_SIZE * (*cnt));
+		ret[*cnt].fa_size = FLASH_AREA_IMAGE_SCRATCH_SIZE;
+		*cnt = *cnt + 1;
+		len -= FLASH_AREA_IMAGE_SCRATCH_SIZE;
+	}
 
 	return 0;
 }
diff --git a/boot/zephyr/include/config-asn1.h b/boot/zephyr/include/config-asn1.h
new file mode 100644
index 0000000..ba5b97c
--- /dev/null
+++ b/boot/zephyr/include/config-asn1.h
@@ -0,0 +1,47 @@
+/*
+ *  Configuration of mbedTLS containing only the ASN.1 parser.
+ *
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  Copyright (C) 2016, Linaro Ltd
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  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.
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ */
+
+/*
+ * Minimal configuration for using TLS in the bootloader
+ *
+ * - RSA or ECDSA signature verification
+ */
+
+#ifndef MBEDTLS_CONFIG_H
+#define MBEDTLS_CONFIG_H
+
+#define MBEDTLS_PLATFORM_C
+#define MBEDTLS_PLATFORM_MEMORY
+#define MBEDTLS_MEMORY_BUFFER_ALLOC_C
+#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
+
+/* mbed TLS modules */
+#define MBEDTLS_ASN1_PARSE_C
+// #define MBEDTLS_ASN1_WRITE_C
+// #define MBEDTLS_BIGNUM_C
+// #define MBEDTLS_MD_C
+// #define MBEDTLS_OID_C
+#define MBEDTLS_SHA256_C
+
+#include "mbedtls/check_config.h"
+
+#endif /* MBEDTLS_CONFIG_H */
diff --git a/boot/zephyr/keys.c b/boot/zephyr/keys.c
index 051eb8a..9a06f3c 100644
--- a/boot/zephyr/keys.c
+++ b/boot/zephyr/keys.c
@@ -19,6 +19,7 @@
 
 #include <bootutil/sign_key.h>
 
+#if defined(BOOTUTIL_SIGN_RSA)
 const unsigned char root_pub_der[] = {
   0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xd1, 0x06, 0x08,
   0x1a, 0x18, 0x44, 0x2c, 0x18, 0xe8, 0xfb, 0xfd, 0xf7, 0x0d, 0xa3, 0x4f,
@@ -45,6 +46,24 @@
   0xc9, 0x02, 0x03, 0x01, 0x00, 0x01
 };
 const unsigned int root_pub_der_len = 270;
+#elif defined(BOOTUTIL_SIGN_EC256)
+const unsigned char root_pub_der[] = {
+	0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
+	0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a,
+	0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
+	0x42, 0x00, 0x04, 0x2a, 0xcb, 0x40, 0x3c, 0xe8,
+	0xfe, 0xed, 0x5b, 0xa4, 0x49, 0x95, 0xa1, 0xa9,
+	0x1d, 0xae, 0xe8, 0xdb, 0xbe, 0x19, 0x37, 0xcd,
+	0x14, 0xfb, 0x2f, 0x24, 0x57, 0x37, 0xe5, 0x95,
+	0x39, 0x88, 0xd9, 0x94, 0xb9, 0xd6, 0x5a, 0xeb,
+	0xd7, 0xcd, 0xd5, 0x30, 0x8a, 0xd6, 0xfe, 0x48,
+	0xb2, 0x4a, 0x6a, 0x81, 0x0e, 0xe5, 0xf0, 0x7d,
+	0x8b, 0x68, 0x34, 0xcc, 0x3a, 0x6a, 0xfc, 0x53,
+	0x8e, 0xfa, 0xc1, };
+const unsigned int root_pub_der_len = 91;
+#else
+#error "No public key available for given signing algorithm."
+#endif
 
 const struct bootutil_key bootutil_keys[] = {
 	{
diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c
index 960dcf2..50da986 100644
--- a/boot/zephyr/main.c
+++ b/boot/zephyr/main.c
@@ -18,9 +18,8 @@
 #include <flash.h>
 #include <asm_inline.h>
 
-#define SYS_LOG_DOMAIN "BOOTLOADER"
-#define SYS_LOG_LEVEL SYS_LOG_LEVEL_INFO
-#include <logging/sys_log.h>
+#define BOOT_LOG_LEVEL BOOT_LOG_LEVEL_INFO
+#include "bootutil/bootutil_log.h"
 
 #if defined(MCUBOOT_TARGET_CONFIG)
 #include MCUBOOT_TARGET_CONFIG
@@ -46,39 +45,34 @@
 	struct vector_table *vt;
 	int rc;
 
-	SYS_LOG_INF("Starting bootloader");
+	BOOT_LOG_INF("Starting bootloader");
 
 	os_heap_init();
 
 	boot_flash_device = device_get_binding(FLASH_DRIVER_NAME);
 	if (!boot_flash_device) {
-		SYS_LOG_ERR("Flash device not found");
+		BOOT_LOG_ERR("Flash device not found");
 		while (1)
 			;
 	}
 
 	rc = boot_go(&rsp);
 	if (rc != 0) {
-		SYS_LOG_ERR("Unable to find bootable image");
+		BOOT_LOG_ERR("Unable to find bootable image");
 		while (1)
 			;
 	}
 
-	SYS_LOG_INF("Bootloader chainload address: 0x%x", rsp.br_image_addr);
+	BOOT_LOG_INF("Bootloader chainload address: 0x%x", rsp.br_image_addr);
 	vt = (struct vector_table *)(rsp.br_image_addr +
 				     rsp.br_hdr->ih_hdr_size);
 	irq_lock();
 	_MspSet(vt->msp);
 
-	SYS_LOG_INF("Setting vector table to %p", vt);
-
-	/* Not all targets set the VTOR, so just set it. */
-	_scs_relocate_vector_table((void *) vt);
-
-	SYS_LOG_INF("Jumping to the first image slot");
+	BOOT_LOG_INF("Jumping to the first image slot");
 	((void (*)(void))vt->reset)();
 
-	SYS_LOG_ERR("Never should get here");
+	BOOT_LOG_ERR("Never should get here");
 	while (1)
 		;
 }
diff --git a/boot/zephyr/prj-p256.conf b/boot/zephyr/prj-p256.conf
new file mode 100644
index 0000000..95b2b7e
--- /dev/null
+++ b/boot/zephyr/prj-p256.conf
@@ -0,0 +1,18 @@
+CONFIG_CONSOLE_HANDLER=y
+CONFIG_SYS_LOG=y
+CONFIG_DEBUG=y
+
+CONFIG_MAIN_STACK_SIZE=10240
+CONFIG_MBEDTLS=y
+CONFIG_MBEDTLS_BUILTIN=y
+CONFIG_MBEDTLS_CFG_FILE="config-asn1.h"
+CONFIG_TINYCRYPT=y
+CONFIG_TINYCRYPT_ECC_DSA=y
+
+### mbedTLS wants a heap
+CONFIG_HEAP_MEM_POOL_SIZE=16384
+
+CONFIG_FLASH=y
+
+### Disable Bluetooth by default
+# CONFIG_BLUETOOTH is not set
diff --git a/boot/zephyr/targets/96b_nitrogen.h b/boot/zephyr/targets/96b_nitrogen.h
index 291844f..9a0443d 100644
--- a/boot/zephyr/targets/96b_nitrogen.h
+++ b/boot/zephyr/targets/96b_nitrogen.h
@@ -20,7 +20,7 @@
  */
 
 #define FLASH_DRIVER_NAME		"NRF5_FLASH"
-#define FLASH_ALIGN			1
+#define FLASH_ALIGN			4
 #define FLASH_AREA_IMAGE_0_OFFSET	0x08000
 #define FLASH_AREA_IMAGE_0_SIZE		0x3A000
 #define FLASH_AREA_IMAGE_1_OFFSET	0x42000
diff --git a/root-ec-p256.pem b/root-ec-p256.pem
new file mode 100644
index 0000000..2f4accf
--- /dev/null
+++ b/root-ec-p256.pem
@@ -0,0 +1,5 @@
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEINeY1S+DASQ701QrflXtTHRhGQCw+VBagk/h6OwGO8/xoAoGCCqGSM49
+AwEHoUQDQgAEKstAPOj+7VukSZWhqR2u6Nu+GTfNFPsvJFc35ZU5iNmUudZa69fN
+1TCK1v5IskpqgQ7l8H2LaDTMOmr8U476wQ==
+-----END EC PRIVATE KEY-----
diff --git a/root.pem b/root-rsa-2048.pem
similarity index 100%
rename from root.pem
rename to root-rsa-2048.pem
diff --git a/sign.sh b/sign.sh
index 6fe08f5..5c9989e 100755
--- a/sign.sh
+++ b/sign.sh
@@ -1,22 +1,48 @@
 #! /bin/sh
 
+# This script can be used as an example of how to sign images.
+
 source $(dirname $0)/target.sh
 
-./scripts/zep2newt.py \
-    --bin ../zephyr/samples/shell/outdir/$BOARD/zephyr.bin \
-    --key root.pem \
-    --sig RSA \
-    --out shell.signed.bin \
-    --vtoff 0x200 \
-    --word-size 8 \
-    --image-version 3 \
-    --bit --pad 0x20000
+# RSA signatures can be made with the signing script in the scripts
+# directory.
+if true; then
+	./scripts/zep2newt.py \
+	    --bin ../zephyr/samples/shell/outdir/$BOARD/zephyr.bin \
+	    --key root.pem \
+	    --sig RSA \
+	    --out shell.signed.bin \
+	    --vtoff 0x200 \
+	    --word-size 8 \
+	    --image-version 3 \
+	    --bit --pad 0x20000
 
-./scripts/zep2newt.py \
-    --bin ../zephyr/samples/hello_world/outdir/$BOARD/zephyr.bin \
-    --key root.pem \
-    --sig RSA \
-    --vtoff 0x200 \
-    --word-size 8 \
-    --image-version 2 \
-    --out hello.signed.bin
+	./scripts/zep2newt.py \
+	    --bin ../zephyr/samples/hello_world/outdir/$BOARD/zephyr.bin \
+	    --key root.pem \
+	    --sig RSA \
+	    --vtoff 0x200 \
+	    --word-size 8 \
+	    --image-version 2 \
+	    --out hello.signed.bin
+fi
+
+# Currently, ECDSA signatures need to be made with the imgtool.  See
+# 'imgtool' for instructions on building the tool.
+if false; then
+	imgtool sign \
+		--key root_ec.pem \
+		--header-size 0x200 \
+		--version 3.0 \
+		--align 8 \
+		--pad 0x20000 \
+		../zephyr/samples/shell/outdir/$BOARD/zephyr.bin \
+		shell.signed.bin
+
+	imgtool sign \
+		--key root_ec.pem \
+		--header-size 0x200 \
+		--version 3.0 \
+		../zephyr/samples/hello_world/outdir/$BOARD/zephyr.bin \
+		hello.signed.bin
+fi