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 <ccoll...@apache.org> Authored: Fri Oct 14 13:40:00 2016 -0700 Committer: Christopher Collins <ccoll...@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);