Boot loader update 1. Increase copy magic number from 4 bytes to 16. 2. Ensure magic, status, and swap state get written sequentially within a sector. 3. Standardize on the flash_map API (flash_area_open(), etc.). Previously, we were using both the flash map API and direct HAL flash reads. 4. Remove boot request; now boot loader calculates flash information on its own. 5. Remove boot_req and boot_state global variables.
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/f855c453 Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/f855c453 Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/f855c453 Branch: refs/heads/develop Commit: f855c453f9d0e8fe8289f81e200c04bb30ce8304 Parents: dbb7803 Author: Christopher Collins <ccoll...@apache.org> Authored: Wed Oct 19 17:23:37 2016 -0700 Committer: Christopher Collins <ccoll...@apache.org> Committed: Thu Oct 20 19:16:19 2016 -0700 ---------------------------------------------------------------------- apps/boot/src/boot.c | 13 +- boot/boot_serial/src/boot_serial.c | 4 +- boot/bootutil/include/bootutil/bootutil.h | 43 +- boot/bootutil/include/bootutil/image.h | 15 +- boot/bootutil/signed_images.md | 8 +- boot/bootutil/src/bootutil_misc.c | 315 ++++-- boot/bootutil/src/bootutil_priv.h | 55 +- boot/bootutil/src/image_validate.c | 34 +- boot/bootutil/src/loader.c | 962 ++++++++++--------- boot/bootutil/syscfg.yml | 2 - boot/bootutil/test/src/boot_test.h | 3 +- boot/bootutil/test/src/boot_test_utils.c | 67 +- .../test/src/testcases/boot_test_invalid_hash.c | 10 +- .../src/testcases/boot_test_no_flag_has_hash.c | 10 +- .../test/src/testcases/boot_test_no_hash.c | 10 +- .../test/src/testcases/boot_test_nv_bs_10.c | 10 +- .../test/src/testcases/boot_test_nv_bs_11.c | 13 +- .../src/testcases/boot_test_nv_bs_11_2areas.c | 11 +- .../test/src/testcases/boot_test_nv_ns_01.c | 10 +- .../test/src/testcases/boot_test_nv_ns_10.c | 10 +- .../test/src/testcases/boot_test_nv_ns_11.c | 10 +- .../test/src/testcases/boot_test_revert.c | 10 +- .../src/testcases/boot_test_revert_continue.c | 11 +- .../test/src/testcases/boot_test_vb_ns_11.c | 10 +- .../test/src/testcases/boot_test_vm_ns_01.c | 10 +- .../test/src/testcases/boot_test_vm_ns_10.c | 10 +- .../src/testcases/boot_test_vm_ns_11_2areas.c | 10 +- .../test/src/testcases/boot_test_vm_ns_11_a.c | 10 +- .../test/src/testcases/boot_test_vm_ns_11_b.c | 10 +- sys/flash_map/include/flash_map/flash_map.h | 2 +- sys/flash_map/src/flash_map.c | 5 +- 31 files changed, 908 insertions(+), 795 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f855c453/apps/boot/src/boot.c ---------------------------------------------------------------------- diff --git a/apps/boot/src/boot.c b/apps/boot/src/boot.c index 6a25b57..966e453 100755 --- a/apps/boot/src/boot.c +++ b/apps/boot/src/boot.c @@ -50,14 +50,6 @@ static os_stack_t boot_ser_stack[BOOT_SER_STACK_SZ]; int main(void) { - struct flash_area descs[AREA_DESC_MAX]; - /** Areas representing the beginning of image slots. */ - uint8_t img_starts[2]; - struct boot_req req = { - .br_area_descs = descs, - .br_slot_areas = img_starts, - }; - struct boot_rsp rsp; int rc; @@ -68,9 +60,6 @@ main(void) hal_bsp_init(); #endif - rc = boot_build_request(&req, AREA_DESC_MAX); - assert(rc == 0); - #if MYNEWT_VAL(BOOT_SERIAL) /* * Configure a GPIO as input, and compare it against expected value. @@ -84,7 +73,7 @@ main(void) os_start(); } #endif - rc = boot_go(&req, &rsp); + rc = boot_go(&rsp); assert(rc == 0); system_start((void *)(rsp.br_image_addr + rsp.br_hdr->ih_hdr_size)); http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f855c453/boot/boot_serial/src/boot_serial.c ---------------------------------------------------------------------- diff --git a/boot/boot_serial/src/boot_serial.c b/boot/boot_serial/src/boot_serial.c index 564fb41..fdc2d2e 100644 --- a/boot/boot_serial/src/boot_serial.c +++ b/boot/boot_serial/src/boot_serial.c @@ -110,8 +110,8 @@ bs_list(char *buf, int len) flash_area_read(fap, 0, &hdr, sizeof(hdr)); if (hdr.ih_magic == IMAGE_MAGIC && - bootutil_img_validate(&hdr, fap->fa_device_id, fap->fa_off, - tmpbuf, sizeof(tmpbuf), NULL, 0, NULL) == 0) { + bootutil_img_validate(&hdr, fap, tmpbuf, sizeof(tmpbuf), + NULL, 0, NULL) == 0) { good_img = 1; } else { good_img = 0; http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f855c453/boot/bootutil/include/bootutil/bootutil.h ---------------------------------------------------------------------- diff --git a/boot/bootutil/include/bootutil/bootutil.h b/boot/bootutil/include/bootutil/bootutil.h index ebc3441..f75f59c 100644 --- a/boot/bootutil/include/bootutil/bootutil.h +++ b/boot/bootutil/include/bootutil/bootutil.h @@ -26,45 +26,14 @@ extern "C" { #endif -#define BOOT_STATUS_SOURCE_NONE 0 -#define BOOT_STATUS_SOURCE_SCRATCH 1 -#define BOOT_STATUS_SOURCE_SLOT0 2 - -#define BOOT_SWAP_TYPE_NONE 0 -#define BOOT_SWAP_TYPE_TEST 1 -#define BOOT_SWAP_TYPE_REVERT 2 +#define BOOT_SWAP_TYPE_NONE 1 +#define BOOT_SWAP_TYPE_TEST 2 +#define BOOT_SWAP_TYPE_REVERT 3 +#define BOOT_SWAP_TYPE_FAIL 4 struct image_header; struct boot_img_trailer; -/** A request object instructing the boot loader how to proceed. */ -struct boot_req { - /** - * Array of area descriptors indicating the layout of flash(es); must - * be terminated with a 0-length element. - */ - struct flash_area *br_area_descs; - - /** - * Array of indices of elements in the br_area_descs array; indicates which - * areas represent the beginning of an image slot. These are indices - * to br_area_descs array. - */ - uint8_t *br_slot_areas; - - /** - * The number of image areas (i.e., the size of the br_image_areas array). - */ - uint8_t br_num_image_areas; - - /** The area to use as the image scratch area, index is - index to br_area_descs array, of the */ - uint8_t br_scratch_area_idx; - - /** Size of the image slot */ - uint32_t br_img_sz; -}; - /** * A response object provided by the boot loader code; indicates where to jump * to execute the main image. @@ -82,9 +51,7 @@ struct boot_rsp { }; /* you must have pre-allocated all the entries within this structure */ -int boot_build_request(struct boot_req *preq, int area_descriptor_max); - -int boot_go(const struct boot_req *req, struct boot_rsp *rsp); +int boot_go(struct boot_rsp *rsp); int boot_swap_type(void); http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f855c453/boot/bootutil/include/bootutil/image.h ---------------------------------------------------------------------- diff --git a/boot/bootutil/include/bootutil/image.h b/boot/bootutil/include/bootutil/image.h index 67e56e0..6e89da6 100644 --- a/boot/bootutil/include/bootutil/image.h +++ b/boot/bootutil/include/bootutil/image.h @@ -26,6 +26,8 @@ extern "C" { #endif +struct flash_area; + #define IMAGE_MAGIC 0x96f3b83c #define IMAGE_MAGIC_NONE 0xffffffff @@ -77,18 +79,13 @@ struct image_tlv { uint16_t it_len; }; -struct boot_image_location { - uint8_t bil_flash_id; - uint32_t bil_address; -}; - - _Static_assert(sizeof(struct image_header) == IMAGE_HEADER_SIZE, "struct image_header not required size"); -int bootutil_img_validate(struct image_header *hdr, uint8_t flash_id, - uint32_t addr, uint8_t *tmp_buf, uint32_t tmp_buf_sz, - uint8_t *seed, int seed_len, uint8_t *out_hash); +int bootutil_img_validate(struct image_header *hdr, + const struct flash_area *fap, + uint8_t *tmp_buf, uint32_t tmp_buf_sz, + uint8_t *seed, int seed_len, uint8_t *out_hash); #ifdef __cplusplus } http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f855c453/boot/bootutil/signed_images.md ---------------------------------------------------------------------- diff --git a/boot/bootutil/signed_images.md b/boot/bootutil/signed_images.md index 39792ea..64869c1 100644 --- a/boot/bootutil/signed_images.md +++ b/boot/bootutil/signed_images.md @@ -66,8 +66,6 @@ This gets bootutil to turn on image signature validation. pkg.name: libs/mykeys pkg.deps: - libs/bootutil - pkg.features.bootloader: - - IMAGE_KEYS_RSA ## Sample source file This exports the keys. @@ -87,5 +85,11 @@ This exports the keys. ## Building bootloader +Enable the BOOTUTIL_SIGN_RSA syscfg setting in your app or target syscfg.yml +file + + syscfg.vals: + BOOTUTIL_SIGN_RSA: 1 + After you've created the key package, you must include it in the build for bootloader. So modify the pkg.yml for apps/boot to include it. http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f855c453/boot/bootutil/src/bootutil_misc.c ---------------------------------------------------------------------- diff --git a/boot/bootutil/src/bootutil_misc.c b/boot/bootutil/src/bootutil_misc.c index 37bfaa2..a3c3d04 100644 --- a/boot/bootutil/src/bootutil_misc.c +++ b/boot/bootutil/src/bootutil_misc.c @@ -33,10 +33,17 @@ int boot_current_slot; +const uint32_t boot_img_magic[4] = { + 0xf395c277, + 0x7fefd260, + 0x0f505235, + 0x8079b62c, +}; + struct boot_swap_table { /** * For each field, a value of 0 means "any". */ - uint32_t bsw_magic_slot0; - uint32_t bsw_magic_slot1; + uint8_t bsw_magic_slot0; + uint8_t bsw_magic_slot1; uint8_t bsw_image_ok_slot0; uint8_t bsw_swap_type; @@ -50,14 +57,14 @@ static const struct boot_swap_table boot_swap_tables[] = { { /* | slot-0 | slot-1 | *----------+------------+------------| - * magic | 0xffffffff | 0xffffffff | - * image-ok | 0x** | N/A | + * magic | Unset | Unset | + * image-ok | Any | N/A | * ---------+------------+------------' * swap: none | * -----------------------------------' */ - .bsw_magic_slot0 = 0xffffffff, - .bsw_magic_slot1 = 0xffffffff, + .bsw_magic_slot0 = BOOT_MAGIC_UNSET, + .bsw_magic_slot1 = BOOT_MAGIC_UNSET, .bsw_image_ok_slot0 = 0, .bsw_swap_type = BOOT_SWAP_TYPE_NONE, }, @@ -65,14 +72,14 @@ static const struct boot_swap_table boot_swap_tables[] = { { /* | slot-0 | slot-1 | *----------+------------+------------| - * magic | 0x******** | 0x12344321 | - * image-ok | 0x** | N/A | + * magic | Any | Good | + * image-ok | Any | N/A | * ---------+------------+------------' * swap: test | * -----------------------------------' */ .bsw_magic_slot0 = 0, - .bsw_magic_slot1 = 0x12344321, + .bsw_magic_slot1 = BOOT_MAGIC_GOOD, .bsw_image_ok_slot0 = 0, .bsw_swap_type = BOOT_SWAP_TYPE_TEST, }, @@ -80,14 +87,14 @@ static const struct boot_swap_table boot_swap_tables[] = { { /* | slot-0 | slot-1 | *----------+------------+------------| - * magic | 0x12344321 | 0xffffffff | + * magic | Good | Unset | * image-ok | 0xff | N/A | * ---------+------------+------------' * swap: revert (test image running) | * -----------------------------------' */ - .bsw_magic_slot0 = 0x12344321, - .bsw_magic_slot1 = 0xffffffff, + .bsw_magic_slot0 = BOOT_MAGIC_GOOD, + .bsw_magic_slot1 = BOOT_MAGIC_UNSET, .bsw_image_ok_slot0 = 0xff, .bsw_swap_type = BOOT_SWAP_TYPE_REVERT, }, @@ -95,14 +102,14 @@ static const struct boot_swap_table boot_swap_tables[] = { { /* | slot-0 | slot-1 | *----------+------------+------------| - * magic | 0x12344321 | 0xffffffff | + * magic | Good | Unset | * image-ok | 0x01 | N/A | * ---------+------------+------------' * swap: none (confirmed test image) | * -----------------------------------' */ - .bsw_magic_slot0 = 0x12344321, - .bsw_magic_slot1 = 0xffffffff, + .bsw_magic_slot0 = BOOT_MAGIC_GOOD, + .bsw_magic_slot1 = BOOT_MAGIC_UNSET, .bsw_image_ok_slot0 = 0x01, .bsw_swap_type = BOOT_SWAP_TYPE_NONE, }, @@ -111,24 +118,124 @@ static const struct boot_swap_table boot_swap_tables[] = { #define BOOT_SWAP_TABLES_COUNT \ (sizeof boot_swap_tables / sizeof boot_swap_tables[0]) +int +boot_magic_code(const uint32_t *magic) +{ + int i; + + if (memcmp(magic, boot_img_magic, sizeof boot_img_magic) == 0) { + return BOOT_MAGIC_GOOD; + } + + for (i = 0; i < 4; i++) { + if (magic[i] == 0xffffffff) { + return BOOT_MAGIC_UNSET; + } + } + + return BOOT_MAGIC_BAD; +} + +uint32_t +boot_status_sz(uint8_t min_write_sz) +{ + return BOOT_STATUS_MAX_ENTRIES * BOOT_STATUS_STATE_COUNT * min_write_sz; +} + +uint32_t +boot_trailer_sz(uint8_t min_write_sz) +{ + return sizeof boot_img_magic + + boot_status_sz(min_write_sz) + + min_write_sz * 2; +} + +static uint32_t +boot_magic_off(const struct flash_area *fap) +{ + uint32_t off_from_end; + uint8_t elem_sz; + + elem_sz = flash_area_align(fap); + + off_from_end = boot_trailer_sz(elem_sz); + + assert(off_from_end <= fap->fa_size); + return fap->fa_size - off_from_end; +} + +uint32_t +boot_status_off(const struct flash_area *fap) +{ + return boot_magic_off(fap) + sizeof boot_img_magic; +} + +static uint32_t +boot_copy_done_off(const struct flash_area *fap) +{ + return fap->fa_size - flash_area_align(fap) * 2; +} + +static uint32_t +boot_image_ok_off(const struct flash_area *fap) +{ + return fap->fa_size - flash_area_align(fap); +} + +int +boot_read_swap_state(const struct flash_area *fap, + struct boot_swap_state *state) +{ + uint32_t magic[4]; + uint32_t off; + int rc; + + off = boot_magic_off(fap); + rc = flash_area_read(fap, off, magic, sizeof magic); + if (rc != 0) { + return BOOT_EFLASH; + } + state->magic = boot_magic_code(magic); + + off = boot_copy_done_off(fap); + rc = flash_area_read(fap, off, &state->copy_done, 1); + if (rc != 0) { + return BOOT_EFLASH; + } + + off = boot_image_ok_off(fap); + rc = flash_area_read(fap, off, &state->image_ok, 1); + if (rc != 0) { + return BOOT_EFLASH; + } + + return 0; +} + /** * Reads the image trailer from the scratch area. */ int -boot_read_scratch_trailer(struct boot_img_trailer *bit) +boot_read_swap_state_scratch(struct boot_swap_state *state) { - int rc; const struct flash_area *fap; - uint32_t off; + int rc; rc = flash_area_open(FLASH_AREA_IMAGE_SCRATCH, &fap); if (rc) { - return rc; + rc = BOOT_EFLASH; + goto done; } - off = fap->fa_size - sizeof(struct boot_img_trailer); - rc = flash_area_read(fap, off, bit, sizeof(*bit)); - flash_area_close(fap); + rc = boot_read_swap_state(fap, state); + if (rc != 0) { + goto done; + } + + rc = 0; + +done: + flash_area_close(fap); return rc; } @@ -136,49 +243,107 @@ boot_read_scratch_trailer(struct boot_img_trailer *bit) * Reads the image trailer from a given image slot. */ int -boot_read_img_trailer(int slot, struct boot_img_trailer *bit) +boot_read_swap_state_img(int slot, struct boot_swap_state *state) { - int rc; const struct flash_area *fap; - uint32_t off; int area_id; + int rc; area_id = flash_area_id_from_image_slot(slot); rc = flash_area_open(area_id, &fap); - if (rc) { - return rc; + if (rc != 0) { + rc = BOOT_EFLASH; + goto done; } - off = fap->fa_size - sizeof(struct boot_img_trailer); - rc = flash_area_read(fap, off, bit, sizeof(*bit)); - flash_area_close(fap); + rc = boot_read_swap_state(fap, state); + if (rc != 0) { + goto done; + } + + rc = 0; + +done: + flash_area_close(fap); return rc; } int +boot_write_magic(const struct flash_area *fap) +{ + uint32_t off; + int rc; + + off = boot_magic_off(fap); + + rc = flash_area_write(fap, off, boot_img_magic, sizeof boot_img_magic); + if (rc != 0) { + return BOOT_EFLASH; + } + + return 0; +} + +int +boot_write_copy_done(const struct flash_area *fap) +{ + uint32_t off; + uint8_t val; + int rc; + + off = boot_copy_done_off(fap); + + val = 1; + rc = flash_area_write(fap, off, &val, 1); + if (rc != 0) { + return BOOT_EFLASH; + } + + return 0; +} + +int +boot_write_image_ok(const struct flash_area *fap) +{ + uint32_t off; + uint8_t val; + int rc; + + off = boot_image_ok_off(fap); + + val = 1; + rc = flash_area_write(fap, off, &val, 1); + if (rc != 0) { + return BOOT_EFLASH; + } + + return 0; +} + +int boot_swap_type(void) { const struct boot_swap_table *table; - struct boot_img_trailer bit_slot0; - struct boot_img_trailer bit_slot1; + struct boot_swap_state state_slot0; + struct boot_swap_state state_slot1; int rc; int i; - rc = boot_read_img_trailer(0, &bit_slot0); + rc = boot_read_swap_state_img(0, &state_slot0); assert(rc == 0); - rc = boot_read_img_trailer(1, &bit_slot1); + rc = boot_read_swap_state_img(1, &state_slot1); assert(rc == 0); for (i = 0; i < BOOT_SWAP_TABLES_COUNT; i++) { table = boot_swap_tables + i; if ((table->bsw_magic_slot0 == 0 || - table->bsw_magic_slot0 == bit_slot0.bit_copy_start) && + table->bsw_magic_slot0 == state_slot0.magic) && (table->bsw_magic_slot1 == 0 || - table->bsw_magic_slot1 == bit_slot1.bit_copy_start) && + table->bsw_magic_slot1 == state_slot1.magic) && (table->bsw_image_ok_slot0 == 0 || - table->bsw_image_ok_slot0 == bit_slot0.bit_img_ok)) { + table->bsw_image_ok_slot0 == state_slot0.image_ok)) { return table->bsw_swap_type; } @@ -189,7 +354,8 @@ boot_swap_type(void) } /** - * Write the test image version number from the boot vector. + * Marks the image in slot 1 as pending. On the next reboot, the system will + * perform a one-time boot of the slot 1 image. * * @return 0 on success; nonzero on failure. */ @@ -197,31 +363,29 @@ int boot_set_pending(void) { const struct flash_area *fap; - struct boot_img_trailer bit_slot1; - uint32_t off; + struct boot_swap_state state_slot1; int area_id; int rc; - rc = boot_read_img_trailer(1, &bit_slot1); - assert(rc == 0); + rc = boot_read_swap_state_img(1, &state_slot1); + if (rc != 0) { + return rc; + } - switch (bit_slot1.bit_copy_start) { - case BOOT_IMG_MAGIC: + switch (state_slot1.magic) { + case BOOT_MAGIC_GOOD: /* Swap already scheduled. */ return 0; - case 0xffffffff: - bit_slot1.bit_copy_start = BOOT_IMG_MAGIC; - + case BOOT_MAGIC_UNSET: area_id = flash_area_id_from_image_slot(1); rc = flash_area_open(area_id, &fap); - if (rc) { - return rc; + if (rc != 0) { + rc = BOOT_EFLASH; + } else { + rc = boot_write_magic(fap); } - off = fap->fa_size - sizeof(struct boot_img_trailer); - rc = flash_area_write(fap, off, &bit_slot1, - sizeof bit_slot1.bit_copy_start); flash_area_close(fap); return rc; @@ -233,9 +397,7 @@ boot_set_pending(void) } /** - * Deletes the main image version number from the boot vector. - * This must be called by the app to confirm that it is ok to keep booting - * to this image. + * Marks the image in slot 0 as confirmed. The system will continue booting into the image in slot 0 until told to boot from a different slot. * * @return 0 on success; nonzero on failure. */ @@ -243,39 +405,52 @@ int boot_set_confirmed(void) { const struct flash_area *fap; - struct boot_img_trailer bit_slot0; - uint32_t off; - uint8_t img_ok; + struct boot_swap_state state_slot0; int rc; - rc = boot_read_img_trailer(0, &bit_slot0); - assert(rc == 0); + rc = boot_read_swap_state_img(0, &state_slot0); + if (rc != 0) { + return rc; + } - if (bit_slot0.bit_copy_start != BOOT_IMG_MAGIC) { + switch (state_slot0.magic) { + case BOOT_MAGIC_GOOD: + /* Confirm needed; proceed. */ + break; + + case BOOT_MAGIC_UNSET: /* Already confirmed. */ return 0; + + case BOOT_MAGIC_BAD: + /* Unexpected state. */ + return BOOT_EBADVECT; } - if (bit_slot0.bit_copy_done == 0xff) { + if (state_slot0.copy_done == 0xff) { /* Swap never completed. This is unexpected. */ - return -1; + return BOOT_EBADVECT; } - if (bit_slot0.bit_img_ok != 0xff) { + if (state_slot0.image_ok != 0xff) { /* Already confirmed. */ return 0; } rc = flash_area_open(FLASH_AREA_IMAGE_0, &fap); if (rc) { - return rc; + rc = BOOT_EFLASH; + goto done; } - off = fap->fa_size - - sizeof(struct boot_img_trailer) + - offsetof(struct boot_img_trailer, bit_img_ok); + rc = boot_write_image_ok(fap); + if (rc != 0) { + goto done; + } + + rc = 0; - img_ok = 1; - rc = flash_area_write(fap, off, &img_ok, 1); +done: + flash_area_close(fap); return rc; } http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f855c453/boot/bootutil/src/bootutil_priv.h ---------------------------------------------------------------------- diff --git a/boot/bootutil/src/bootutil_priv.h b/boot/bootutil/src/bootutil_priv.h index 5ed1414..52ca226 100644 --- a/boot/bootutil/src/bootutil_priv.h +++ b/boot/bootutil/src/bootutil_priv.h @@ -27,6 +27,8 @@ extern "C" { #endif +struct flash_area; + #define BOOT_EFLASH 1 #define BOOT_EFILE 2 #define BOOT_EBADIMAGE 3 @@ -42,37 +44,62 @@ extern "C" { */ 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 */ }; +#define BOOT_MAGIC_GOOD 1 +#define BOOT_MAGIC_BAD 2 +#define BOOT_MAGIC_UNSET 3 + /** - * End-of-image slot data structure. + * End-of-image slot structure. + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * ~ MAGIC (16 octets) ~ + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * ~ ~ + * ~ Swap status (variable, aligned) ~ + * ~ ~ + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Copy done | 0xff padding (up to min-write-sz) ~ + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Image OK | 0xff padding (up to min-write-sz) ~ + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ -#define BOOT_IMG_MAGIC 0x12344321 - struct boot_img_trailer { - uint32_t bit_copy_start; - uint8_t bit_copy_done; - uint8_t bit_img_ok; - uint16_t _pad; +extern const uint32_t boot_img_magic[4]; + +struct boot_swap_state { + uint8_t magic; /* One of the BOOT_MAGIC_[...] values. */ + uint8_t copy_done; + uint8_t image_ok; }; #define BOOT_STATUS_STATE_COUNT 3 #define BOOT_STATUS_MAX_ENTRIES 128 +#define BOOT_STATUS_SOURCE_NONE 0 +#define BOOT_STATUS_SOURCE_SCRATCH 1 +#define BOOT_STATUS_SOURCE_SLOT0 2 + int bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, int slen, uint8_t key_id); +uint32_t boot_trailer_sz(uint8_t min_write_sz); +uint32_t boot_status_off(const struct flash_area *fap); +int boot_read_swap_state(const struct flash_area *fap, + struct boot_swap_state *state); +int boot_read_swap_state_img(int slot, struct boot_swap_state *state); +int boot_read_swap_state_scratch(struct boot_swap_state *state); +int boot_write_magic(const struct flash_area *fap); int boot_write_status(struct boot_status *bs); int boot_schedule_test_swap(void); +int boot_write_copy_done(const struct flash_area *fap); +int boot_write_image_ok(const struct flash_area *fap); -uint32_t boot_status_sz(int elem_sz); - -#if MYNEWT_VAL(TEST) -struct boot_req; -void boot_req_set(struct boot_req *req); -#endif +uint32_t boot_status_sz(uint8_t min_write_sz); #ifdef __cplusplus } http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f855c453/boot/bootutil/src/image_validate.c ---------------------------------------------------------------------- diff --git a/boot/bootutil/src/image_validate.c b/boot/bootutil/src/image_validate.c index 3793948..8c01324 100644 --- a/boot/bootutil/src/image_validate.c +++ b/boot/bootutil/src/image_validate.c @@ -24,6 +24,7 @@ #include "syscfg/syscfg.h" #include "hal/hal_flash.h" +#include "flash_map/flash_map.h" #include "bootutil/image.h" #include "bootutil/sign_key.h" @@ -38,8 +39,9 @@ * Compute SHA256 over the image. */ static int -bootutil_img_hash(struct image_header *hdr, uint8_t flash_id, uint32_t addr, - uint8_t *tmp_buf, uint32_t tmp_buf_sz, uint8_t *hash_result, uint8_t *seed, int seed_len) +bootutil_img_hash(struct image_header *hdr, const struct flash_area *fap, + uint8_t *tmp_buf, uint32_t tmp_buf_sz, + uint8_t *hash_result, uint8_t *seed, int seed_len) { mbedtls_sha256_context sha256_ctx; uint32_t blk_sz; @@ -68,7 +70,7 @@ bootutil_img_hash(struct image_header *hdr, uint8_t flash_id, uint32_t addr, if (blk_sz > tmp_buf_sz) { blk_sz = tmp_buf_sz; } - rc = hal_flash_read(flash_id, addr + off, tmp_buf, blk_sz); + rc = flash_area_read(fap, off, tmp_buf, blk_sz); if (rc) { return rc; } @@ -84,8 +86,9 @@ bootutil_img_hash(struct image_header *hdr, uint8_t flash_id, uint32_t addr, * Return non-zero if image could not be validated/does not validate. */ int -bootutil_img_validate(struct image_header *hdr, uint8_t flash_id, uint32_t addr, - uint8_t *tmp_buf, uint32_t tmp_buf_sz, uint8_t *seed, int seed_len, uint8_t *out_hash) +bootutil_img_validate(struct image_header *hdr, const struct flash_area *fap, + uint8_t *tmp_buf, uint32_t tmp_buf_sz, + uint8_t *seed, int seed_len, uint8_t *out_hash) { uint32_t off; uint32_t size; @@ -113,23 +116,22 @@ bootutil_img_validate(struct image_header *hdr, uint8_t flash_id, uint32_t addr, return -1; } - rc = bootutil_img_hash(hdr, flash_id, addr, tmp_buf, tmp_buf_sz, hash, seed, seed_len); + rc = bootutil_img_hash(hdr, fap, tmp_buf, tmp_buf_sz, hash, + seed, seed_len); if (rc) { return rc; } - if(out_hash) { + if (out_hash) { memcpy(out_hash, hash, 32); } - /* - * After image there's TLVs. - */ + /* After image there are TLVs. */ off = hdr->ih_img_size + hdr->ih_hdr_size; size = off + hdr->ih_tlv_size; for (; off < size; off += sizeof(tlv) + tlv.it_len) { - rc = hal_flash_read(flash_id, addr + off, &tlv, sizeof(tlv)); + rc = flash_area_read(fap, off, &tlv, sizeof tlv); if (rc) { return rc; } @@ -137,14 +139,14 @@ bootutil_img_validate(struct image_header *hdr, uint8_t flash_id, uint32_t addr, if (tlv.it_len != sizeof(hash)) { return -1; } - sha_off = addr + off + sizeof(tlv); + sha_off = off + sizeof(tlv); } #if MYNEWT_VAL(BOOTUTIL_SIGN_RSA) if (tlv.it_type == IMAGE_TLV_RSA2048) { if (tlv.it_len != 256) { /* 2048 bits */ return -1; } - sig_off = addr + off + sizeof(tlv); + sig_off = off + sizeof(tlv); sig_len = tlv.it_len; } #endif @@ -153,7 +155,7 @@ bootutil_img_validate(struct image_header *hdr, uint8_t flash_id, uint32_t addr, if (tlv.it_len < 64) { /* oids + 2 * 28 bytes */ return -1; } - sig_off = addr + off + sizeof(tlv); + sig_off = off + sizeof(tlv); sig_len = tlv.it_len; } #endif @@ -165,7 +167,7 @@ bootutil_img_validate(struct image_header *hdr, uint8_t flash_id, uint32_t addr, */ return -1; } - rc = hal_flash_read(flash_id, sha_off, buf, sizeof(hash)); + rc = flash_area_read(fap, sha_off, buf, sizeof hash); if (rc) { return rc; } @@ -181,7 +183,7 @@ bootutil_img_validate(struct image_header *hdr, uint8_t flash_id, uint32_t addr, */ return -1; } - rc = hal_flash_read(flash_id, sig_off, buf, sig_len); + rc = flash_area_read(fap, sig_off, buf, sig_len); if (rc) { return -1; } http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f855c453/boot/bootutil/src/loader.c ---------------------------------------------------------------------- diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c index c1a4281..08eb721 100644 --- a/boot/bootutil/src/loader.c +++ b/boot/bootutil/src/loader.c @@ -35,46 +35,48 @@ #include "bootutil/image.h" #include "bootutil_priv.h" +#define BOOT_MAX_IMG_SECTORS 120 + /** Number of image slots in flash; currently limited to two. */ #define BOOT_NUM_SLOTS 2 -/** The request object provided by the client. */ -static const struct boot_req *boot_req; +static struct { + struct { + struct image_header hdr; + struct flash_area sectors[BOOT_MAX_IMG_SECTORS]; + } imgs[BOOT_NUM_SLOTS]; -/** Info about image slots. */ -static struct boot_img { - struct image_header hdr; - struct boot_image_location loc; - uint32_t area; -} boot_img[BOOT_NUM_SLOTS]; + int num_img_sectors; + struct flash_area scratch_sector; -static int boot_erase_area(int area_idx, uint32_t sz); -static uint32_t boot_copy_sz(int max_idx, int *cnt); + uint8_t write_sz; +} boot_data; struct boot_status_table { - /** * For each field, a value of 0 means "any". */ - uint32_t bst_magic_slot0; - uint32_t bst_magic_scratch; + /** + * For each field, a value of 0 means "any". + */ + uint8_t bst_magic_slot0; + uint8_t bst_magic_scratch; uint8_t bst_copy_done_slot0; - uint8_t bst_status_source; }; /** - * This set of tables maps image trailer contents to swap status location. - * When searching for a match, these tables must be iterated sequentially. + * This set of tables maps swap state contents to boot status location. + * When searching for a match, these tables must be iterated in order. */ static const struct boot_status_table boot_status_tables[] = { { /* | slot-0 | scratch | * ----------+------------+------------| - * magic | 0x12344321 | 0x******** | + * magic | Good | Any | * copy-done | 0x01 | N/A | * ----------+------------+------------' * status: none | * ------------------------------------' */ - .bst_magic_slot0 = BOOT_IMG_MAGIC, + .bst_magic_slot0 = BOOT_MAGIC_GOOD, .bst_magic_scratch = 0, .bst_copy_done_slot0 = 0x01, .bst_status_source = BOOT_STATUS_SOURCE_NONE, @@ -83,13 +85,13 @@ static const struct boot_status_table boot_status_tables[] = { { /* | slot-0 | scratch | * ----------+------------+------------| - * magic | 0x12344321 | 0x******** | + * magic | Good | Any | * copy-done | 0xff | N/A | * ----------+------------+------------' * status: slot 0 | * ------------------------------------' */ - .bst_magic_slot0 = BOOT_IMG_MAGIC, + .bst_magic_slot0 = BOOT_MAGIC_GOOD, .bst_magic_scratch = 0, .bst_copy_done_slot0 = 0xff, .bst_status_source = BOOT_STATUS_SOURCE_SLOT0, @@ -98,14 +100,14 @@ static const struct boot_status_table boot_status_tables[] = { { /* | slot-0 | scratch | * ----------+------------+------------| - * magic | 0x******** | 0x12344321 | - * copy-done | 0x** | N/A | + * magic | Any | Good | + * copy-done | Any | N/A | * ----------+------------+------------' * status: scratch | * ------------------------------------' */ .bst_magic_slot0 = 0, - .bst_magic_scratch = BOOT_IMG_MAGIC, + .bst_magic_scratch = BOOT_MAGIC_GOOD, .bst_copy_done_slot0 = 0, .bst_status_source = BOOT_STATUS_SOURCE_SCRATCH, }, @@ -113,17 +115,17 @@ static const struct boot_status_table boot_status_tables[] = { { /* | slot-0 | scratch | * ----------+------------+------------| - * magic | 0xffffffff | 0xffffffff | + * magic | Unset | Any | * copy-done | 0xff | N/A | * ----------+------------+------------| * status: slot 0 | - * ------------------------------------+-------------------------------+ - * This represents one of two cases: | - * o No swaps ever (no status to read anyway, so no harm in checking). | - * o Mid-revert; status in slot 0. | - * --------------------------------------------------------------------' + * ------------------------------------+------------------------------+ + * This represents one of two cases: | + * o No swaps ever (no status to read, so no harm in checking). | + * o Mid-revert; status in slot 0. | + * -------------------------------------------------------------------' */ - .bst_magic_slot0 = 0xffffffff, + .bst_magic_slot0 = BOOT_MAGIC_UNSET, .bst_magic_scratch = 0, .bst_copy_done_slot0 = 0xff, .bst_status_source = BOOT_STATUS_SOURCE_SLOT0, @@ -133,34 +135,55 @@ static const struct boot_status_table boot_status_tables[] = { #define BOOT_STATUS_TABLES_COUNT \ (sizeof boot_status_tables / sizeof boot_status_tables[0]) +/** + * This table indicates the next swap type that should be performed. The first + * column contains the current swap type. The second column contains the swap + * type that should be effected after the first completes. + */ +static const uint8_t boot_swap_trans_table[][2] = { + /* From To */ + { BOOT_SWAP_TYPE_REVERT, BOOT_SWAP_TYPE_NONE }, + { BOOT_SWAP_TYPE_TEST, BOOT_SWAP_TYPE_REVERT }, +}; + +#define BOOT_SWAP_TRANS_TABLE_SIZE \ + (sizeof boot_swap_trans_table / sizeof boot_swap_trans_table[0]) + +/** + * 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 + * loader reset. + * + * @return A BOOT_STATUS_SOURCE_[...] code indicating where * status should be read from. + */ static int boot_status_source(void) { const struct boot_status_table *table; - struct boot_img_trailer bit_scratch; - struct boot_img_trailer bit_slot0; - struct boot_img_trailer bit_slot1; + struct boot_swap_state state_scratch; + struct boot_swap_state state_slot0; + struct boot_swap_state state_slot1; int rc; int i; - rc = boot_read_img_trailer(0, &bit_slot0); + rc = boot_read_swap_state_img(0, &state_slot0); assert(rc == 0); - rc = boot_read_img_trailer(1, &bit_slot1); + rc = boot_read_swap_state_img(1, &state_slot1); assert(rc == 0); - rc = boot_read_scratch_trailer(&bit_scratch); + rc = boot_read_swap_state_scratch(&state_scratch); assert(rc == 0); for (i = 0; i < BOOT_STATUS_TABLES_COUNT; i++) { table = boot_status_tables + i; if ((table->bst_magic_slot0 == 0 || - table->bst_magic_slot0 == bit_slot0.bit_copy_start) && + table->bst_magic_slot0 == state_slot0.magic) && (table->bst_magic_scratch == 0 || - table->bst_magic_scratch == bit_scratch.bit_copy_start) && + table->bst_magic_scratch == state_scratch.magic) && (table->bst_copy_done_slot0 == 0 || - table->bst_copy_done_slot0 == bit_slot0.bit_copy_done)) { + table->bst_copy_done_slot0 == state_slot0.copy_done)) { return table->bst_status_source; } @@ -169,191 +192,156 @@ boot_status_source(void) return BOOT_STATUS_SOURCE_NONE; } +/** + * Calculates the type of swap that just completed. + */ static int -boot_partial_swap_type(void) +boot_previous_swap_type(void) { - int swap_type; - - swap_type = boot_swap_type(); - switch (swap_type) { - case BOOT_SWAP_TYPE_NONE: - return BOOT_SWAP_TYPE_REVERT; + int post_swap_type; + int i; - case BOOT_SWAP_TYPE_REVERT: - return BOOT_SWAP_TYPE_TEST; + post_swap_type = boot_swap_type(); - default: - assert(0); - return BOOT_SWAP_TYPE_REVERT; + for (i = 0; i < BOOT_SWAP_TRANS_TABLE_SIZE; i++){ + if (boot_swap_trans_table[i][1] == post_swap_type) { + return boot_swap_trans_table[i][0]; + } } -} + + /* XXX: Temporary assert. */ + assert(0); -/** - * Calculates the flash offset of the specified image slot. - * - * @param slot_num The number of the slot to calculate. - * @param loc The flash location of the slot. - * - */ -static void -boot_slot_addr(int slot_num, struct boot_image_location *loc) -{ - const struct flash_area *area_desc; - uint8_t area_idx; - - area_idx = boot_req->br_slot_areas[slot_num]; - area_desc = boot_req->br_area_descs + area_idx; - loc->bil_flash_id = area_desc->fa_device_id; - loc->bil_address = area_desc->fa_off; + return BOOT_SWAP_TYPE_REVERT; } -/** - * Reads the header of image present in flash. Header corresponding to - * empty image slot is filled with 0xff bytes. - * - * @param out_headers Points to an array of image headers. Each - * element is filled with the header of the - * corresponding image in flash. - * @param addresses An array containing the flash addresses of each - * image slot. - * @param num_addresses The number of headers to read. This should - * also be equal to the lengths of the - * out_headers and addresses arrays. - */ static int -boot_read_image_header(struct boot_image_location *loc, - struct image_header *out_hdr) +boot_read_image_header(int slot, struct image_header *out_hdr) { + const struct flash_area *fap; + int area_id; int rc; - rc = hal_flash_read(loc->bil_flash_id, loc->bil_address, out_hdr, - sizeof *out_hdr); + area_id = flash_area_id_from_image_slot(slot); + rc = flash_area_open(area_id, &fap); if (rc != 0) { rc = BOOT_EFLASH; - } else if (out_hdr->ih_magic != IMAGE_MAGIC) { - rc = BOOT_EBADIMAGE; + goto done; } - if (rc) { - memset(out_hdr, 0xff, sizeof(*out_hdr)); + rc = flash_area_read(fap, 0, out_hdr, sizeof *out_hdr); + if (rc != 0) { + rc = BOOT_EFLASH; + goto done; } + + rc = 0; + +done: + flash_area_close(fap); return rc; } -static void +static int boot_read_image_headers(void) { - struct boot_img *b; + int rc; int i; for (i = 0; i < BOOT_NUM_SLOTS; i++) { - b = &boot_img[i]; - boot_slot_addr(i, &b->loc); - boot_read_image_header(&b->loc, &b->hdr); - b->area = boot_req->br_img_sz; + rc = boot_read_image_header(i, &boot_data.imgs[i].hdr); + if (rc != 0) { + return rc; + } } + + return 0; } -int -boot_build_request(struct boot_req *preq, int area_descriptor_max) +static uint8_t +boot_write_sz(void) { - int cnt; - int total; - int rc; - const struct flash_area *fap; - struct flash_area *descs = preq->br_area_descs; - uint8_t *img_starts = preq->br_slot_areas; + uint8_t elem_sz; + uint8_t align; - cnt = area_descriptor_max; - rc = flash_area_to_sectors(FLASH_AREA_IMAGE_0, &cnt, descs); - img_starts[0] = 0; - total = cnt; + /* Figure out what size to write update status update as. The size depends + * on what the minimum write size is for scratch area, active image slot. + * We need to use the bigger of those 2 values. + */ + elem_sz = hal_flash_align(boot_data.imgs[0].sectors[0].fa_device_id); + align = hal_flash_align(boot_data.scratch_sector.fa_device_id); + if (align > elem_sz) { + elem_sz = align; + } - flash_area_open(FLASH_AREA_IMAGE_0, &fap); - preq->br_img_sz = fap->fa_size; + return elem_sz; +} - cnt = area_descriptor_max - total; - if (cnt < 0) { - return -1; - } +/** + * Determines the sector layout of both image slots and the scratch area. + * This information is necessary for calculating the number of bytes to erase + * and copy during an image swap. The information collected during this + * function is used to populate the boot_data global. + */ +static int +boot_read_sectors(void) +{ + const struct flash_area *sector0; + const struct flash_area *sector1; + const struct flash_area *scratch; + int num_sectors_slot0; + int num_sectors_slot1; + int rc; + int i; - rc = flash_area_to_sectors(FLASH_AREA_IMAGE_1, &cnt, - &descs[total]); + num_sectors_slot0 = BOOT_MAX_IMG_SECTORS; + rc = flash_area_to_sectors(FLASH_AREA_IMAGE_0, &num_sectors_slot0, + boot_data.imgs[0].sectors); if (rc != 0) { - return -2; + return BOOT_EFLASH; } - img_starts[1] = total; - total += cnt; - cnt = area_descriptor_max - total; - if (cnt < 0) { - return -3; + num_sectors_slot1 = BOOT_MAX_IMG_SECTORS; + rc = flash_area_to_sectors(FLASH_AREA_IMAGE_1, &num_sectors_slot1, + boot_data.imgs[1].sectors); + if (rc != 0) { + return BOOT_EFLASH; } - rc = flash_area_to_sectors(FLASH_AREA_IMAGE_SCRATCH, &cnt, - &descs[total]); - if(rc != 0) { - return -4; + rc = flash_area_open(FLASH_AREA_IMAGE_SCRATCH, &scratch); + if (rc != 0) { + return BOOT_EFLASH; } + boot_data.scratch_sector = *scratch; + boot_data.write_sz = hal_flash_align(scratch->fa_device_id); - preq->br_scratch_area_idx = total; - total += cnt; - preq->br_num_image_areas = total; - return 0; -} - -/* - * Status about copy-in-progress is either in slot0 (target slot) or - * in scratch area. It is in scratch area if the process is currently - * moving the last sector within image. - * - * If the copy-in-progress status is within the image slot, it will - * be at the end of the area. - * If the sector containing the boot copy status is in scratch, it's - * offset from beginning of scratch depends on how much of the image - * fits inside the scratch area. - * - * We start copy from the end of image, so boot-copy-status is in - * scratch when the first area is being moved. Otherwise it will be - * in slot 0. - */ -static void -boot_magic_loc(int slot_num, uint8_t *flash_id, uint32_t *off) -{ - struct boot_img *b; - - b = &boot_img[slot_num]; - *flash_id = b->loc.bil_flash_id; - *off = b->area + b->loc.bil_address - sizeof(struct boot_img_trailer); -} + /* Ensure both image slots have identical sector layouts. */ + if (num_sectors_slot0 != num_sectors_slot1) { + return BOOT_EFLASH; + } + for (i = 0; i < num_sectors_slot0; i++) { + sector0 = boot_data.imgs[0].sectors + i; + sector1 = boot_data.imgs[1].sectors + i; + if (sector0->fa_size != sector1->fa_size) { + return BOOT_EFLASH; + } + } -static void -boot_scratch_loc(uint8_t *flash_id, uint32_t *off) -{ - struct flash_area *scratch; - int cnt; + boot_data.num_img_sectors = num_sectors_slot0; - scratch = &boot_req->br_area_descs[boot_req->br_scratch_area_idx]; - *flash_id = scratch->fa_device_id; + boot_data.write_sz = boot_write_sz(); - /* Calculate where the boot status would be if it was copied to scratch. */ - *off = boot_copy_sz(boot_req->br_slot_areas[1], &cnt); - *off += (scratch->fa_off - sizeof(struct boot_img_trailer)); + return 0; } static uint32_t -boot_status_off(uint32_t trailer_off, int status_idx, int status_state, - int elem_sz) +boot_status_internal_off(int idx, int state, int elem_sz) { - uint32_t status_start; int idx_sz; - status_start = trailer_off - boot_status_sz(elem_sz); + idx_sz = elem_sz * BOOT_STATUS_STATE_COUNT; - idx_sz = BOOT_STATUS_STATE_COUNT * elem_sz; - return status_start + - status_idx * idx_sz + - status_state * elem_sz; + return idx * idx_sz + state * elem_sz; } /** @@ -361,23 +349,24 @@ boot_status_off(uint32_t trailer_off, int status_idx, int status_state, * to recover in case the boot lodaer was reset in the middle of a swap * operation. */ -static void -boot_read_status_bytes(struct boot_status *bs, uint8_t flash_id, - uint32_t trailer_off) +static int +boot_read_status_bytes(const struct flash_area *fap, struct boot_status *bs) { - uint32_t status_sz; uint32_t off; uint8_t status; int found; + int rc; int i; - status_sz = boot_status_sz(bs->elem_sz); - off = trailer_off - status_sz; + off = boot_status_off(fap); found = 0; - for (i = 0; i < status_sz; i++) { - hal_flash_read(flash_id, off + i * bs->elem_sz, - &status, sizeof status); + for (i = 0; i < BOOT_STATUS_MAX_ENTRIES; i++) { + rc = flash_area_read(fap, off + i * boot_data.write_sz, &status, 1); + if (rc != 0) { + return BOOT_EFLASH; + } + if (status == 0xff) { if (found) { break; @@ -392,28 +381,8 @@ boot_read_status_bytes(struct boot_status *bs, uint8_t flash_id, bs->idx = i / BOOT_STATUS_STATE_COUNT; bs->state = i % BOOT_STATUS_STATE_COUNT; } -} - -static uint8_t -boot_status_elem_sz(void) -{ - const struct flash_area *scratch; - uint8_t elem_sz; - uint8_t align; - /* Figure out what size to write update status update as. The size depends - * on what the minimum write size is for scratch area, active image slot. - * We need to use the bigger of those 2 values. - */ - elem_sz = hal_flash_align(boot_img[0].loc.bil_flash_id); - - scratch = &boot_req->br_area_descs[boot_req->br_scratch_area_idx]; - align = hal_flash_align(scratch->fa_device_id); - if (align > elem_sz) { - elem_sz = align; - } - - return elem_sz; + return 0; } /** @@ -423,37 +392,44 @@ boot_status_elem_sz(void) * there is no operation in progress. */ static int -boot_read_status(struct boot_status *boot_state) +boot_read_status(struct boot_status *bs) { - uint32_t off; - uint8_t flash_id; + const struct flash_area *fap; int status_loc; + int area_id; + int rc; - memset(boot_state, 0, sizeof *boot_state); - - boot_state->elem_sz = boot_status_elem_sz(); + memset(bs, 0, sizeof *bs); status_loc = boot_status_source(); switch (status_loc) { case BOOT_STATUS_SOURCE_NONE: - break; + return 0; case BOOT_STATUS_SOURCE_SCRATCH: - boot_scratch_loc(&flash_id, &off); - boot_read_status_bytes(boot_state, flash_id, off); + area_id = FLASH_AREA_IMAGE_SCRATCH; break; case BOOT_STATUS_SOURCE_SLOT0: - boot_magic_loc(0, &flash_id, &off); - boot_read_status_bytes(boot_state, flash_id, off); + area_id = FLASH_AREA_IMAGE_0; break; default: assert(0); - break; + return BOOT_EBADARGS; } - return boot_state->idx != 0 || boot_state->state != 0; + rc = flash_area_open(area_id, &fap); + if (rc != 0) { + return BOOT_EFLASH; + } + + rc = boot_read_status_bytes(fap, bs); + if (rc != 0) { + return rc; + } + + return 0; } /** @@ -467,29 +443,46 @@ boot_read_status(struct boot_status *boot_state) int boot_write_status(struct boot_status *bs) { - uint32_t trailer_off; - uint32_t status_off; - uint8_t flash_id; + const struct flash_area *fap; + uint32_t off; + int area_id; + int rc; if (bs->idx == 0) { /* Write to scratch. */ - boot_scratch_loc(&flash_id, &trailer_off); + area_id = FLASH_AREA_IMAGE_SCRATCH; } else { /* Write to slot 0. */ - boot_magic_loc(0, &flash_id, &trailer_off); + area_id = FLASH_AREA_IMAGE_0; + } + + rc = flash_area_open(area_id, &fap); + if (rc != 0) { + rc = BOOT_EFLASH; + goto done; } - status_off = boot_status_off(trailer_off, bs->idx, bs->state, bs->elem_sz); - hal_flash_write(flash_id, status_off, &bs->state, 1); + off = boot_status_off(fap) + + boot_status_internal_off(bs->idx, bs->state, boot_data.write_sz); - return 0; + rc = flash_area_write(fap, off, &bs->state, 1); + if (rc != 0) { + rc = BOOT_EFLASH; + goto done; + } + + rc = 0; + +done: + flash_area_close(fap); + return rc; } /* * Validate image hash/signature in a slot. */ static int -boot_image_check(struct image_header *hdr, struct boot_image_location *loc) +boot_image_check(struct image_header *hdr, const struct flash_area *fap) { static void *tmpbuf; @@ -499,19 +492,18 @@ boot_image_check(struct image_header *hdr, struct boot_image_location *loc) return BOOT_ENOMEM; } } - if (bootutil_img_validate(hdr, loc->bil_flash_id, loc->bil_address, - tmpbuf, BOOT_TMPBUF_SZ, NULL, 0, NULL)) { + if (bootutil_img_validate(hdr, fap, tmpbuf, BOOT_TMPBUF_SZ, + NULL, 0, NULL)) { return BOOT_EBADIMAGE; } return 0; } - static int split_image_check(struct image_header *app_hdr, - struct boot_image_location *app_loc, + const struct flash_area *app_fap, struct image_header *loader_hdr, - struct boot_image_location *loader_loc) + const struct flash_area *loader_fap) { static void *tmpbuf; uint8_t loader_hash[32]; @@ -522,41 +514,53 @@ split_image_check(struct image_header *app_hdr, return BOOT_ENOMEM; } } - if (bootutil_img_validate(loader_hdr, loader_loc->bil_flash_id, - loader_loc->bil_address, tmpbuf, BOOT_TMPBUF_SZ, - NULL, 0, loader_hash)) { + if (bootutil_img_validate(loader_hdr, loader_fap, tmpbuf, BOOT_TMPBUF_SZ, + NULL, 0, loader_hash)) { return BOOT_EBADIMAGE; } - if (bootutil_img_validate(app_hdr, app_loc->bil_flash_id, - app_loc->bil_address, - tmpbuf, BOOT_TMPBUF_SZ, loader_hash, 32, NULL)) { + if (bootutil_img_validate(app_hdr, app_fap, tmpbuf, BOOT_TMPBUF_SZ, + loader_hash, 32, NULL)) { return BOOT_EBADIMAGE; } + return 0; } static int boot_validate_slot1(void) { - if (boot_img[1].hdr.ih_magic == 0xffffffff || - boot_img[1].hdr.ih_flags & IMAGE_F_NON_BOOTABLE) { + 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) { /* No bootable image in slot 1; continue booting from slot 0. */ return -1; } - if (boot_img[1].hdr.ih_magic != IMAGE_MAGIC || - boot_image_check(&boot_img[1].hdr, &boot_img[1].loc) != 0) { + /* Image in slot 1 is invalid. Erase the image and continue booting + * from slot 0. + */ + rc = flash_area_open(FLASH_AREA_IMAGE_1, &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) { /* Image in slot 1 is invalid. Erase the image and continue booting * from slot 0. */ - boot_erase_area(boot_req->br_slot_areas[1], boot_img[1].area); + flash_area_erase(fap, 0, fap->fa_size); return -1; } + flash_area_close(fap); + /* Image in slot 1 is valid. */ return 0; } @@ -584,199 +588,236 @@ boot_validated_swap_type(void) /* Boot loader wants to switch to slot 1. Ensure image is valid. */ rc = boot_validate_slot1(); if (rc != 0) { - return BOOT_SWAP_TYPE_NONE; + return BOOT_SWAP_TYPE_FAIL; } return swap_type; } /** - * Calculates the size of the swap status and image trailer at the end of each - * image slot. - */ -static int -boot_meta_sz(int status_elem_sz) -{ - return sizeof (struct boot_img_trailer) + boot_status_sz(status_elem_sz); -} - -/** - * How many sectors starting from sector[idx] can fit inside scratch. + * Calculates the number of sectors the scratch area can contain. A "last" + * source sector is specified because images are copied backwards in flash + * (final index to index number 0). + * + * @param last_sector_idx The index of the last source sector + * (inclusive). + * @param out_first_sector_idx The index of the first source sector + * (inclusive) gets written here. + * + * @return The number of bytes comprised by the + * [first-sector, last-sector] range. */ static uint32_t -boot_copy_sz(int max_idx, int *cnt) +boot_copy_sz(int last_sector_idx, int *out_first_sector_idx) { - int i; + uint32_t new_sz; uint32_t sz; - static uint32_t scratch_sz = 0; + int i; - if (!scratch_sz) { - for (i = boot_req->br_scratch_area_idx; - i < boot_req->br_num_image_areas; - i++) { - scratch_sz += boot_req->br_area_descs[i].fa_size; - } - } sz = 0; - *cnt = 0; - for (i = max_idx - 1; i >= 0; i--) { - if (sz + boot_req->br_area_descs[i].fa_size > scratch_sz) { + + for (i = last_sector_idx; i >= 0; i--) { + new_sz = sz + boot_data.imgs[0].sectors[i].fa_size; + if (new_sz > boot_data.scratch_sector.fa_size) { break; } - sz += boot_req->br_area_descs[i].fa_size; - *cnt = *cnt + 1; + sz = new_sz; } + + /* i currently refers to a sector that doesn't fit or it is -1 because all + * sectors have been processed. In both cases, exclude sector i. + */ + *out_first_sector_idx = i + 1; return sz; } /** - * Erases one area. + * Erases a region of flash. * - * @param area_idx The index of the area. + * @param flash_area_idx The ID of the flash area containing the region + * to erase. + * @param off The offset within the flash area to start the + * erase. * @param sz The number of bytes to erase. * * @return 0 on success; nonzero on failure. */ static int -boot_erase_area(int area_idx, uint32_t sz) +boot_erase_area(int flash_area_id, uint32_t off, uint32_t sz) { - const struct flash_area *area_desc; + const struct flash_area *fap; int rc; - area_desc = boot_req->br_area_descs + area_idx; - rc = hal_flash_erase(area_desc->fa_device_id, area_desc->fa_off, sz); + rc = flash_area_open(flash_area_id, &fap); if (rc != 0) { - return BOOT_EFLASH; + rc = BOOT_EFLASH; + goto done; } - return 0; + + rc = flash_area_erase(fap, off, sz); + if (rc != 0) { + rc = BOOT_EFLASH; + goto done; + } + + rc = 0; + +done: + flash_area_close(fap); + return rc; } /** - * Copies the contents of one area to another. The destination area must - * be erased prior to this function being called. + * Copies the contents of one flash region to another. You must erase the + * destination region prior to calling this function. * - * @param from_area_idx The index of the source area. - * @param to_area_idx The index of the destination area. - * @param sz The number of bytes to move. + * @param flash_area_id_src The ID of the source flash area. + * @param flash_area_id_dst The ID of the destination flash area. + * @param off_src The offset within the source flash area to + * copy from. + * @param off_dst The offset within the destination flash area to + * copy to. + * @param sz The number of bytes to copy. * * @return 0 on success; nonzero on failure. */ static int -boot_copy_area(int from_area_idx, int to_area_idx, uint32_t sz) +boot_copy_area(int flash_area_id_src, int flash_area_id_dst, + uint32_t off_src, uint32_t off_dst, uint32_t sz) { - const struct flash_area *from_area_desc; - const struct flash_area *to_area_desc; - uint32_t from_addr; - uint32_t to_addr; - uint32_t off; + const struct flash_area *fap_src; + const struct flash_area *fap_dst; + uint32_t bytes_copied; int chunk_sz; int rc; static uint8_t buf[1024]; - from_area_desc = boot_req->br_area_descs + from_area_idx; - to_area_desc = boot_req->br_area_descs + to_area_idx; + fap_src = NULL; + fap_dst = NULL; + + rc = flash_area_open(flash_area_id_src, &fap_src); + if (rc != 0) { + rc = BOOT_EFLASH; + goto done; + } - assert(to_area_desc->fa_size >= from_area_desc->fa_size); + rc = flash_area_open(flash_area_id_dst, &fap_dst); + if (rc != 0) { + rc = BOOT_EFLASH; + goto done; + } - off = 0; - while (off < sz) { - if (sz - off > sizeof buf) { + bytes_copied = 0; + while (bytes_copied < sz) { + if (sz - bytes_copied > sizeof buf) { chunk_sz = sizeof buf; } else { - chunk_sz = sz - off; + chunk_sz = sz - bytes_copied; } - from_addr = from_area_desc->fa_off + off; - rc = hal_flash_read(from_area_desc->fa_device_id, from_addr, buf, - chunk_sz); + rc = flash_area_read(fap_src, off_src + bytes_copied, buf, chunk_sz); if (rc != 0) { - return rc; + rc = BOOT_EFLASH; + goto done; } - to_addr = to_area_desc->fa_off + off; - rc = hal_flash_write(to_area_desc->fa_device_id, to_addr, buf, - chunk_sz); + rc = flash_area_write(fap_dst, off_dst + bytes_copied, buf, chunk_sz); if (rc != 0) { - return rc; + rc = BOOT_EFLASH; + goto done; } - off += chunk_sz; + bytes_copied += chunk_sz; } - return 0; + rc = 0; + +done: + flash_area_close(fap_src); + flash_area_close(fap_dst); + return rc; } /** - * Swaps the contents of two flash areas belonging to images. + * Swaps the contents of two flash regions within the two image slots. * - * @param 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 end_area Whether this is the last sector in the source - * and destination slots (0/1). + * @param idx The index of the first sector in the range of + * sectors being swapped. + * @param sz The number of bytes to swap. + * @param bs The current boot status. This struct gets + * updated according to the outcome. * * @return 0 on success; nonzero on failure. */ static int -boot_swap_areas(int idx, uint32_t sz, int end_area, - struct boot_status *boot_state) +boot_swap_areas(int idx, uint32_t sz, struct boot_status *bs) { - int area_idx_0; - int area_idx_1; + uint32_t copy_sz; + uint32_t img_off; int rc; - area_idx_0 = boot_req->br_slot_areas[0] + idx; - area_idx_1 = boot_req->br_slot_areas[1] + idx; - assert(area_idx_0 != area_idx_1); - assert(area_idx_0 != boot_req->br_scratch_area_idx); - assert(area_idx_1 != boot_req->br_scratch_area_idx); + /* Calculate offset from start of image area. */ + img_off = boot_data.imgs[0].sectors[idx].fa_off - + boot_data.imgs[0].sectors[0].fa_off; - if (boot_state->state == 0) { - rc = boot_erase_area(boot_req->br_scratch_area_idx, sz); + if (bs->state == 0) { + rc = boot_erase_area(FLASH_AREA_IMAGE_SCRATCH, 0, sz); if (rc != 0) { return rc; } - rc = boot_copy_area(area_idx_1, boot_req->br_scratch_area_idx, sz); + rc = boot_copy_area(FLASH_AREA_IMAGE_1, FLASH_AREA_IMAGE_SCRATCH, + img_off, 0, sz); if (rc != 0) { return rc; } - boot_state->state = 1; - (void)boot_write_status(boot_state); + bs->state = 1; + (void)boot_write_status(bs); } - if (boot_state->state == 1) { - rc = boot_erase_area(area_idx_1, sz); + if (bs->state == 1) { + rc = boot_erase_area(FLASH_AREA_IMAGE_1, img_off, sz); if (rc != 0) { return rc; } - rc = boot_copy_area(area_idx_0, area_idx_1, - end_area ? (sz - boot_meta_sz(boot_state->elem_sz)) : sz); + copy_sz = sz; + if (boot_data.imgs[0].sectors[idx].fa_off + sz >= + boot_data.imgs[1].sectors[0].fa_off) { + + /* This is the end of the area. Don't copy the image state into + * slot 1. + */ + copy_sz -= boot_trailer_sz(boot_data.write_sz); + } + + rc = boot_copy_area(FLASH_AREA_IMAGE_0, FLASH_AREA_IMAGE_1, + img_off, img_off, copy_sz); if (rc != 0) { return rc; } - boot_state->state = 2; - (void)boot_write_status(boot_state); + bs->state = 2; + (void)boot_write_status(bs); } - if (boot_state->state == 2) { - rc = boot_erase_area(area_idx_0, sz); + if (bs->state == 2) { + rc = boot_erase_area(FLASH_AREA_IMAGE_0, img_off, sz); if (rc != 0) { return rc; } - rc = boot_copy_area(boot_req->br_scratch_area_idx, area_idx_0, sz); + rc = boot_copy_area(FLASH_AREA_IMAGE_SCRATCH, FLASH_AREA_IMAGE_0, + 0, img_off, sz); if (rc != 0) { return rc; } - boot_state->idx++; - boot_state->state = 0; - (void)boot_write_status(boot_state); + bs->idx++; + bs->state = 0; + (void)boot_write_status(bs); } + return 0; } @@ -784,24 +825,32 @@ boot_swap_areas(int idx, uint32_t sz, int end_area, * Swaps the two images in flash. If a prior copy operation was interrupted * by a system reset, this function completes that operation. * + * @param bs The current boot status. This function reads + * this struct to determine if it is resuming + * an interrupted swap operation. This + * function writes the updated status to this + * function on return. + * * @return 0 on success; nonzero on failure. */ static int -boot_copy_image(struct boot_status *boot_state) +boot_copy_image(struct boot_status *bs) { uint32_t sz; - int i; - int end_area = 1; - int cnt; - int cur_idx; - - for (i = boot_req->br_slot_areas[1], cur_idx = 0; i > 0; cur_idx++) { - sz = boot_copy_sz(i, &cnt); - i -= cnt; - if (cur_idx >= boot_state->idx) { - boot_swap_areas(i, sz, end_area, boot_state); + int first_sector_idx; + int last_sector_idx; + int swap_idx; + + swap_idx = 0; + last_sector_idx = boot_data.num_img_sectors - 1; + while (last_sector_idx >= 0) { + sz = boot_copy_sz(last_sector_idx, &first_sector_idx); + if (swap_idx >= bs->idx) { + boot_swap_areas(first_sector_idx, sz, bs); } - end_area = 0; + + last_sector_idx = first_sector_idx - 1; + swap_idx++; } return 0; @@ -813,18 +862,20 @@ boot_copy_image(struct boot_status *boot_state) static int boot_finalize_test_swap(void) { - struct boot_img_trailer bit; - uint32_t off; - uint8_t flash_id; + const struct flash_area *fap; int rc; - boot_magic_loc(0, &flash_id, &off); - off += offsetof(struct boot_img_trailer, bit_copy_done); + rc = flash_area_open(FLASH_AREA_IMAGE_0, &fap); + if (rc != 0) { + return BOOT_EFLASH; + } - bit.bit_copy_done = 1; - rc = hal_flash_write(flash_id, off, &bit.bit_copy_done, 1); + rc = boot_write_copy_done(fap); + if (rc != 0) { + return rc; + } - return rc; + return 0; } /** @@ -835,67 +886,95 @@ boot_finalize_test_swap(void) static int boot_finalize_revert_swap(void) { - struct boot_img_trailer bit; - uint32_t off; - uint8_t flash_id; + const struct flash_area *fap; + struct boot_swap_state state_slot0; int rc; - boot_magic_loc(0, &flash_id, &off); + rc = flash_area_open(FLASH_AREA_IMAGE_0, &fap); + if (rc != 0) { + return BOOT_EFLASH; + } - bit.bit_copy_start = BOOT_IMG_MAGIC; - bit.bit_copy_done = 1; - bit.bit_img_ok = 1; - rc = hal_flash_write(flash_id, off, &bit, sizeof bit); + rc = boot_read_swap_state(fap, &state_slot0); + if (rc != 0) { + return BOOT_EFLASH; + } - return rc; -} + if (state_slot0.magic == BOOT_MAGIC_UNSET) { + rc = boot_write_magic(fap); + if (rc != 0) { + return rc; + } + } -uint32_t -boot_status_sz(int elem_sz) -{ - return BOOT_STATUS_MAX_ENTRIES * BOOT_STATUS_STATE_COUNT * elem_sz; + if (state_slot0.copy_done == 0xff) { + rc = boot_write_copy_done(fap); + if (rc != 0) { + return rc; + } + } + + if (state_slot0.image_ok == 0xff) { + rc = boot_write_image_ok(fap); + if (rc != 0) { + return rc; + } + } + + return 0; } /** - * Prepares the booting process. Based on the information provided in the - * request object, this function moves images around in flash as appropriate, - * and tells you what address to boot from. + * Prepares the booting process. This function moves images around in flash as + * appropriate, and tells you what address to boot from. * - * @param req Contains information about the flash layout. * @param rsp On success, indicates how booting should occur. * * @return 0 on success; nonzero on failure. */ int -boot_go(const struct boot_req *req, struct boot_rsp *rsp) +boot_go(struct boot_rsp *rsp) { - struct boot_status boot_state; - int partial_swap; + struct boot_status bs; int swap_type; int slot; int rc; - /* Set the global boot request object. The remainder of the boot process - * will reference the global. - */ - boot_req = req; + /* Determine the sector layout of the image slots and scratch area. */ + rc = boot_read_sectors(); + if (rc != 0) { + return rc; + } /* Attempt to read an image header from each slot. */ - boot_read_image_headers(); + rc = boot_read_image_headers(); + if (rc != 0) { + return rc; + } /* Determine if we rebooted in the middle of an image swap operation. */ - partial_swap = boot_read_status(&boot_state); - if (partial_swap) { - /* Complete the partial swap. */ - rc = boot_copy_image(&boot_state); + rc = boot_read_status(&bs); + if (rc != 0) { + return rc; + } + + /* If a partial swap was detected, complete it. */ + if (bs.idx != 0 || bs.state != 0) { + rc = boot_copy_image(&bs); assert(rc == 0); - swap_type = boot_partial_swap_type(); + /* Extrapolate the type of the partial swap. We need this information + * to know how to mark the swap complete in flash. + */ + swap_type = boot_previous_swap_type(); } else { swap_type = boot_validated_swap_type(); - if (swap_type != BOOT_SWAP_TYPE_NONE) { - rc = boot_copy_image(&boot_state); + switch (swap_type) { + case BOOT_SWAP_TYPE_TEST: + case BOOT_SWAP_TYPE_REVERT: + rc = boot_copy_image(&bs); assert(rc == 0); + break; } } @@ -914,6 +993,15 @@ boot_go(const struct boot_req *req, struct boot_rsp *rsp) boot_finalize_revert_swap(); break; + case BOOT_SWAP_TYPE_FAIL: + /* The image in slot 1 was invalid and is now erased. Ensure we don't + * try to boot into it again on the next reboot. Do this by pretending + * we just reverted back to slot 0. + */ + slot = 0; + boot_finalize_revert_swap(); + break; + default: assert(0); slot = 0; @@ -921,76 +1009,72 @@ boot_go(const struct boot_req *req, struct boot_rsp *rsp) } /* 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; - rsp->br_hdr = &boot_img[slot].hdr; + rsp->br_flash_id = boot_data.imgs[0].sectors[0].fa_device_id; + rsp->br_image_addr = boot_data.imgs[0].sectors[0].fa_off; + rsp->br_hdr = &boot_data.imgs[slot].hdr; return 0; } -#define SPLIT_AREA_DESC_MAX (255) - int split_go(int loader_slot, int split_slot, void **entry) { - int rc; - /** Areas representing the beginning of image slots. */ - uint8_t img_starts[2]; - struct flash_area *descs; + const struct flash_area *loader_fap; + const struct flash_area *app_fap; uint32_t entry_val; - struct boot_req req = { - .br_slot_areas = img_starts, - }; + int loader_flash_id; + int app_flash_id; + int rc; - descs = calloc(SPLIT_AREA_DESC_MAX, sizeof(struct flash_area)); - if (descs == NULL) { - return SPLIT_GO_ERR; - } + app_fap = NULL; + loader_fap = NULL; - req.br_area_descs = descs; + rc = boot_read_sectors(); + if (rc != 0) { + goto done; + } - rc = boot_build_request(&req, SPLIT_AREA_DESC_MAX); + rc = boot_read_image_headers(); if (rc != 0) { - rc = SPLIT_GO_ERR; - goto split_app_go_end; + goto done; } - boot_req = &req; + app_flash_id = flash_area_id_from_image_slot(split_slot); + rc = flash_area_open(app_flash_id, &app_fap); + if (rc != 0) { + rc = BOOT_EFLASH; + goto done; + } - boot_read_image_headers(); + loader_flash_id = flash_area_id_from_image_slot(loader_slot); + rc = flash_area_open(loader_flash_id, &loader_fap); + if (rc != 0) { + rc = BOOT_EFLASH; + goto done; + } - /* Don't check the bootable image flag because we could really - * call a bootable or non-bootable image. Just validate that - * the image check passes which is distinct from the normal check */ - rc = split_image_check(&boot_img[split_slot].hdr, - &boot_img[split_slot].loc, - &boot_img[loader_slot].hdr, - &boot_img[loader_slot].loc); + /* Don't check the bootable image flag because we could really call a + * bootable or non-bootable image. Just validate that the image check + * passes which is distinct from the normal check. + */ + rc = split_image_check(&boot_data.imgs[split_slot].hdr, + app_fap, + &boot_data.imgs[loader_slot].hdr, + loader_fap); if (rc != 0) { rc = SPLIT_GO_NON_MATCHING; - goto split_app_go_end; + goto done; } - entry_val = (uint32_t) boot_img[split_slot].loc.bil_address + - (uint32_t) boot_img[split_slot].hdr.ih_hdr_size; + entry_val = boot_data.imgs[split_slot].sectors[0].fa_off + + boot_data.imgs[split_slot].hdr.ih_hdr_size; *entry = (void*) entry_val; rc = SPLIT_GO_OK; -split_app_go_end: - free(descs); - return rc; -} + rc = 0; -#if MYNEWT_VAL(TEST) - -/** - * Used by unit tests. This allows a test to call boot loader functions - * without starting the boot loader. - */ -void -boot_req_set(struct boot_req *req) -{ - boot_req = req; +done: + flash_area_close(app_fap); + flash_area_close(loader_fap); + return rc; } - -#endif http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f855c453/boot/bootutil/syscfg.yml ---------------------------------------------------------------------- diff --git a/boot/bootutil/syscfg.yml b/boot/bootutil/syscfg.yml index 5d59704..cfa3d44 100644 --- a/boot/bootutil/syscfg.yml +++ b/boot/bootutil/syscfg.yml @@ -7,5 +7,3 @@ syscfg.defs: BOOTUTIL_SIGN_EC: description: 'TBD' value: '0' -pkg.cflags.IMAGE_KEYS_RSA: -DIMAGE_SIGNATURES_RSA -pkg.cflags.IMAGE_KEYS_EC: -DIMAGE_SIGNATURES_EC http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f855c453/boot/bootutil/test/src/boot_test.h ---------------------------------------------------------------------- diff --git a/boot/bootutil/test/src/boot_test.h b/boot/bootutil/test/src/boot_test.h index e883c8f..d43febf 100644 --- a/boot/bootutil/test/src/boot_test.h +++ b/boot/bootutil/test/src/boot_test.h @@ -74,8 +74,7 @@ void boot_test_util_verify_flash(const struct image_header *hdr0, int orig_slot_0, const struct image_header *hdr1, int orig_slot_1); -void boot_test_util_verify_all(const struct boot_req *req, - int expected_swap_type, +void boot_test_util_verify_all(int expected_swap_type, const struct image_header *hdr0, const struct image_header *hdr1); #ifdef __cplusplus http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f855c453/boot/bootutil/test/src/boot_test_utils.c ---------------------------------------------------------------------- diff --git a/boot/bootutil/test/src/boot_test_utils.c b/boot/bootutil/test/src/boot_test_utils.c index 3040604..40e8960 100644 --- a/boot/bootutil/test/src/boot_test_utils.c +++ b/boot/bootutil/test/src/boot_test_utils.c @@ -120,7 +120,7 @@ boot_test_util_area_write_size(int dst_idx, uint32_t off, uint32_t size) /* Don't include trailer in copy to second slot. */ desc = boot_test_area_descs + dst_idx; - trailer_start = desc->fa_size - boot_status_sz(1); + trailer_start = desc->fa_size - boot_trailer_sz(1); diff = off + size - trailer_start; if (diff > 0) { if (diff > size) { @@ -262,35 +262,51 @@ boot_test_util_write_hash(const struct image_header *hdr, int slot) TEST_ASSERT(rc == 0); } -void -boot_test_util_write_bit(int flash_area_id, struct boot_img_trailer *bit) +static void +boot_test_util_write_swap_state(int flash_area_id, + const struct boot_swap_state *state) { const struct flash_area *fap; int rc; - /* XXX: This function only works by chance. It requires that the boot - * loader have have been run once already so that its global state has been - * populated. - */ - rc = flash_area_open(flash_area_id, &fap); TEST_ASSERT_FATAL(rc == 0); - rc = flash_area_write(fap, fap->fa_size - sizeof *bit, bit, sizeof *bit); - TEST_ASSERT_FATAL(rc == 0); + switch (state->magic) { + case 0: + break; + + case BOOT_MAGIC_GOOD: + rc = boot_write_magic(fap); + TEST_ASSERT_FATAL(rc == 0); + break; + + default: + TEST_ASSERT_FATAL(0); + break; + } + + if (state->copy_done != 0xff) { + rc = boot_write_copy_done(fap); + TEST_ASSERT_FATAL(rc == 0); + } + + if (state->image_ok != 0xff) { + rc = boot_write_image_ok(fap); + TEST_ASSERT_FATAL(rc == 0); + } } void boot_test_util_mark_revert(void) { - struct boot_img_trailer bit_slot0 = { - .bit_copy_start = BOOT_IMG_MAGIC, - .bit_copy_done = 0x01, - .bit_img_ok = 0xff, - ._pad = 0xffff, + struct boot_swap_state state_slot0 = { + .magic = BOOT_MAGIC_GOOD, + .copy_done = 0x01, + .image_ok = 0xff, }; - boot_test_util_write_bit(FLASH_AREA_IMAGE_0, &bit_slot0); + boot_test_util_write_swap_state(FLASH_AREA_IMAGE_0, &state_slot0); } void @@ -371,18 +387,14 @@ boot_test_util_verify_area(const struct flash_area *area_desc, void boot_test_util_verify_status_clear(void) { - struct boot_img_trailer bit; - const struct flash_area *fap; + struct boot_swap_state state_slot0; int rc; - rc = flash_area_open(FLASH_AREA_IMAGE_0, &fap); - TEST_ASSERT(rc == 0); - - rc = flash_area_read(fap, fap->fa_size - sizeof(bit), &bit, sizeof(bit)); - TEST_ASSERT(rc == 0); + rc = boot_read_swap_state_img(0, &state_slot0); + assert(rc == 0); - TEST_ASSERT(bit.bit_copy_start != BOOT_IMG_MAGIC || - bit.bit_copy_done != 0xff); + TEST_ASSERT(state_slot0.magic != BOOT_MAGIC_UNSET || + state_slot0.copy_done != 0); } @@ -420,7 +432,7 @@ boot_test_util_verify_flash(const struct image_header *hdr0, int orig_slot_0, } void -boot_test_util_verify_all(const struct boot_req *req, int expected_swap_type, +boot_test_util_verify_all(int expected_swap_type, const struct image_header *hdr0, const struct image_header *hdr1) { @@ -433,12 +445,11 @@ 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); + rc = boot_go(&rsp); TEST_ASSERT_FATAL(rc == 0); if (expected_swap_type != BOOT_SWAP_TYPE_NONE) { http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f855c453/boot/bootutil/test/src/testcases/boot_test_invalid_hash.c ---------------------------------------------------------------------- diff --git a/boot/bootutil/test/src/testcases/boot_test_invalid_hash.c b/boot/bootutil/test/src/testcases/boot_test_invalid_hash.c index c26abfb..515ab45 100644 --- a/boot/bootutil/test/src/testcases/boot_test_invalid_hash.c +++ b/boot/bootutil/test/src/testcases/boot_test_invalid_hash.c @@ -39,14 +39,6 @@ TEST_CASE(boot_test_invalid_hash) .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), - }; - struct image_tlv tlv = { .it_type = IMAGE_TLV_SHA256, .it_len = 32 @@ -63,5 +55,5 @@ TEST_CASE(boot_test_invalid_hash) rc = boot_set_pending(); TEST_ASSERT(rc == 0); - boot_test_util_verify_all(&req, BOOT_SWAP_TYPE_NONE, &hdr0, NULL); + boot_test_util_verify_all(BOOT_SWAP_TYPE_NONE, &hdr0, NULL); } http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f855c453/boot/bootutil/test/src/testcases/boot_test_no_flag_has_hash.c ---------------------------------------------------------------------- diff --git a/boot/bootutil/test/src/testcases/boot_test_no_flag_has_hash.c b/boot/bootutil/test/src/testcases/boot_test_no_flag_has_hash.c index 6bfa845..a4f555a 100644 --- a/boot/bootutil/test/src/testcases/boot_test_no_flag_has_hash.c +++ b/boot/bootutil/test/src/testcases/boot_test_no_flag_has_hash.c @@ -39,14 +39,6 @@ TEST_CASE(boot_test_no_flag_has_hash) .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); @@ -56,5 +48,5 @@ TEST_CASE(boot_test_no_flag_has_hash) rc = boot_set_pending(); TEST_ASSERT(rc == 0); - boot_test_util_verify_all(&req, BOOT_SWAP_TYPE_NONE, &hdr0, NULL); + boot_test_util_verify_all(BOOT_SWAP_TYPE_NONE, &hdr0, NULL); } http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f855c453/boot/bootutil/test/src/testcases/boot_test_no_hash.c ---------------------------------------------------------------------- diff --git a/boot/bootutil/test/src/testcases/boot_test_no_hash.c b/boot/bootutil/test/src/testcases/boot_test_no_hash.c index 6f05d16..a5c74dd 100644 --- a/boot/bootutil/test/src/testcases/boot_test_no_hash.c +++ b/boot/bootutil/test/src/testcases/boot_test_no_hash.c @@ -39,14 +39,6 @@ TEST_CASE(boot_test_no_hash) .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); @@ -55,5 +47,5 @@ TEST_CASE(boot_test_no_hash) rc = boot_set_pending(); TEST_ASSERT(rc == 0); - boot_test_util_verify_all(&req, BOOT_SWAP_TYPE_NONE, &hdr0, NULL); + boot_test_util_verify_all(BOOT_SWAP_TYPE_NONE, &hdr0, NULL); } http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f855c453/boot/bootutil/test/src/testcases/boot_test_nv_bs_10.c ---------------------------------------------------------------------- diff --git a/boot/bootutil/test/src/testcases/boot_test_nv_bs_10.c b/boot/bootutil/test/src/testcases/boot_test_nv_bs_10.c index bb7bc9c..02d6d17 100644 --- a/boot/bootutil/test/src/testcases/boot_test_nv_bs_10.c +++ b/boot/bootutil/test/src/testcases/boot_test_nv_bs_10.c @@ -29,19 +29,11 @@ TEST_CASE(boot_test_nv_bs_10) .ih_ver = { 0, 2, 3, 4 }, }; - 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(&hdr, 0); boot_test_util_write_hash(&hdr, 0); boot_test_util_swap_areas(boot_test_slot_areas[1], BOOT_TEST_AREA_IDX_SCRATCH); - boot_test_util_verify_all(&req, BOOT_SWAP_TYPE_NONE, &hdr, NULL); + boot_test_util_verify_all(BOOT_SWAP_TYPE_NONE, &hdr, NULL); } http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f855c453/boot/bootutil/test/src/testcases/boot_test_nv_bs_11.c ---------------------------------------------------------------------- diff --git a/boot/bootutil/test/src/testcases/boot_test_nv_bs_11.c b/boot/bootutil/test/src/testcases/boot_test_nv_bs_11.c index c3376b4..16efcf1 100644 --- a/boot/bootutil/test/src/testcases/boot_test_nv_bs_11.c +++ b/boot/bootutil/test/src/testcases/boot_test_nv_bs_11.c @@ -41,14 +41,6 @@ TEST_CASE(boot_test_nv_bs_11) .ih_ver = { 1, 1, 5, 5 }, }; - 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); @@ -57,14 +49,11 @@ TEST_CASE(boot_test_nv_bs_11) rc = boot_set_pending(); boot_test_util_copy_area(5, BOOT_TEST_AREA_IDX_SCRATCH); - // XXX - boot_req_set(&req); status.idx = 0; - status.elem_sz = 1; status.state = 1; rc = boot_write_status(&status); TEST_ASSERT(rc == 0); - boot_test_util_verify_all(&req, BOOT_SWAP_TYPE_TEST, &hdr0, &hdr1); + boot_test_util_verify_all(BOOT_SWAP_TYPE_TEST, &hdr0, &hdr1); } http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f855c453/boot/bootutil/test/src/testcases/boot_test_nv_bs_11_2areas.c ---------------------------------------------------------------------- diff --git a/boot/bootutil/test/src/testcases/boot_test_nv_bs_11_2areas.c b/boot/bootutil/test/src/testcases/boot_test_nv_bs_11_2areas.c index 1cb808d..a69aedc 100644 --- a/boot/bootutil/test/src/testcases/boot_test_nv_bs_11_2areas.c +++ b/boot/bootutil/test/src/testcases/boot_test_nv_bs_11_2areas.c @@ -41,14 +41,6 @@ TEST_CASE(boot_test_nv_bs_11_2areas) .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); @@ -60,11 +52,10 @@ TEST_CASE(boot_test_nv_bs_11_2areas) boot_test_util_swap_areas(2, 5); 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_TEST, &hdr0, &hdr1); + boot_test_util_verify_all(BOOT_SWAP_TYPE_TEST, &hdr0, &hdr1); }