You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by cc...@apache.org on 2016/10/14 23:41:20 UTC

[1/2] incubator-mynewt-core git commit: Two-stage boot (test / confirm).

Repository: incubator-mynewt-core
Updated Branches:
  refs/heads/develop e7abb3c74 -> 3758239db


Two-stage boot (test / confirm).

Code cleanup to follow.


Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/commit/4b1a5c1d
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/4b1a5c1d
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/4b1a5c1d

Branch: refs/heads/develop
Commit: 4b1a5c1dacb83ca13df68460a752b3d6d94041ce
Parents: e7abb3c
Author: Christopher Collins <cc...@apache.org>
Authored: Fri Oct 14 13:27:14 2016 -0700
Committer: Christopher Collins <cc...@apache.org>
Committed: Fri Oct 14 16:39:43 2016 -0700

----------------------------------------------------------------------
 boot/bootutil/src/bootutil_misc.c  |  65 ++++++++--
 boot/bootutil/src/bootutil_priv.h  |  67 ++++++++++-
 boot/bootutil/src/loader.c         | 175 ++++++++++++++++-----------
 boot/bootutil/test/src/boot_test.c | 207 ++++++++++++++++++--------------
 mgmt/imgmgr/src/imgmgr_state.c     |  28 +++--
 5 files changed, 352 insertions(+), 190 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/4b1a5c1d/boot/bootutil/src/bootutil_misc.c
----------------------------------------------------------------------
diff --git a/boot/bootutil/src/bootutil_misc.c b/boot/bootutil/src/bootutil_misc.c
index 0ee7ea9..bb7b2a3 100644
--- a/boot/bootutil/src/bootutil_misc.c
+++ b/boot/bootutil/src/bootutil_misc.c
@@ -39,7 +39,7 @@ int8_t boot_split_app_active;
 /*
  * Read the image trailer from a given slot.
  */
-static int
+int
 boot_vect_read_img_trailer(int slot, struct boot_img_trailer *bit)
 {
     int rc;
@@ -59,6 +59,39 @@ boot_vect_read_img_trailer(int slot, struct boot_img_trailer *bit)
     return rc;
 }
 
+int
+boot_status_sz(void)
+{
+    return sizeof(struct boot_img_trailer) + 32 * sizeof(uint32_t);
+}
+
+/*
+ * Read the image trailer from a given slot.
+ */
+static int
+boot_vect_read_img_trailer(int slot, struct boot_img_trailer *bit)
+{
+    struct boot_img_trailer bit0;
+    struct boot_img_trailer bit1;
+
+    boot_vect_read_img_trailer(0, &bit0);
+    boot_vect_read_img_trailer(1, &bit1);
+
+    if (bit0.bit_copy_start == BOOT_MAGIC_SWAP_NONE &&
+        bit1.bit_copy_start == BOOT_MAGIC_SWAP_NONE) {
+
+    area_id = flash_area_id_from_image_slot(slot);
+    rc = flash_area_open(area_id, &fap);
+    if (rc) {
+        return rc;
+    }
+    off = fap->fa_size - sizeof(struct boot_img_trailer);
+    rc = flash_area_read(fap, off, bit, sizeof(*bit));
+    flash_area_close(fap);
+
+    return rc;
+}
+
 /**
  * Retrieves from the slot number of the test image (i.e.,
  * the image that has not been proven stable, and which will only run once).
@@ -83,7 +116,7 @@ boot_vect_read_test(int *slot)
         if (rc) {
             continue;
         }
-        if (bit.bit_copy_start == BOOT_IMG_MAGIC) {
+        if (bit.bit_copy_start == BOOT_MAGIC_SWAP_TEMP) {
             *slot = i;
             return 0;
         }
@@ -108,7 +141,7 @@ boot_vect_read_main(int *slot)
     rc = boot_vect_read_img_trailer(0, &bit);
     assert(rc == 0);
 
-    if (bit.bit_copy_start != BOOT_IMG_MAGIC || bit.bit_img_ok != 0xff) {
+    if (bit.bit_copy_start != BOOT_MAGIC_SWAP_TEMP || bit.bit_img_ok != 0xff) {
         /*
          * If there never was copy that took place, or if the current
          * image has been marked good, we'll keep booting it.
@@ -144,7 +177,7 @@ boot_vect_write_test(int slot)
     }
 
     off = fap->fa_size - sizeof(struct boot_img_trailer);
-    magic = BOOT_IMG_MAGIC;
+    magic = BOOT_MAGIC_SWAP_TEMP;
 
     rc = flash_area_write(fap, off, &magic, sizeof(magic));
     flash_area_close(fap);
@@ -256,21 +289,26 @@ boot_read_status(struct boot_status *bs)
     uint8_t flash_id;
     uint32_t off;
 
-    /*
-     * Check if boot_img_trailer is in scratch, or at the end of slot0.
-     */
+    /* Check if boot_img_trailer is in scratch, or at the end of slot0. */
     boot_slot_magic(0, &bit);
-    if (bit.bit_copy_start == BOOT_IMG_MAGIC && bit.bit_copy_done == 0xff) {
+    if (bit.bit_copy_start != BOOT_MAGIC_SWAP_NONE &&
+        bit.bit_copy_done == 0xff) {
+
         boot_magic_loc(0, &flash_id, &off);
         boot_read_status_bytes(bs, flash_id, off);
         return 1;
     }
+
     boot_scratch_magic(&bit);
-    if (bit.bit_copy_start == BOOT_IMG_MAGIC && bit.bit_copy_done == 0xff) {
+    if (bit.bit_copy_start != BOOT_MAGIC_SWAP_NONE &&
+        bit.bit_copy_done == 0xff) {
+
         boot_scratch_loc(&flash_id, &off);
         boot_read_status_bytes(bs, flash_id, off);
         return 1;
     }
+
+
     return 0;
 }
 
@@ -316,10 +354,10 @@ boot_write_status(struct boot_status *bs)
  * progress.
  */
 void
-boot_clear_status(void)
+boot_set_copy_done(void)
 {
+    struct boot_img_trailer bit;
     uint32_t off;
-    uint8_t val = 0;
     uint8_t flash_id;
 
     /*
@@ -327,8 +365,9 @@ boot_clear_status(void)
      * Here we say that copy operation was finished.
      */
     boot_magic_loc(0, &flash_id, &off);
-    off += sizeof(uint32_t);
-    hal_flash_write(flash_id, off, &val, sizeof(val));
+    bit.bit_copy_start = BOOT_MAGIC_SWAP_PERM;
+    bit.bit_copy_done = 1;
+    hal_flash_write(flash_id, off, &bit, 5);
 }
 
 int

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/4b1a5c1d/boot/bootutil/src/bootutil_priv.h
----------------------------------------------------------------------
diff --git a/boot/bootutil/src/bootutil_priv.h b/boot/bootutil/src/bootutil_priv.h
index d24a671..7112c60 100644
--- a/boot/bootutil/src/bootutil_priv.h
+++ b/boot/bootutil/src/bootutil_priv.h
@@ -36,21 +36,32 @@ extern "C" {
 
 #define BOOT_TMPBUF_SZ  256
 
-
-
 /*
  * Maintain state of copy progress.
  */
 struct boot_status {
     uint32_t idx;       /* Which area we're operating on */
     uint8_t elem_sz;    /* Size of the status element to write in bytes */
-    uint8_t state;      /* Which part of the swapping process are we at */
+
+    /**
+     * Which action in the swapping process comes next.
+     * 0: copy slot-1-area --> scratch
+     * 1: copy slot-0-area --> slot-1-area
+     * 2: copy scratch     --> slot-0-area
+     */
+    uint8_t state;
 };
 
+#define BOOT_SWAP_TYPE_NONE     0
+#define BOOT_SWAP_TYPE_TEMP     1
+#define BOOT_SWAP_TYPE_PERM     2
+
 /*
  * End-of-image slot data structure.
  */
-#define BOOT_IMG_MAGIC  0x12344321
+#define BOOT_MAGIC_SWAP_NONE    0xffffffff
+#define BOOT_MAGIC_SWAP_TEMP    0x12344321
+#define BOOT_MAGIC_SWAP_PERM    0x56788765
 struct boot_img_trailer {
     uint32_t bit_copy_start;
     uint8_t  bit_copy_done;
@@ -58,6 +69,52 @@ struct boot_img_trailer {
     uint16_t _pad;
 };
 
+/*
+ *                | slot-0     | slot-1     |
+ * ---------------+------------+------------|
+ * bit-copy-start | 0xffffffff | 0xffffffff |
+ *  bit-copy-done | 0x**       | 0x**       |
+ *     bit-img-ok | 0x**       | 0x**       |
+ * ---------------+------------+------------'
+ * swap: none                               |
+ * -----------------------------------------'
+ *
+ * ~~~
+ *
+ *                | slot-0     | slot-1     |
+ * ---------------+------------+------------|
+ * bit-copy-start | 0x******** | 0x12344321 |
+ *  bit-copy-done | 0x**       | 0x**       |
+ *     bit-img-ok | 0x**       | 0x**       |
+ * ---------------+------------+------------'
+ * swap: temporary                          |
+ * -----------------------------------------'
+ *
+ * ~~~
+ *
+ *                | slot-0     | slot-1     |
+ * ---------------+------------+------------|
+ * bit-copy-start | 0x56788765 | 0xffffffff |
+ *  bit-copy-done | 0x**       | 0x**       |
+ *     bit-img-ok | 0xff       | 0x**       |
+ * ---------------+------------+------------'
+ * swap: permanent (revert)                 |
+ * -----------------------------------------'
+ *
+ * ~~~
+ *
+ *                | slot-0     | slot-1     |
+ * ---------------+------------+------------|
+ * bit-copy-start | 0x56788765 | 0x******** |
+ *  bit-copy-done | 0x**       | 0x**       |
+ *     bit-img-ok | 0x01       | 0x**       |
+ * ---------------+------------+------------'
+ * swap: none (confirmed)                   |
+ * -----------------------------------------'
+ */
+
+int boot_status_sz(void);
+
 int bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, int slen,
     uint8_t key_id);
 
@@ -65,7 +122,7 @@ int boot_read_image_header(struct boot_image_location *loc,
   struct image_header *out_hdr);
 int boot_write_status(struct boot_status *bs);
 int boot_read_status(struct boot_status *bs);
-void boot_clear_status(void);
+void boot_set_copy_done(void);
 
 void boot_magic_loc(int slot_num, uint8_t *flash_id, uint32_t *off);
 void boot_scratch_loc(uint8_t *flash_id, uint32_t *off);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/4b1a5c1d/boot/bootutil/src/loader.c
----------------------------------------------------------------------
diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c
index 54a1e0c..7c07a9c 100644
--- a/boot/bootutil/src/loader.c
+++ b/boot/bootutil/src/loader.c
@@ -185,6 +185,39 @@ boot_scratch_magic(struct boot_img_trailer *bit)
     hal_flash_read(flash_id, off, bit, sizeof(*bit));
 }
 
+static int
+boot_swap_type(void)
+{
+    struct boot_img_trailer bit0;
+    struct boot_img_trailer bit1;
+
+    boot_slot_magic(0, &bit0);
+    boot_slot_magic(1, &bit1);
+
+    if (bit0.bit_copy_start == BOOT_MAGIC_SWAP_NONE &&
+        bit1.bit_copy_start == BOOT_MAGIC_SWAP_NONE) {
+
+        return BOOT_SWAP_TYPE_NONE;
+    }
+
+    if (bit1.bit_copy_start == BOOT_MAGIC_SWAP_TEMP) {
+        return BOOT_SWAP_TYPE_TEMP;
+    }
+
+    if (bit0.bit_copy_start == BOOT_MAGIC_SWAP_PERM) {
+        if (bit0.bit_img_ok != 0xff) {
+            return BOOT_SWAP_TYPE_NONE;
+        } else {
+            return BOOT_SWAP_TYPE_PERM;
+        }
+    }
+
+    /* This should never happen. */
+    /* XXX: Remove this assert. */
+    assert(0);
+    return BOOT_SWAP_TYPE_NONE;
+}
+
 /*
  * Gather info about image in a given slot.
  */
@@ -195,6 +228,8 @@ boot_image_info(void)
     struct boot_img *b;
     struct flash_area *scratch;
 
+    memset(&boot_state, 0, sizeof boot_state);
+
     for (i = 0; i < BOOT_NUM_SLOTS; i++) {
         b = &boot_img[i];
         boot_slot_addr(i, &b->loc);
@@ -282,53 +317,47 @@ split_image_check(struct image_header *app_hdr,
  *                              determined.
  */
 static int
-boot_select_image_slot(void)
+boot_validate_state(int swap_type)
 {
-    /*
-     * Check for swap magic. Check the integrity of the suggested image.
-     */
-    int rc;
-    int i;
-    struct boot_img *b;
     struct boot_img_trailer bit;
+    struct boot_img *b;
+    int img_ok;
+    int slot;
+    int rc;
 
-    boot_slot_magic(0, &bit);
-    if (bit.bit_copy_start == BOOT_IMG_MAGIC && bit.bit_copy_done != 0xff &&
-      bit.bit_img_ok == 0xff) {
-        /*
-         * Copied the image successfully, but image was not confirmed as good.
-         * We need to go back to another image.
-         */
-        boot_vect_write_test(1);
+    if (swap_type == BOOT_SWAP_TYPE_NONE) {
+        slot = 0;
+    } else {
+        slot = 1;
     }
-    for (i = 1; i < BOOT_NUM_SLOTS; i++) {
-        b = &boot_img[i];
-        boot_slot_magic(i, &bit);
-        if (bit.bit_copy_start == BOOT_IMG_MAGIC) {
-            if (b->hdr.ih_magic == IMAGE_MAGIC_NONE) {
-                continue;
-            }
-            if (!boot_image_bootable(&b->hdr)) {
-                continue;
-            }
-            rc = boot_image_check(&b->hdr, &b->loc);
-            if (rc) {
-                /*
-                 * Image fails integrity check. Erase it.
-                 */
-                boot_erase_area(boot_req->br_slot_areas[i], b->area);
-            } else {
-                return i;
-            }
+
+    /* Assume selected image is OK to boot into. */
+    img_ok = 1;
+
+    b = &boot_img[slot];
+    boot_slot_magic(slot, &bit);
+    if (b->hdr.ih_magic == IMAGE_MAGIC_NONE) {
+        img_ok = 0;
+    } else if (!boot_image_bootable(&b->hdr)) {
+        img_ok = 0;
+    } else {
+        rc = boot_image_check(&b->hdr, &b->loc);
+        if (rc != 0) {
+            /* Image fails integrity check. Erase it. */
+            boot_erase_area(boot_req->br_slot_areas[slot], b->area);
+            img_ok = 0;
         }
     }
-    return 0;
-}
 
-static int
-boot_status_sz(void)
-{
-    return sizeof(struct boot_img_trailer) + 32 * sizeof(uint32_t);
+    if (!img_ok) {
+        if (swap_type == BOOT_SWAP_TYPE_NONE) {
+            swap_type = BOOT_SWAP_TYPE_PERM;
+        } else {
+            swap_type = BOOT_SWAP_TYPE_NONE;
+        }
+    }
+
+    return swap_type;
 }
 
 /*
@@ -445,7 +474,7 @@ boot_copy_area(int from_area_idx, int to_area_idx, uint32_t sz)
  *
  * @param area_idx            The index of first slot to exchange. This area
  *                                  must be part of the first image slot.
- * @param sz                  The number of bytes swap.
+ * @param sz                  The number of bytes to swap.
  *
  * @param end_area            Boolean telling whether this includes this
  *                                  area has last slots.
@@ -471,7 +500,8 @@ boot_swap_areas(int idx, uint32_t sz, int end_area)
             return rc;
         }
 
-        rc = boot_copy_area(area_idx_2, boot_req->br_scratch_area_idx, sz);
+        rc = boot_copy_area(area_idx_2, boot_req->br_scratch_area_idx,
+          end_area ? (sz - boot_status_sz()) : sz);
         if (rc != 0) {
             return rc;
         }
@@ -500,7 +530,8 @@ boot_swap_areas(int idx, uint32_t sz, int end_area)
             return rc;
         }
 
-        rc = boot_copy_area(boot_req->br_scratch_area_idx, area_idx_1, sz);
+        rc = boot_copy_area(boot_req->br_scratch_area_idx, area_idx_1,
+          end_area ? (sz - boot_status_sz()) : sz);
         if (rc != 0) {
             return rc;
         }
@@ -518,8 +549,8 @@ boot_swap_areas(int idx, uint32_t sz, int end_area)
  *
  * @return                      0 on success; nonzero on failure.
  */
-static int
-boot_copy_image(void)
+static void
+boot_copy_image(int swap_type)
 {
     uint32_t sz;
     int i;
@@ -535,9 +566,10 @@ boot_copy_image(void)
         }
         end_area = 0;
     }
-    boot_clear_status();
 
-    return 0;
+    if (swap_type == BOOT_SWAP_TYPE_TEMP) {
+        boot_set_copy_done();
+    }
 }
 
 /**
@@ -553,8 +585,9 @@ boot_copy_image(void)
 int
 boot_go(const struct boot_req *req, struct boot_rsp *rsp)
 {
+    int swap_type;
+    int num_swaps;
     int slot;
-    int rc;
 
     /* Set the global boot request object.  The remainder of the boot process
      * will reference the global.
@@ -564,39 +597,35 @@ boot_go(const struct boot_req *req, struct boot_rsp *rsp)
     /* Attempt to read an image header from each slot. */
     boot_image_info();
 
+    num_swaps = 0;
+    swap_type = boot_swap_type();
+
     /* Read the boot status to determine if an image copy operation was
      * interrupted (i.e., the system was reset before the boot loader could
      * finish its task last time).
      */
-    if (boot_read_status(&boot_state)) {
-        /* We are resuming an interrupted image copy. */
-        rc = boot_copy_image();
-        if (rc != 0) {
-            /* We failed to put the images back together; there is really no
-             * solution here.
-             */
-            return rc;
-        }
-    }
-
-    /*
-     * Check if we should initiate copy, or revert back to earlier image.
-     *
-     */
-    slot = boot_select_image_slot();
-    if (slot == -1) {
-        return BOOT_EBADIMAGE;
-    }
-
-    if (slot) {
+    boot_read_status(&boot_state);
+    //if (boot_read_status(&boot_state)) {
+        ///* We are resuming an interrupted image copy. */
+        //boot_copy_image(swap_type);
+        //swap_type = BOOT_SWAP_TYPE_NONE;
+        //num_swaps++;
+    //}
+
+    /* Check if we should initiate copy, or revert back to earlier image. */
+    //swap_type = boot_validate_state(swap_type);
+    swap_type = boot_validate_state(swap_type);
+
+    if (swap_type == BOOT_SWAP_TYPE_NONE) {
         boot_state.idx = 0;
         boot_state.state = 0;
-        rc = boot_copy_image();
-        if (rc) {
-            return rc;
-        }
+    } else {
+        num_swaps++;
+        boot_copy_image(swap_type);
     }
 
+    slot = num_swaps % 2;
+
     /* Always boot from the primary slot. */
     rsp->br_flash_id = boot_img[0].loc.bil_flash_id;
     rsp->br_image_addr = boot_img[0].loc.bil_address;

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/4b1a5c1d/boot/bootutil/test/src/boot_test.c
----------------------------------------------------------------------
diff --git a/boot/bootutil/test/src/boot_test.c b/boot/bootutil/test/src/boot_test.c
index 82ea15f..8bb0015 100644
--- a/boot/bootutil/test/src/boot_test.c
+++ b/boot/bootutil/test/src/boot_test.c
@@ -63,6 +63,9 @@ static struct {
     { 0, 0x80000 },
 };
 
+/** Three areas per image slot */
+#define BOOT_TEST_IMAGE_NUM_AREAS  3
+
 #define BOOT_TEST_AREA_IDX_SCRATCH 6
 
 static uint8_t
@@ -127,11 +130,46 @@ boot_test_util_copy_area(int from_area_idx, int to_area_idx)
     free(buf);
 }
 
+static uint32_t
+boot_test_util_area_write_size(int dst_idx, uint32_t off, uint32_t size)
+{
+    const struct flash_area *desc;
+    int64_t diff;
+    uint32_t trailer_start;
+    int i;
+
+    for (i = 0;
+         i < sizeof boot_test_slot_areas / sizeof boot_test_slot_areas[0];
+         i++) {
+
+        /* Don't include trailer in copy. */
+        if (dst_idx ==
+            boot_test_slot_areas[i] + BOOT_TEST_IMAGE_NUM_AREAS - 1) {
+
+            desc = boot_test_area_descs + dst_idx;
+            trailer_start = desc->fa_size - boot_status_sz();
+            diff = off + size - trailer_start;
+            if (diff > 0) {
+                if (diff > size) {
+                    size = 0;
+                } else {
+                    size -= diff;
+                }
+            }
+
+            break;
+        }
+    }
+
+    return size;
+}
+
 static void
 boot_test_util_swap_areas(int area_idx1, int area_idx2)
 {
     const struct flash_area *area_desc1;
     const struct flash_area *area_desc2;
+    uint32_t size;
     void *buf1;
     void *buf2;
     int rc;
@@ -159,10 +197,12 @@ boot_test_util_swap_areas(int area_idx1, int area_idx2)
     rc = flash_area_erase(area_desc2, 0, area_desc2->fa_size);
     TEST_ASSERT(rc == 0);
 
-    rc = flash_area_write(area_desc1, 0, buf2, area_desc1->fa_size);
+    size = boot_test_util_area_write_size(area_idx1, 0, area_desc1->fa_size);
+    rc = flash_area_write(area_desc1, 0, buf2, size);
     TEST_ASSERT(rc == 0);
 
-    rc = flash_area_write(area_desc2, 0, buf1, area_desc2->fa_size);
+    size = boot_test_util_area_write_size(area_idx2, 0, area_desc2->fa_size);
+    rc = flash_area_write(area_desc2, 0, buf1, size);
     TEST_ASSERT(rc == 0);
 
     free(buf1);
@@ -339,7 +379,7 @@ boot_test_util_verify_status_clear(void)
     rc = flash_area_read(fap, fap->fa_size - sizeof(bit), &bit, sizeof(bit));
     TEST_ASSERT(rc == 0);
 
-    TEST_ASSERT(bit.bit_copy_start != BOOT_IMG_MAGIC ||
+    TEST_ASSERT(bit.bit_copy_start != BOOT_MAGIC_SWAP_TEMP ||
       bit.bit_copy_done != 0xff);
 }
 
@@ -376,11 +416,69 @@ boot_test_util_verify_flash(const struct image_header *hdr0, int orig_slot_0,
     }
 }
 
-TEST_CASE(boot_test_nv_ns_10)
+static void
+boot_test_util_verify_all(const struct boot_req *req, int expected_swap_type,
+                          const struct image_header *hdr0,
+                          const struct image_header *hdr1)
 {
+    const struct image_header *slot0hdr;
+    const struct image_header *slot1hdr;
     struct boot_rsp rsp;
+    int orig_slot_0;
+    int orig_slot_1;
+    int num_swaps;
     int rc;
+    int i;
+
+    num_swaps = 0;
+    for (i = 0; i < 3; i++) {
+        rc = boot_go(req, &rsp);
+        TEST_ASSERT_FATAL(rc == 0);
+
+        if (expected_swap_type != BOOT_SWAP_TYPE_NONE) {
+            num_swaps++;
+        }
+
+        if (num_swaps % 2 == 0) {
+            slot0hdr = hdr0;
+            slot1hdr = hdr1;
+            orig_slot_0 = 0;
+            orig_slot_1 = 1;
+        } else {
+            slot0hdr = hdr1;
+            slot1hdr = hdr0;
+            orig_slot_0 = 1;
+            orig_slot_1 = 0;
+        }
+
+        TEST_ASSERT(memcmp(rsp.br_hdr, slot0hdr, sizeof *slot0hdr) == 0);
+        TEST_ASSERT(rsp.br_flash_id == boot_test_img_addrs[0].flash_id);
+        TEST_ASSERT(rsp.br_image_addr == boot_test_img_addrs[0].address);
+
+        boot_test_util_verify_flash(slot0hdr, orig_slot_0,
+                                    slot1hdr, orig_slot_1);
+        boot_test_util_verify_status_clear();
+
+        if (expected_swap_type != BOOT_SWAP_TYPE_NONE) {
+            switch (expected_swap_type) {
+            case BOOT_SWAP_TYPE_TEMP:
+                expected_swap_type = BOOT_SWAP_TYPE_PERM;
+                break;
+
+            case BOOT_SWAP_TYPE_PERM:
+                expected_swap_type = BOOT_SWAP_TYPE_NONE;
+                break;
 
+            default:
+                TEST_ASSERT_FATAL(0);
+                break;
+            }
+        }
+    }
+}
+
+TEST_CASE(boot_test_nv_ns_10)
+{
     struct image_header hdr = {
         .ih_magic = IMAGE_MAGIC,
         .ih_tlv_size = 4 + 32,
@@ -402,15 +500,7 @@ TEST_CASE(boot_test_nv_ns_10)
     boot_test_util_write_image(&hdr, 0);
     boot_test_util_write_hash(&hdr, 0);
 
-    rc = boot_go(&req, &rsp);
-    TEST_ASSERT(rc == 0);
-
-    TEST_ASSERT(memcmp(rsp.br_hdr, &hdr, sizeof hdr) == 0);
-    TEST_ASSERT(rsp.br_flash_id == boot_test_img_addrs[0].flash_id);
-    TEST_ASSERT(rsp.br_image_addr == boot_test_img_addrs[0].address);
-
-    boot_test_util_verify_flash(&hdr, 0, NULL, 0xff);
-    boot_test_util_verify_status_clear();
+    boot_test_util_verify_all(&req, BOOT_SWAP_TYPE_NONE, &hdr, NULL);
 }
 
 TEST_CASE(boot_test_nv_ns_01)
@@ -815,8 +905,7 @@ TEST_CASE(boot_test_nv_bs_11)
     boot_test_util_write_image(&hdr1, 1);
     boot_test_util_write_hash(&hdr1, 1);
     rc = boot_vect_write_test(1);
-    boot_test_util_copy_area(5,
-      BOOT_TEST_AREA_IDX_SCRATCH);
+    boot_test_util_copy_area(5, BOOT_TEST_AREA_IDX_SCRATCH);
 
     boot_req_set(&req);
     status.idx = 0;
@@ -840,7 +929,6 @@ TEST_CASE(boot_test_nv_bs_11)
 TEST_CASE(boot_test_nv_bs_11_2areas)
 {
     struct boot_status status;
-    struct boot_rsp rsp;
     int rc;
 
     struct image_header hdr0 = {
@@ -874,35 +962,25 @@ TEST_CASE(boot_test_nv_bs_11_2areas)
     boot_test_util_write_hash(&hdr0, 0);
     boot_test_util_write_image(&hdr1, 1);
     boot_test_util_write_hash(&hdr1, 1);
-    rc = boot_vect_write_test(1);
 
     boot_test_util_swap_areas(2, 5);
 
+    rc = boot_vect_write_test(1);
+    TEST_ASSERT_FATAL(rc == 0);
+
     status.idx = 1;
     status.elem_sz = 1;
     status.state = 0;
 
     rc = boot_write_status(&status);
-    TEST_ASSERT(rc == 0);
-
-    rc = boot_go(&req, &rsp);
-    TEST_ASSERT(rc == 0);
+    TEST_ASSERT_FATAL(rc == 0);
 
-    TEST_ASSERT(memcmp(rsp.br_hdr, &hdr1, sizeof hdr1) == 0);
-    TEST_ASSERT(rsp.br_flash_id == boot_test_img_addrs[0].flash_id);
-    TEST_ASSERT(rsp.br_image_addr == boot_test_img_addrs[0].address);
-
-    boot_test_util_verify_flash(&hdr1, 1, &hdr0, 0);
-    boot_test_util_verify_status_clear();
+    boot_test_util_verify_all(&req, BOOT_SWAP_TYPE_TEMP, &hdr0, &hdr1);
 }
 
 TEST_CASE(boot_test_vb_ns_11)
 {
-    const struct flash_area *fap;
-    struct boot_img_trailer bit;
-    struct boot_rsp rsp;
     int rc;
-    int i;
 
     struct image_header hdr0 = {
         .ih_magic = IMAGE_MAGIC,
@@ -936,49 +1014,14 @@ TEST_CASE(boot_test_vb_ns_11)
     boot_test_util_write_image(&hdr1, 1);
     boot_test_util_write_hash(&hdr1, 1);
 
-    rc = flash_area_open(FLASH_AREA_IMAGE_0, &fap);
-    TEST_ASSERT(rc == 0);
-
-    memset(&bit, 0xff, sizeof(bit));
-    bit.bit_copy_start = BOOT_IMG_MAGIC;
-    bit.bit_copy_done = 0;
-    bit.bit_img_ok = 1;
-
-    rc = flash_area_write(fap, fap->fa_size - sizeof(bit), &bit, sizeof(bit));
-    TEST_ASSERT(rc == 0);
-
     rc = boot_vect_write_test(1);
-    TEST_ASSERT(rc == 0);
-
-    /* First boot should use the test image. */
-    rc = boot_go(&req, &rsp);
-    TEST_ASSERT(rc == 0);
-
-    TEST_ASSERT(memcmp(rsp.br_hdr, &hdr1, sizeof hdr1) == 0);
-    TEST_ASSERT(rsp.br_flash_id == boot_test_img_addrs[0].flash_id);
-    TEST_ASSERT(rsp.br_image_addr == boot_test_img_addrs[0].address);
-
-    boot_test_util_verify_flash(&hdr1, 1, &hdr0, 0);
-    boot_test_util_verify_status_clear();
-
-    /* Ensure all subsequent boots use the main image. */
-    for (i = 0; i < 10; i++) {
-        rc = boot_go(&req, &rsp);
-        TEST_ASSERT(rc == 0);
+    TEST_ASSERT_FATAL(rc == 0);
 
-        TEST_ASSERT(memcmp(rsp.br_hdr, &hdr0, sizeof hdr0) == 0);
-        TEST_ASSERT(rsp.br_flash_id == boot_test_img_addrs[0].flash_id);
-        TEST_ASSERT(rsp.br_image_addr == boot_test_img_addrs[0].address);
-
-        boot_test_util_verify_flash(&hdr0, 0, &hdr1, 1);
-        boot_test_util_verify_status_clear();
-        boot_vect_write_main();
-    }
+    boot_test_util_verify_all(&req, BOOT_SWAP_TYPE_TEMP, &hdr0, &hdr1);
 }
 
 TEST_CASE(boot_test_no_hash)
 {
-    struct boot_rsp rsp;
     int rc;
 
     struct image_header hdr0 = {
@@ -1012,20 +1055,13 @@ TEST_CASE(boot_test_no_hash)
     boot_test_util_write_image(&hdr1, 1);
 
     rc = boot_vect_write_test(1);
-    TEST_ASSERT(rc == 0);
+    TEST_ASSERT_FATAL(rc == 0);
 
-    rc = boot_go(&req, &rsp);
-    TEST_ASSERT(rc == 0);
-
-    TEST_ASSERT(memcmp(rsp.br_hdr, &hdr0, sizeof hdr0) == 0);
-
-    boot_test_util_verify_flash(&hdr0, 0, NULL, 0xff);
-    boot_test_util_verify_status_clear();
+    boot_test_util_verify_all(&req, BOOT_SWAP_TYPE_NONE, &hdr0, NULL);
 }
 
 TEST_CASE(boot_test_no_flag_has_hash)
 {
-    struct boot_rsp rsp;
     int rc;
 
     struct image_header hdr0 = {
@@ -1062,18 +1098,11 @@ TEST_CASE(boot_test_no_flag_has_hash)
     rc = boot_vect_write_test(1);
     TEST_ASSERT(rc == 0);
 
-    rc = boot_go(&req, &rsp);
-    TEST_ASSERT(rc == 0);
-
-    TEST_ASSERT(memcmp(rsp.br_hdr, &hdr0, sizeof hdr0) == 0);
-
-    boot_test_util_verify_flash(&hdr0, 0, NULL, 0xff);
-    boot_test_util_verify_status_clear();
+    boot_test_util_verify_all(&req, BOOT_SWAP_TYPE_NONE, &hdr0, NULL);
 }
 
 TEST_CASE(boot_test_invalid_hash)
 {
-    struct boot_rsp rsp;
     int rc;
 
     struct image_header hdr0 = {
@@ -1117,13 +1146,7 @@ TEST_CASE(boot_test_invalid_hash)
     rc = boot_vect_write_test(1);
     TEST_ASSERT(rc == 0);
 
-    rc = boot_go(&req, &rsp);
-    TEST_ASSERT(rc == 0);
-
-    TEST_ASSERT(memcmp(rsp.br_hdr, &hdr0, sizeof hdr0) == 0);
-
-    boot_test_util_verify_flash(&hdr0, 0, NULL, 0xff);
-    boot_test_util_verify_status_clear();
+    boot_test_util_verify_all(&req, BOOT_SWAP_TYPE_NONE, &hdr0, NULL);
 }
 
 TEST_SUITE(boot_test_main)

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/4b1a5c1d/mgmt/imgmgr/src/imgmgr_state.c
----------------------------------------------------------------------
diff --git a/mgmt/imgmgr/src/imgmgr_state.c b/mgmt/imgmgr/src/imgmgr_state.c
index 3a6efdd..ce61e32 100644
--- a/mgmt/imgmgr/src/imgmgr_state.c
+++ b/mgmt/imgmgr/src/imgmgr_state.c
@@ -47,13 +47,27 @@ imgmgr_state_flags(int query_slot)
     /* Determine if this is is pending or confirmed (only applicable for
      * unified images and loaders.
      */
-    rc = boot_vect_read_test(&slot);
-    if (rc == 0 && slot == query_slot) {
-        flags |= IMGMGR_STATE_F_PENDING;
-    }
-    rc = boot_vect_read_main(&slot);
-    if (rc == 0 && slot == query_slot) {
-        flags |= IMGMGR_STATE_F_CONFIRMED;
+    swap_type = boot_swap_type();
+    switch (swap_type) {
+    case BOOT_SWAP_TYPE_NONE:
+        if (query_slot == 0) {
+            flags |= IMGMGR_STATE_F_CONFIRMED;
+            flags |= IMGMGR_STATE_F_ACTIVE;
+        }
+        break;
+
+    case BOOT_SWAP_TYPE_TEMP:
+        if (query_slot == 1) {
+            flags |= IMGMGR_STATE_F_PENDING;
+        }
+        break;
+    case BOOT_SWAP_TYPE_PERM:
+        if (query_slot == 0) {
+            flags |= IMGMGR_STATE_F_ACTIVE;
+        } else if (query_slot == 1) {
+            flags |= IMGMGR_STATE_F_CONFIRMED;
+        }
+        break;
     }
 
     /* Slot 0 is always active.  Slot 1 is also active if a split app is


[2/2] incubator-mynewt-core git commit: bootutil - Add unit tests for image revert.

Posted by cc...@apache.org.
bootutil - Add unit tests for image revert.


Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/commit/3758239d
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/3758239d
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/3758239d

Branch: refs/heads/develop
Commit: 3758239dba41f5dae47e481ef82b4f95edb59cf2
Parents: 4b1a5c1
Author: Christopher Collins <cc...@apache.org>
Authored: Fri Oct 14 13:40:00 2016 -0700
Committer: Christopher Collins <cc...@apache.org>
Committed: Fri Oct 14 16:39:48 2016 -0700

----------------------------------------------------------------------
 boot/bootutil/include/bootutil/bootutil_misc.h |   7 +-
 boot/bootutil/src/bootutil_misc.c              |  85 ++-----
 boot/bootutil/src/bootutil_priv.h              |   4 -
 boot/bootutil/src/loader.c                     |  34 ---
 boot/bootutil/test/src/boot_test.c             | 237 ++++++++++----------
 mgmt/imgmgr/src/imgmgr_state.c                 |   3 +-
 6 files changed, 141 insertions(+), 229 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/3758239d/boot/bootutil/include/bootutil/bootutil_misc.h
----------------------------------------------------------------------
diff --git a/boot/bootutil/include/bootutil/bootutil_misc.h b/boot/bootutil/include/bootutil/bootutil_misc.h
index 1efe864..87b0b28 100644
--- a/boot/bootutil/include/bootutil/bootutil_misc.h
+++ b/boot/bootutil/include/bootutil/bootutil_misc.h
@@ -26,8 +26,11 @@
 extern "C" {
 #endif
 
-int boot_vect_read_test(int *slot);
-int boot_vect_read_main(int *slot);
+#define BOOT_SWAP_TYPE_NONE     0
+#define BOOT_SWAP_TYPE_TEMP     1
+#define BOOT_SWAP_TYPE_PERM     2
+
+int boot_swap_type(void);
 int boot_vect_write_test(int slot);
 int boot_vect_write_main(void);
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/3758239d/boot/bootutil/src/bootutil_misc.c
----------------------------------------------------------------------
diff --git a/boot/bootutil/src/bootutil_misc.c b/boot/bootutil/src/bootutil_misc.c
index bb7b2a3..0606215 100644
--- a/boot/bootutil/src/bootutil_misc.c
+++ b/boot/bootutil/src/bootutil_misc.c
@@ -65,11 +65,8 @@ boot_status_sz(void)
     return sizeof(struct boot_img_trailer) + 32 * sizeof(uint32_t);
 }
 
-/*
- * Read the image trailer from a given slot.
- */
-static int
-boot_vect_read_img_trailer(int slot, struct boot_img_trailer *bit)
+int
+boot_swap_type(void)
 {
     struct boot_img_trailer bit0;
     struct boot_img_trailer bit1;
@@ -80,77 +77,25 @@ boot_vect_read_img_trailer(int slot, struct boot_img_trailer *bit)
     if (bit0.bit_copy_start == BOOT_MAGIC_SWAP_NONE &&
         bit1.bit_copy_start == BOOT_MAGIC_SWAP_NONE) {
 
-    area_id = flash_area_id_from_image_slot(slot);
-    rc = flash_area_open(area_id, &fap);
-    if (rc) {
-        return rc;
+        return BOOT_SWAP_TYPE_NONE;
     }
-    off = fap->fa_size - sizeof(struct boot_img_trailer);
-    rc = flash_area_read(fap, off, bit, sizeof(*bit));
-    flash_area_close(fap);
-
-    return rc;
-}
 
-/**
- * Retrieves from the slot number of the test image (i.e.,
- * the image that has not been proven stable, and which will only run once).
- *
- * @param slot              On success, the slot number of image to boot.
- *
- * @return                  0 if a test image was found;
- *                          nonzero if there is no test image.
- */
-int
-boot_vect_read_test(int *slot)
-{
-    struct boot_img_trailer bit;
-    int i;
-    int rc;
+    if (bit1.bit_copy_start == BOOT_MAGIC_SWAP_TEMP) {
+        return BOOT_SWAP_TYPE_TEMP;
+    }
 
-    for (i = 0; i < 2; i++) {
-        if (i == boot_current_slot) {
-            continue;
-        }
-        rc = boot_vect_read_img_trailer(i, &bit);
-        if (rc) {
-            continue;
-        }
-        if (bit.bit_copy_start == BOOT_MAGIC_SWAP_TEMP) {
-            *slot = i;
-            return 0;
+    if (bit0.bit_copy_start == BOOT_MAGIC_SWAP_PERM) {
+        if (bit0.bit_img_ok != 0xff) {
+            return BOOT_SWAP_TYPE_NONE;
+        } else {
+            return BOOT_SWAP_TYPE_PERM;
         }
     }
-    return -1;
-}
-
-/**
- * Retrieves from the slot number of the main image. If this is
- * different from test image slot, next restart will revert to main.
- *
- * @param out_ver           On success, the main version gets written here.
- *
- * @return                  0 on success; nonzero on failure.
- */
-int
-boot_vect_read_main(int *slot)
-{
-    int rc;
-    struct boot_img_trailer bit;
-
-    rc = boot_vect_read_img_trailer(0, &bit);
-    assert(rc == 0);
 
-    if (bit.bit_copy_start != BOOT_MAGIC_SWAP_TEMP || bit.bit_img_ok != 0xff) {
-        /*
-         * If there never was copy that took place, or if the current
-         * image has been marked good, we'll keep booting it.
-         */
-        *slot = 0;
-    } else {
-        *slot = 1;
-    }
-    return 0;
+    /* This should never happen. */
+    /* XXX: Remove this assert. */
+    assert(0);
+    return BOOT_SWAP_TYPE_NONE;
 }
 
 /**

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/3758239d/boot/bootutil/src/bootutil_priv.h
----------------------------------------------------------------------
diff --git a/boot/bootutil/src/bootutil_priv.h b/boot/bootutil/src/bootutil_priv.h
index 7112c60..73202f7 100644
--- a/boot/bootutil/src/bootutil_priv.h
+++ b/boot/bootutil/src/bootutil_priv.h
@@ -52,10 +52,6 @@ struct boot_status {
     uint8_t state;
 };
 
-#define BOOT_SWAP_TYPE_NONE     0
-#define BOOT_SWAP_TYPE_TEMP     1
-#define BOOT_SWAP_TYPE_PERM     2
-
 /*
  * End-of-image slot data structure.
  */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/3758239d/boot/bootutil/src/loader.c
----------------------------------------------------------------------
diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c
index 7c07a9c..f7d159e 100644
--- a/boot/bootutil/src/loader.c
+++ b/boot/bootutil/src/loader.c
@@ -185,39 +185,6 @@ boot_scratch_magic(struct boot_img_trailer *bit)
     hal_flash_read(flash_id, off, bit, sizeof(*bit));
 }
 
-static int
-boot_swap_type(void)
-{
-    struct boot_img_trailer bit0;
-    struct boot_img_trailer bit1;
-
-    boot_slot_magic(0, &bit0);
-    boot_slot_magic(1, &bit1);
-
-    if (bit0.bit_copy_start == BOOT_MAGIC_SWAP_NONE &&
-        bit1.bit_copy_start == BOOT_MAGIC_SWAP_NONE) {
-
-        return BOOT_SWAP_TYPE_NONE;
-    }
-
-    if (bit1.bit_copy_start == BOOT_MAGIC_SWAP_TEMP) {
-        return BOOT_SWAP_TYPE_TEMP;
-    }
-
-    if (bit0.bit_copy_start == BOOT_MAGIC_SWAP_PERM) {
-        if (bit0.bit_img_ok != 0xff) {
-            return BOOT_SWAP_TYPE_NONE;
-        } else {
-            return BOOT_SWAP_TYPE_PERM;
-        }
-    }
-
-    /* This should never happen. */
-    /* XXX: Remove this assert. */
-    assert(0);
-    return BOOT_SWAP_TYPE_NONE;
-}
-
 /*
  * Gather info about image in a given slot.
  */
@@ -613,7 +580,6 @@ boot_go(const struct boot_req *req, struct boot_rsp *rsp)
     //}
 
     /* Check if we should initiate copy, or revert back to earlier image. */
-    //swap_type = boot_validate_state(swap_type);
     swap_type = boot_validate_state(swap_type);
 
     if (swap_type == BOOT_SWAP_TYPE_NONE) {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/3758239d/boot/bootutil/test/src/boot_test.c
----------------------------------------------------------------------
diff --git a/boot/bootutil/test/src/boot_test.c b/boot/bootutil/test/src/boot_test.c
index 8bb0015..cf69dcd 100644
--- a/boot/bootutil/test/src/boot_test.c
+++ b/boot/bootutil/test/src/boot_test.c
@@ -430,6 +430,9 @@ boot_test_util_verify_all(const struct boot_req *req, int expected_swap_type,
     int rc;
     int i;
 
+    TEST_ASSERT_FATAL(req != NULL);
+    TEST_ASSERT_FATAL(hdr0 != NULL || hdr1 != NULL);
+
     num_swaps = 0;
     for (i = 0; i < 3; i++) {
         rc = boot_go(req, &rsp);
@@ -440,13 +443,23 @@ boot_test_util_verify_all(const struct boot_req *req, int expected_swap_type,
         }
 
         if (num_swaps % 2 == 0) {
-            slot0hdr = hdr0;
-            slot1hdr = hdr1;
+            if (hdr0 != NULL) {
+                slot0hdr = hdr0;
+                slot1hdr = hdr1;
+            } else {
+                slot0hdr = hdr1;
+                slot1hdr = hdr0;
+            }
             orig_slot_0 = 0;
             orig_slot_1 = 1;
         } else {
-            slot0hdr = hdr1;
-            slot1hdr = hdr0;
+            if (hdr1 != NULL) {
+                slot0hdr = hdr1;
+                slot1hdr = hdr0;
+            } else {
+                slot0hdr = hdr0;
+                slot1hdr = hdr1;
+            }
             orig_slot_0 = 1;
             orig_slot_1 = 0;
         }
@@ -505,10 +518,6 @@ TEST_CASE(boot_test_nv_ns_10)
 
 TEST_CASE(boot_test_nv_ns_01)
 {
-    struct boot_rsp rsp;
-    int rc;
-
-
     struct image_header hdr = {
         .ih_magic = IMAGE_MAGIC,
         .ih_tlv_size = 4 + 32,
@@ -530,23 +539,11 @@ TEST_CASE(boot_test_nv_ns_01)
     boot_test_util_write_image(&hdr, 1);
     boot_test_util_write_hash(&hdr, 1);
 
-    boot_vect_write_test(1);
-    rc = boot_go(&req, &rsp);
-    TEST_ASSERT(rc == 0);
-
-    TEST_ASSERT(memcmp(rsp.br_hdr, &hdr, sizeof hdr) == 0);
-    TEST_ASSERT(rsp.br_flash_id == boot_test_img_addrs[0].flash_id);
-    TEST_ASSERT(rsp.br_image_addr == boot_test_img_addrs[0].address);
-
-    boot_test_util_verify_flash(&hdr, 1, NULL, 0xff);
-    boot_test_util_verify_status_clear();
+    boot_test_util_verify_all(&req, BOOT_SWAP_TYPE_PERM, NULL, &hdr);
 }
 
 TEST_CASE(boot_test_nv_ns_11)
 {
-    struct boot_rsp rsp;
-    int rc;
-
     struct image_header hdr0 = {
         .ih_magic = IMAGE_MAGIC,
         .ih_tlv_size = 4 + 32,
@@ -579,23 +576,11 @@ TEST_CASE(boot_test_nv_ns_11)
     boot_test_util_write_image(&hdr1, 1);
     boot_test_util_write_hash(&hdr1, 1);
 
-    rc = boot_go(&req, &rsp);
-    TEST_ASSERT(rc == 0);
-
-    TEST_ASSERT(memcmp(rsp.br_hdr, &hdr0, sizeof hdr0) == 0);
-    TEST_ASSERT(rsp.br_flash_id == boot_test_img_addrs[0].flash_id);
-    TEST_ASSERT(rsp.br_image_addr == boot_test_img_addrs[0].address);
-
-    boot_test_util_verify_flash(&hdr0, 0, &hdr1, 1);
-    boot_test_util_verify_status_clear();
+    boot_test_util_verify_all(&req, BOOT_SWAP_TYPE_NONE, &hdr0, &hdr1);
 }
 
 TEST_CASE(boot_test_vm_ns_10)
 {
-    struct boot_rsp rsp;
-    int rc;
-
-
     struct image_header hdr = {
         .ih_magic = IMAGE_MAGIC,
         .ih_tlv_size = 4 + 32,
@@ -617,20 +602,11 @@ TEST_CASE(boot_test_vm_ns_10)
     boot_test_util_write_image(&hdr, 0);
     boot_test_util_write_hash(&hdr, 0);
 
-    rc = boot_go(&req, &rsp);
-    TEST_ASSERT(rc == 0);
-
-    TEST_ASSERT(memcmp(rsp.br_hdr, &hdr, sizeof hdr) == 0);
-    TEST_ASSERT(rsp.br_flash_id == boot_test_img_addrs[0].flash_id);
-    TEST_ASSERT(rsp.br_image_addr == boot_test_img_addrs[0].address);
-
-    boot_test_util_verify_flash(&hdr, 0, NULL, 0xff);
-    boot_test_util_verify_status_clear();
+    boot_test_util_verify_all(&req, BOOT_SWAP_TYPE_NONE, &hdr, NULL);
 }
 
 TEST_CASE(boot_test_vm_ns_01)
 {
-    struct boot_rsp rsp;
     int rc;
 
     struct image_header hdr = {
@@ -657,22 +633,11 @@ TEST_CASE(boot_test_vm_ns_01)
     rc = boot_vect_write_test(1);
     TEST_ASSERT(rc == 0);
 
-    rc = boot_go(&req, &rsp);
-    TEST_ASSERT(rc == 0);
-
-    TEST_ASSERT(memcmp(rsp.br_hdr, &hdr, sizeof hdr) == 0);
-    TEST_ASSERT(rsp.br_flash_id == boot_test_img_addrs[0].flash_id);
-    TEST_ASSERT(rsp.br_image_addr == boot_test_img_addrs[0].address);
-
-    boot_test_util_verify_flash(&hdr, 1, NULL, 0xff);
-    boot_test_util_verify_status_clear();
+    boot_test_util_verify_all(&req, BOOT_SWAP_TYPE_PERM, NULL, &hdr);
 }
 
 TEST_CASE(boot_test_vm_ns_11_a)
 {
-    struct boot_rsp rsp;
-    int rc;
-
     struct image_header hdr0 = {
         .ih_magic = IMAGE_MAGIC,
         .ih_tlv_size = 4 + 32,
@@ -705,20 +670,11 @@ TEST_CASE(boot_test_vm_ns_11_a)
     boot_test_util_write_image(&hdr1, 1);
     boot_test_util_write_hash(&hdr1, 1);
 
-    rc = boot_go(&req, &rsp);
-    TEST_ASSERT(rc == 0);
-
-    TEST_ASSERT(memcmp(rsp.br_hdr, &hdr0, sizeof hdr0) == 0);
-    TEST_ASSERT(rsp.br_flash_id == boot_test_img_addrs[0].flash_id);
-    TEST_ASSERT(rsp.br_image_addr == boot_test_img_addrs[0].address);
-
-    boot_test_util_verify_flash(&hdr0, 0, &hdr1, 1);
-    boot_test_util_verify_status_clear();
+    boot_test_util_verify_all(&req, BOOT_SWAP_TYPE_NONE, &hdr0, &hdr1);
 }
 
 TEST_CASE(boot_test_vm_ns_11_b)
 {
-    struct boot_rsp rsp;
     int rc;
 
     struct image_header hdr0 = {
@@ -756,20 +712,11 @@ TEST_CASE(boot_test_vm_ns_11_b)
     rc = boot_vect_write_test(1);
     TEST_ASSERT(rc == 0);
 
-    rc = boot_go(&req, &rsp);
-    TEST_ASSERT(rc == 0);
-
-    TEST_ASSERT(memcmp(rsp.br_hdr, &hdr1, sizeof hdr1) == 0);
-    TEST_ASSERT(rsp.br_flash_id == boot_test_img_addrs[0].flash_id);
-    TEST_ASSERT(rsp.br_image_addr == boot_test_img_addrs[0].address);
-
-    boot_test_util_verify_flash(&hdr1, 1, &hdr0, 0);
-    boot_test_util_verify_status_clear();
+    boot_test_util_verify_all(&req, BOOT_SWAP_TYPE_TEMP, &hdr0, &hdr1);
 }
 
 TEST_CASE(boot_test_vm_ns_11_2areas)
 {
-    struct boot_rsp rsp;
     int rc;
 
     struct image_header hdr0 = {
@@ -807,23 +754,11 @@ TEST_CASE(boot_test_vm_ns_11_2areas)
     rc = boot_vect_write_test(1);
     TEST_ASSERT(rc == 0);
 
-    rc = boot_go(&req, &rsp);
-    TEST_ASSERT(rc == 0);
-
-    TEST_ASSERT(memcmp(rsp.br_hdr, &hdr1, sizeof hdr1) == 0);
-    TEST_ASSERT(rsp.br_flash_id == boot_test_img_addrs[0].flash_id);
-    TEST_ASSERT(rsp.br_image_addr == boot_test_img_addrs[0].address);
-
-    boot_test_util_verify_flash(&hdr1, 1, &hdr0, 0);
-    boot_test_util_verify_status_clear();
+    boot_test_util_verify_all(&req, BOOT_SWAP_TYPE_TEMP, &hdr0, &hdr1);
 }
 
 TEST_CASE(boot_test_nv_bs_10)
 {
-    struct boot_status status;
-    struct boot_rsp rsp;
-    int rc;
-
     struct image_header hdr = {
         .ih_magic = IMAGE_MAGIC,
         .ih_tlv_size = 4 + 32,
@@ -846,31 +781,13 @@ TEST_CASE(boot_test_nv_bs_10)
     boot_test_util_write_hash(&hdr, 0);
     boot_test_util_swap_areas(boot_test_slot_areas[1],
       BOOT_TEST_AREA_IDX_SCRATCH);
-#if 0
-    status.length = hdr.ih_hdr_size + hdr.ih_img_size + hdr.ih_tlv_size;
-    status.state = 1;
-
-    rc = boot_write_status(&status);
-    TEST_ASSERT(rc == 0);
-    conf_load();
-#else
-    (void)status;
-#endif
-    rc = boot_go(&req, &rsp);
-    TEST_ASSERT(rc == 0);
 
-    TEST_ASSERT(memcmp(rsp.br_hdr, &hdr, sizeof hdr) == 0);
-    TEST_ASSERT(rsp.br_flash_id == boot_test_img_addrs[0].flash_id);
-    TEST_ASSERT(rsp.br_image_addr == boot_test_img_addrs[0].address);
-
-    boot_test_util_verify_flash(&hdr, 0, NULL, 0xff);
-    boot_test_util_verify_status_clear();
+    boot_test_util_verify_all(&req, BOOT_SWAP_TYPE_NONE, &hdr, NULL);
 }
 
 TEST_CASE(boot_test_nv_bs_11)
 {
     struct boot_status status;
-    struct boot_rsp rsp;
     int rc;
 
     struct image_header hdr0 = {
@@ -915,15 +832,7 @@ TEST_CASE(boot_test_nv_bs_11)
     rc = boot_write_status(&status);
     TEST_ASSERT(rc == 0);
 
-    rc = boot_go(&req, &rsp);
-    TEST_ASSERT(rc == 0);
-
-    TEST_ASSERT(memcmp(rsp.br_hdr, &hdr1, sizeof hdr1) == 0);
-    TEST_ASSERT(rsp.br_flash_id == boot_test_img_addrs[0].flash_id);
-    TEST_ASSERT(rsp.br_image_addr == boot_test_img_addrs[0].address);
-
-    boot_test_util_verify_flash(&hdr1, 1, &hdr0, 0);
-    boot_test_util_verify_status_clear();
+    boot_test_util_verify_all(&req, BOOT_SWAP_TYPE_TEMP, &hdr0, &hdr1);
 }
 
 TEST_CASE(boot_test_nv_bs_11_2areas)
@@ -1149,6 +1058,98 @@ TEST_CASE(boot_test_invalid_hash)
     boot_test_util_verify_all(&req, BOOT_SWAP_TYPE_NONE, &hdr0, NULL);
 }
 
+TEST_CASE(boot_test_revert)
+{
+    struct image_header hdr0 = {
+        .ih_magic = IMAGE_MAGIC,
+        .ih_tlv_size = 4 + 32,
+        .ih_hdr_size = BOOT_TEST_HEADER_SIZE,
+        .ih_img_size = 5 * 1024,
+        .ih_flags = IMAGE_F_SHA256,
+        .ih_ver = { 0, 5, 21, 432 },
+    };
+
+    struct image_header hdr1 = {
+        .ih_magic = IMAGE_MAGIC,
+        .ih_tlv_size = 4 + 32,
+        .ih_hdr_size = BOOT_TEST_HEADER_SIZE,
+        .ih_img_size = 32 * 1024,
+        .ih_flags = IMAGE_F_SHA256,
+        .ih_ver = { 1, 2, 3, 432 },
+    };
+
+    struct boot_req req = {
+        .br_area_descs = boot_test_area_descs,
+        .br_slot_areas = boot_test_slot_areas,
+        .br_num_image_areas = BOOT_TEST_AREA_IDX_SCRATCH + 1,
+        .br_scratch_area_idx = BOOT_TEST_AREA_IDX_SCRATCH,
+        .br_img_sz = (384 * 1024),
+    };
+
+    boot_test_util_init_flash();
+    boot_test_util_write_image(&hdr0, 0);
+    boot_test_util_write_hash(&hdr0, 0);
+    boot_test_util_write_image(&hdr1, 1);
+    boot_test_util_write_hash(&hdr1, 1);
+
+    /* Indicate that the image in slot 0 is being tested. */
+    boot_set_copy_done();
+
+    boot_test_util_verify_all(&req, BOOT_SWAP_TYPE_PERM, &hdr0, &hdr1);
+}
+
+TEST_CASE(boot_test_revert_continue)
+{
+    struct boot_status status;
+    int rc;
+
+    struct image_header hdr0 = {
+        .ih_magic = IMAGE_MAGIC,
+        .ih_tlv_size = 4 + 32,
+        .ih_hdr_size = BOOT_TEST_HEADER_SIZE,
+        .ih_img_size = 5 * 1024,
+        .ih_flags = IMAGE_F_SHA256,
+        .ih_ver = { 0, 5, 21, 432 },
+    };
+
+    struct image_header hdr1 = {
+        .ih_magic = IMAGE_MAGIC,
+        .ih_tlv_size = 4 + 32,
+        .ih_hdr_size = BOOT_TEST_HEADER_SIZE,
+        .ih_img_size = 32 * 1024,
+        .ih_flags = IMAGE_F_SHA256,
+        .ih_ver = { 1, 2, 3, 432 },
+    };
+
+    struct boot_req req = {
+        .br_area_descs = boot_test_area_descs,
+        .br_slot_areas = boot_test_slot_areas,
+        .br_num_image_areas = BOOT_TEST_AREA_IDX_SCRATCH + 1,
+        .br_scratch_area_idx = BOOT_TEST_AREA_IDX_SCRATCH,
+        .br_img_sz = (384 * 1024),
+    };
+
+    boot_test_util_init_flash();
+    boot_test_util_write_image(&hdr0, 0);
+    boot_test_util_write_hash(&hdr0, 0);
+    boot_test_util_write_image(&hdr1, 1);
+    boot_test_util_write_hash(&hdr1, 1);
+
+    boot_test_util_swap_areas(2, 5);
+
+    /* Indicate that the image in slot 0 is being tested. */
+    boot_set_copy_done();
+
+    status.idx = 1;
+    status.elem_sz = 1;
+    status.state = 0;
+
+    rc = boot_write_status(&status);
+    TEST_ASSERT_FATAL(rc == 0);
+
+    boot_test_util_verify_all(&req, BOOT_SWAP_TYPE_PERM, &hdr0, &hdr1);
+}
+
 TEST_SUITE(boot_test_main)
 {
     boot_test_nv_ns_10();
@@ -1166,6 +1167,8 @@ TEST_SUITE(boot_test_main)
     boot_test_no_hash();
     boot_test_no_flag_has_hash();
     boot_test_invalid_hash();
+    boot_test_revert();
+    boot_test_revert_continue();
 }
 
 int

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/3758239d/mgmt/imgmgr/src/imgmgr_state.c
----------------------------------------------------------------------
diff --git a/mgmt/imgmgr/src/imgmgr_state.c b/mgmt/imgmgr/src/imgmgr_state.c
index ce61e32..3802b69 100644
--- a/mgmt/imgmgr/src/imgmgr_state.c
+++ b/mgmt/imgmgr/src/imgmgr_state.c
@@ -37,8 +37,7 @@ imgmgr_state_flags(int query_slot)
 {
     split_mode_t split_mode;
     uint8_t flags;
-    int slot;
-    int rc;
+    int swap_type;
 
     assert(query_slot == 0 || query_slot == 1);