Adds total size of a swap to the trailer

When starting a swap upgrade, the total size of data to be swapped is
calculated only at the beginning and saved to the trailer. This avoids
having to use complicated heuristics to find the total swap size, which
might depend on data that was already moved. When resuming a swap, the
size is found in the trailer and used.

Also includes some small comment fixes and refactors.

Signed-off-by: Fabio Utzig <utzig@apache.org>
Signed-off-by: David Brown <david.brown@linaro.org>
diff --git a/boot/bootutil/src/bootutil_misc.c b/boot/bootutil/src/bootutil_misc.c
index a71df72..bf4e9b8 100644
--- a/boot/bootutil/src/bootutil_misc.c
+++ b/boot/bootutil/src/bootutil_misc.c
@@ -120,7 +120,7 @@
 {
     return /* state for all sectors */
            BOOT_STATUS_MAX_ENTRIES * BOOT_STATUS_STATE_COUNT * min_write_sz +
-           BOOT_MAX_ALIGN * 2 /* copy_done + image_ok */                    +
+           BOOT_MAX_ALIGN * 3 /* copy_done + image_ok + swap_size */        +
            BOOT_MAGIC_SZ;
 }
 
@@ -128,7 +128,7 @@
 boot_scratch_trailer_sz(uint8_t min_write_sz)
 {
     return BOOT_STATUS_STATE_COUNT * min_write_sz +  /* state for one sector */
-           BOOT_MAX_ALIGN                         +  /* image_ok */
+           BOOT_MAX_ALIGN * 2                     +  /* image_ok + swap_size */
            BOOT_MAGIC_SZ;
 }
 
@@ -186,6 +186,20 @@
     return fap->fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN;
 }
 
+static uint32_t
+boot_swap_size_off(const struct flash_area *fap)
+{
+    /*
+     * The "swap_size" field if located just before the trailer.
+     * The scratch slot doesn't store "copy_done"...
+     */
+    if (fap->fa_id == FLASH_AREA_IMAGE_SCRATCH) {
+        return fap->fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN * 2;
+    }
+
+    return fap->fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN * 3;
+}
+
 int
 boot_read_swap_state(const struct flash_area *fap,
                      struct boot_swap_state *state)
@@ -203,14 +217,14 @@
 
     if (fap->fa_id != FLASH_AREA_IMAGE_SCRATCH) {
         off = boot_copy_done_off(fap);
-        rc = flash_area_read(fap, off, &state->copy_done, 1);
+        rc = flash_area_read(fap, off, &state->copy_done, sizeof state->copy_done);
         if (rc != 0) {
             return BOOT_EFLASH;
         }
     }
 
     off = boot_image_ok_off(fap);
-    rc = flash_area_read(fap, off, &state->image_ok, 1);
+    rc = flash_area_read(fap, off, &state->image_ok, sizeof state->image_ok);
     if (rc != 0) {
         return BOOT_EFLASH;
     }
@@ -246,6 +260,68 @@
 }
 
 int
+boot_read_swap_size(uint32_t *swap_size)
+{
+    uint32_t magic[BOOT_MAGIC_SZ];
+    uint32_t off;
+    const struct flash_area *fap;
+    int rc;
+
+    /*
+     * In the middle a swap, tries to locate the saved swap size. Looks
+     * for a valid magic, first on Slot 0, then on scratch. Both "slots"
+     * can end up being temporary storage for a swap and it is assumed
+     * that if magic is valid then swap size is too, because magic is
+     * always written in the last step.
+     */
+
+    rc = flash_area_open(FLASH_AREA_IMAGE_0, &fap);
+    if (rc != 0) {
+        return BOOT_EFLASH;
+    }
+
+    off = boot_magic_off(fap);
+    rc = flash_area_read(fap, off, magic, BOOT_MAGIC_SZ);
+    if (rc != 0) {
+        rc = BOOT_EFLASH;
+        goto out;
+    }
+
+    if (memcmp(magic, boot_img_magic, BOOT_MAGIC_SZ) != 0) {
+        /*
+         * If Slot 0 's magic is not valid, try scratch...
+         */
+
+        flash_area_close(fap);
+
+        rc = flash_area_open(FLASH_AREA_IMAGE_SCRATCH, &fap);
+        if (rc != 0) {
+            return BOOT_EFLASH;
+        }
+
+        off = boot_magic_off(fap);
+        rc = flash_area_read(fap, off, magic, BOOT_MAGIC_SZ);
+        if (rc != 0) {
+            rc = BOOT_EFLASH;
+            goto out;
+        }
+
+        assert(memcmp(magic, boot_img_magic, BOOT_MAGIC_SZ) == 0);
+    }
+
+    off = boot_swap_size_off(fap);
+    rc = flash_area_read(fap, off, swap_size, sizeof *swap_size);
+    if (rc != 0) {
+        rc = BOOT_EFLASH;
+    }
+
+out:
+    flash_area_close(fap);
+    return rc;
+}
+
+
+int
 boot_write_magic(const struct flash_area *fap)
 {
     uint32_t off;
@@ -306,6 +382,31 @@
 }
 
 int
+boot_write_swap_size(const struct flash_area *fap, uint32_t swap_size)
+{
+    uint32_t off;
+    int rc;
+    uint8_t buf[BOOT_MAX_ALIGN];
+    uint8_t align;
+
+    off = boot_swap_size_off(fap);
+    align = hal_flash_align(fap->fa_device_id);
+    assert(align <= BOOT_MAX_ALIGN);
+    if (align < sizeof swap_size) {
+        align = sizeof swap_size;
+    }
+    memset(buf, 0xFF, BOOT_MAX_ALIGN);
+    memcpy(buf, (uint8_t *)&swap_size, sizeof swap_size);
+
+    rc = flash_area_write(fap, off, buf, align);
+    if (rc != 0) {
+        return BOOT_EFLASH;
+    }
+
+    return 0;
+}
+
+int
 boot_swap_type(void)
 {
     const struct boot_swap_table *table;