zephyr: fix flash_area_to_sectors()

This fixes MCUB-39.

On Zephyr targets, flash_area_to_sectors() assumes that the flash
device's sector size is equal to the size of the scratch area.

That breaks swap and rollback when scratch size doesn't divide image
size, since the image flash areas will not be correctly configured.
This is a valid configuration supported by the rest of mcuboot.

The best way to fix this would be to get the flash layout from Zephyr,
but that's not possible yet.

Instead, provide a new FLASH_AREA_IMAGE_SECTOR_SIZE define from
target.h. This must be the sector size for these areas:

       - FLASH_AREA_IMAGE_0
       - FLASH_AREA_IMAGE_1
       - FLASH_AREA_IMAGE_SCRATCH

Other areas on the device may have sizes different than
FLASH_AREA_IMAGE_SECTOR_SIZE.

This won't work on platforms where those areas have nonuniform sector
sizes, but we'll cross that bridge when we come to it. (At that point,
an upstream Zephyr change to the flash API really seems needed.)

Revert to the old/buggy behavior when FLASH_AREA_IMAGE_SECTOR_SIZE
isn't provided, but emit a warning. Additionally, touch up the logging
and error handling while we're here.

Signed-off-by: Marti Bolivar <marti.bolivar@linaro.org>
diff --git a/boot/zephyr/flash_map.c b/boot/zephyr/flash_map.c
index 431eacf..edb02ed 100644
--- a/boot/zephyr/flash_map.c
+++ b/boot/zephyr/flash_map.c
@@ -125,6 +125,11 @@
 	return slot + FLASH_AREA_IMAGE_0;
 }
 
+#ifndef FLASH_AREA_IMAGE_SECTOR_SIZE
+#warning "Missing FLASH_AREA_IMAGE_SECTOR_SIZE; assuming scratch size instead"
+#define FLASH_AREA_IMAGE_SECTOR_SIZE FLASH_AREA_IMAGE_SCRATCH_SIZE
+#endif
+
 /*
  * Lookup the sector map for a given flash area.  This should fill in
  * `ret` with all of the sectors in the area.  `*cnt` will be set to
@@ -136,8 +141,8 @@
 	uint32_t off;
 	uint32_t len;
 	uint32_t max_cnt = *cnt;
+	uint32_t rem_len;
 
-	BOOT_LOG_DBG("lookup area %d", idx);
 	/*
 	 * This simple layout has uniform slots, so just fill in the
 	 * right one.
@@ -166,15 +171,30 @@
 		return -1;
 	}
 
+	BOOT_LOG_DBG("area %d: offset=0x%x, length=0x%x, sector size=0x%x",
+		     idx, off, len, FLASH_AREA_IMAGE_SECTOR_SIZE);
+
+	rem_len = len;
 	*cnt = 0;
-	while (len > 0 && *cnt < max_cnt) {
+	while (rem_len > 0 && *cnt < max_cnt) {
+		if (rem_len < FLASH_AREA_IMAGE_SECTOR_SIZE) {
+			BOOT_LOG_ERR("area %d size 0x%x not divisible by sector size 0x%x",
+				     idx, len, FLASH_AREA_IMAGE_SECTOR_SIZE);
+			return -1;
+		}
+
 		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;
+		ret[*cnt].fa_off = off + (FLASH_AREA_IMAGE_SECTOR_SIZE * (*cnt));
+		ret[*cnt].fa_size = FLASH_AREA_IMAGE_SECTOR_SIZE;
 		*cnt = *cnt + 1;
-		len -= FLASH_AREA_IMAGE_SCRATCH_SIZE;
+		rem_len -= FLASH_AREA_IMAGE_SECTOR_SIZE;
+	}
+
+	if (*cnt >= max_cnt) {
+		BOOT_LOG_ERR("flash area %d sector count overflow", idx);
+		return -1;
 	}
 
 	return 0;
diff --git a/boot/zephyr/include/target.h b/boot/zephyr/include/target.h
index 6f85e5b..de9ecaf 100644
--- a/boot/zephyr/include/target.h
+++ b/boot/zephyr/include/target.h
@@ -6,10 +6,16 @@
 #ifndef H_TARGETS_TARGET_
 #define H_TARGETS_TARGET_
 
+/* Board-specific definitions go first, to allow maximum override. */
 #if defined(MCUBOOT_TARGET_CONFIG)
 #include MCUBOOT_TARGET_CONFIG
 #else
 #error "Board is currently not supported by bootloader"
 #endif
 
+/* SoC family configuration. */
+#if defined(CONFIG_SOC_FAMILY_NRF5)
+#include "soc_family_nrf5.h"
+#endif
+
 #endif
diff --git a/boot/zephyr/targets/96b_carbon.h b/boot/zephyr/targets/96b_carbon.h
index 8243f35..8f52f54 100644
--- a/boot/zephyr/targets/96b_carbon.h
+++ b/boot/zephyr/targets/96b_carbon.h
@@ -32,3 +32,7 @@
 #define FLASH_AREA_IMAGE_1_SIZE		0x20000
 #define FLASH_AREA_IMAGE_SCRATCH_OFFSET	0x60000
 #define FLASH_AREA_IMAGE_SCRATCH_SIZE	0x20000
+
+/* Though sectors have variable size on this part, we've chosen
+ * three sectors with uniform size here. */
+#define FLASH_AREA_IMAGE_SECTOR_SIZE	0x20000
diff --git a/boot/zephyr/targets/96b_nitrogen.h b/boot/zephyr/targets/96b_nitrogen.h
index 968c721..9c2777c 100644
--- a/boot/zephyr/targets/96b_nitrogen.h
+++ b/boot/zephyr/targets/96b_nitrogen.h
@@ -27,3 +27,4 @@
 #define FLASH_AREA_IMAGE_1_SIZE		0x34000
 #define FLASH_AREA_IMAGE_SCRATCH_OFFSET	0x70000
 #define FLASH_AREA_IMAGE_SCRATCH_SIZE	0x0D000
+/* Flash sector size is provided by SoC family include */
diff --git a/boot/zephyr/targets/frdm_k64f.h b/boot/zephyr/targets/frdm_k64f.h
index 9270399..cfec2b3 100644
--- a/boot/zephyr/targets/frdm_k64f.h
+++ b/boot/zephyr/targets/frdm_k64f.h
@@ -27,3 +27,4 @@
 #define FLASH_AREA_IMAGE_1_SIZE		0x20000
 #define FLASH_AREA_IMAGE_SCRATCH_OFFSET	0x60000
 #define FLASH_AREA_IMAGE_SCRATCH_SIZE	0x20000
+#define FLASH_AREA_IMAGE_SECTOR_SIZE	0x01000
diff --git a/boot/zephyr/targets/nucleo_f401re.h b/boot/zephyr/targets/nucleo_f401re.h
index b8328be..c7fe17a 100644
--- a/boot/zephyr/targets/nucleo_f401re.h
+++ b/boot/zephyr/targets/nucleo_f401re.h
@@ -27,3 +27,7 @@
 #define FLASH_AREA_IMAGE_1_SIZE		0x20000
 #define FLASH_AREA_IMAGE_SCRATCH_OFFSET	0x60000
 #define FLASH_AREA_IMAGE_SCRATCH_SIZE	0x20000
+
+/* Though sectors have variable size on this part, we've chosen
+ * three sectors with uniform size here. */
+#define FLASH_AREA_IMAGE_SECTOR_SIZE	0x20000
diff --git a/boot/zephyr/targets/soc_family_nrf5.h b/boot/zephyr/targets/soc_family_nrf5.h
new file mode 100644
index 0000000..05d1d84
--- /dev/null
+++ b/boot/zephyr/targets/soc_family_nrf5.h
@@ -0,0 +1,12 @@
+/*
+ *  Copyright (C) 2017, Linaro Ltd
+ *  SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <soc.h>
+
+/*
+ * Rather than hard-coding the flash size for each SoC, pull it out of
+ * the factory information configuration registers.
+ */
+#define FLASH_AREA_IMAGE_SECTOR_SIZE (NRF_FICR->CODEPAGESIZE)