From 04bf2e1bd1cd5deb706572083cdf9c5e8b249628 Mon Sep 17 00:00:00 2001 From: Findlay Feng Date: Wed, 1 Aug 2018 14:50:48 +0800 Subject: [PATCH] dfu/mcuboot: use flash_map instead of flash API Patch introduces flash_map subsystem to operate on flash footprint instead of direct operation using flash_driver API. Flash area ID is used in API instead of direct flash-bank-offsets. Changes allows to support operation on the partition in any flash device. flash_map was not available when this subsystem was introduced. Signed-off-by: Findlay Feng --- include/dfu/mcuboot.h | 14 +- subsys/dfu/Kconfig | 1 + subsys/dfu/boot/mcuboot.c | 178 +++++++++--------- .../dfu/mcuboot/nrf52840_pca10056.overlay | 38 ++++ tests/subsys/dfu/mcuboot/src/main.c | 103 +++++----- 5 files changed, 176 insertions(+), 158 deletions(-) create mode 100644 tests/subsys/dfu/mcuboot/nrf52840_pca10056.overlay diff --git a/include/dfu/mcuboot.h b/include/dfu/mcuboot.h index 085439b358f..82db0134f07 100644 --- a/include/dfu/mcuboot.h +++ b/include/dfu/mcuboot.h @@ -92,12 +92,10 @@ struct mcuboot_img_header { /** * @brief Read the MCUboot image header information from an image bank. * - * This attempts to parse the image header, which must begin at offset - * @a bank_offset from the beginning of the flash device used by - * MCUboot. + * This attempts to parse the image header, + * From the start of the @a area_id image. * - * @param bank_offset Offset of the image header from the start of the - * flash device used by MCUboot to store firmware. + * @param area_id flash_area ID of image bank which stores the image. * @param header On success, the returned header information is available * in this structure. * @param header_size Size of the header structure passed by the caller. @@ -105,7 +103,7 @@ struct mcuboot_img_header { * necessary information, an error is returned. * @return Zero on success, a negative value on error. */ -int boot_read_bank_header(u32_t bank_offset, +int boot_read_bank_header(u8_t area_id, struct mcuboot_img_header *header, size_t header_size); @@ -162,9 +160,9 @@ int boot_request_upgrade(int permanent); /** * @brief Erase the image Bank. * - * @param bank_offset address of the image bank + * @param area_id flash_area ID of image bank to be erased. * @return 0 on success, negative errno code on fail. */ -int boot_erase_img_bank(u32_t bank_offset); +int boot_erase_img_bank(u8_t area_id); #endif /* ZEPHYR_INCLUDE_DFU_MCUBOOT_H_ */ diff --git a/subsys/dfu/Kconfig b/subsys/dfu/Kconfig index 5f2e0a48d20..87d547faf1b 100644 --- a/subsys/dfu/Kconfig +++ b/subsys/dfu/Kconfig @@ -28,6 +28,7 @@ choice config MCUBOOT_IMG_MANAGER bool "Image manager for mcuboot" + select FLASH_MAP help Enable support for managing DFU image downloaded using mcuboot. endchoice diff --git a/subsys/dfu/boot/mcuboot.c b/subsys/dfu/boot/mcuboot.c index 6ed86650a83..59119c9e20f 100644 --- a/subsys/dfu/boot/mcuboot.c +++ b/subsys/dfu/boot/mcuboot.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -67,20 +68,17 @@ struct mcuboot_v1_raw_header { #define BOOT_FLAG_COPY_DONE 1 #define FLASH_MIN_WRITE_SIZE FLASH_WRITE_BLOCK_SIZE -#define FLASH_BANK0_OFFSET FLASH_AREA_IMAGE_0_OFFSET /* FLASH_AREA_IMAGE_XX_YY values used below are auto-generated thanks to DT */ -#define FLASH_BANK_SIZE FLASH_AREA_IMAGE_0_SIZE -#define FLASH_BANK1_OFFSET FLASH_AREA_IMAGE_1_OFFSET -#define FLASH_STATE_OFFSET (FLASH_AREA_IMAGE_SCRATCH_OFFSET +\ - FLASH_AREA_IMAGE_SCRATCH_SIZE) +#define FLASH_BANK0_ID DT_FLASH_AREA_IMAGE_0_ID +#define FLASH_BANK1_ID DT_FLASH_AREA_IMAGE_1_ID -#define COPY_DONE_OFFS(bank_offs) (bank_offs + FLASH_BANK_SIZE -\ +#define COPY_DONE_OFFS(bank_area) ((bank_area)->fa_size -\ BOOT_MAGIC_SZ - BOOT_MAX_ALIGN * 2) -#define IMAGE_OK_OFFS(bank_offs) (bank_offs + FLASH_BANK_SIZE - BOOT_MAGIC_SZ -\ +#define IMAGE_OK_OFFS(bank_area) ((bank_area)->fa_size - BOOT_MAGIC_SZ -\ BOOT_MAX_ALIGN) -#define MAGIC_OFFS(bank_offs) (bank_offs + FLASH_BANK_SIZE - BOOT_MAGIC_SZ) +#define MAGIC_OFFS(bank_area) ((bank_area)->fa_size - BOOT_MAGIC_SZ) static const u32_t boot_img_magic[4] = { 0xf395c277, @@ -163,72 +161,66 @@ static const struct boot_swap_table boot_swap_tables[] = { }; #define BOOT_SWAP_TABLES_COUNT (ARRAY_SIZE(boot_swap_tables)) -static struct device *flash_dev; - -static int boot_flag_offs(int flag, u32_t bank_offs, u32_t *offs) +static int boot_flag_offs(int flag, const struct flash_area *fa, u32_t *offs) { switch (flag) { case BOOT_FLAG_COPY_DONE: - *offs = COPY_DONE_OFFS(bank_offs); + *offs = COPY_DONE_OFFS(fa); return 0; case BOOT_FLAG_IMAGE_OK: - *offs = IMAGE_OK_OFFS(bank_offs); + *offs = IMAGE_OK_OFFS(fa); return 0; default: return -ENOTSUP; } } -static int boot_flash_write(off_t offs, const void *data, size_t len) -{ - int rc; - - rc = flash_write_protection_set(flash_dev, false); - if (rc) { - return rc; - } - - rc = flash_write(flash_dev, offs, data, len); - if (rc) { - return rc; - } - - rc = flash_write_protection_set(flash_dev, true); - - return rc; -} - -static int boot_flag_write(int flag, u32_t bank_offs) +static int boot_flag_write(int flag, u8_t bank_id) { + const struct flash_area *fa; u8_t buf[FLASH_MIN_WRITE_SIZE]; u32_t offs; int rc; - rc = boot_flag_offs(flag, bank_offs, &offs); + rc = flash_area_open(bank_id, &fa); + if (rc) { + return rc; + } + + rc = boot_flag_offs(flag, fa, &offs); if (rc != 0) { + flash_area_close(fa); return rc; } (void)memset(buf, BOOT_FLAG_UNSET, sizeof(buf)); buf[0] = BOOT_FLAG_SET; - rc = boot_flash_write(offs, buf, sizeof(buf)); + rc = flash_area_write(fa, offs, buf, sizeof(buf)); + flash_area_close(fa); return rc; } -static int boot_flag_read(int flag, u32_t bank_offs) +static int boot_flag_read(int flag, u8_t bank_id) { + const struct flash_area *fa; u32_t offs; int rc; u8_t flag_val; - rc = boot_flag_offs(flag, bank_offs, &offs); - if (rc != 0) { + rc = flash_area_open(bank_id, &fa); + if (rc) { return rc; } - rc = flash_read(flash_dev, offs, &flag_val, sizeof(flag_val)); + rc = boot_flag_offs(flag, fa, &offs); + if (rc != 0) { + flash_area_close(fa); + return rc; + } + + rc = flash_area_read(fa, offs, &flag_val, sizeof(flag_val)); if (rc != 0) { return rc; } @@ -236,42 +228,56 @@ static int boot_flag_read(int flag, u32_t bank_offs) return flag_val; } -static int boot_image_ok_read(u32_t bank_offs) +static int boot_image_ok_read(u8_t bank_id) { - return boot_flag_read(BOOT_FLAG_IMAGE_OK, bank_offs); + return boot_flag_read(BOOT_FLAG_IMAGE_OK, bank_id); } -static int boot_image_ok_write(u32_t bank_offs) +static int boot_image_ok_write(u8_t bank_id) { - return boot_flag_write(BOOT_FLAG_IMAGE_OK, bank_offs); + return boot_flag_write(BOOT_FLAG_IMAGE_OK, bank_id); } -static int boot_copy_done_read(u32_t bank_offs) +static int boot_copy_done_read(u8_t bank_id) { - return boot_flag_read(BOOT_FLAG_COPY_DONE, bank_offs); + return boot_flag_read(BOOT_FLAG_COPY_DONE, bank_id); } -static int boot_magic_write(u32_t bank_offs) +static int boot_magic_write(u8_t bank_id) { + const struct flash_area *fa; u32_t offs; int rc; - offs = MAGIC_OFFS(bank_offs); + rc = flash_area_open(bank_id, &fa); + if (rc) { + return rc; + } - rc = boot_flash_write(offs, boot_img_magic, BOOT_MAGIC_SZ); + offs = MAGIC_OFFS(fa); + + rc = flash_area_write(fa, offs, boot_img_magic, BOOT_MAGIC_SZ); + flash_area_close(fa); return rc; } -static int boot_read_v1_header(u32_t bank_offset, +static int boot_read_v1_header(u8_t area_id, struct mcuboot_v1_raw_header *v1_raw) { + const struct flash_area *fa; int rc; + rc = flash_area_open(area_id, &fa); + if (rc) { + return rc; + } + /* * Read and sanity-check the raw header. */ - rc = flash_read(flash_dev, bank_offset, v1_raw, sizeof(*v1_raw)); + rc = flash_area_read(fa, 0, v1_raw, sizeof(*v1_raw)); + flash_area_close(fa); if (rc) { return rc; } @@ -302,7 +308,7 @@ static int boot_read_v1_header(u32_t bank_offset, return 0; } -int boot_read_bank_header(u32_t bank_offset, +int boot_read_bank_header(u8_t area_id, struct mcuboot_img_header *header, size_t header_size) { @@ -318,7 +324,7 @@ int boot_read_bank_header(u32_t bank_offset, if (header_size < v1_min_size) { return -ENOMEM; } - rc = boot_read_v1_header(bank_offset, &v1_raw); + rc = boot_read_v1_header(area_id, &v1_raw); if (rc) { return rc; } @@ -360,14 +366,22 @@ static int boot_magic_code_check(const u32_t *magic) return BOOT_MAGIC_UNSET; } -static int boot_magic_state_read(u32_t bank_offs) +static int boot_magic_state_read(u8_t bank_id) { - u32_t magic[4]; + const struct flash_area *fa; + u32_t magic[(sizeof(u32_t) - 1 + BOOT_MAGIC_SZ) / sizeof(u32_t)]; u32_t offs; int rc; - offs = MAGIC_OFFS(bank_offs); - rc = flash_read(flash_dev, offs, magic, sizeof(magic)); + rc = flash_area_open(bank_id, &fa); + if (rc) { + return rc; + } + + offs = MAGIC_OFFS(fa); + rc = flash_area_read(fa, offs, magic, BOOT_MAGIC_SZ); + flash_area_close(fa); + if (rc != 0) { return rc; } @@ -375,25 +389,25 @@ static int boot_magic_state_read(u32_t bank_offs) return boot_magic_code_check(magic); } -static int boot_read_swap_state(u32_t bank_offs, struct boot_swap_state *state) +static int boot_read_swap_state(u8_t bank_id, struct boot_swap_state *state) { int rc; - rc = boot_magic_state_read(bank_offs); + rc = boot_magic_state_read(bank_id); if (rc < 0) { return rc; } state->magic = rc; - if (bank_offs != FLASH_AREA_IMAGE_SCRATCH_OFFSET) { - rc = boot_copy_done_read(bank_offs); + if (bank_id != DT_FLASH_AREA_IMAGE_SCRATCH_ID) { + rc = boot_copy_done_read(bank_id); if (rc < 0) { return rc; } state->copy_done = rc; } - rc = boot_image_ok_read(bank_offs); + rc = boot_image_ok_read(bank_id); if (rc < 0) { return rc; } @@ -410,12 +424,12 @@ int boot_swap_type(void) int rc; int i; - rc = boot_read_swap_state(FLASH_BANK0_OFFSET, &state_slot0); + rc = boot_read_swap_state(FLASH_BANK0_ID, &state_slot0); if (rc != 0) { return rc; } - rc = boot_read_swap_state(FLASH_BANK1_OFFSET, &state_slot1); + rc = boot_read_swap_state(FLASH_BANK1_ID, &state_slot1); if (rc != 0) { return rc; } @@ -448,9 +462,9 @@ int boot_request_upgrade(int permanent) { int rc; - rc = boot_magic_write(FLASH_BANK1_OFFSET); + rc = boot_magic_write(FLASH_BANK1_ID); if (rc == 0 && permanent) { - rc = boot_image_ok_write(FLASH_BANK1_OFFSET); + rc = boot_image_ok_write(FLASH_BANK1_ID); } return rc; @@ -458,54 +472,36 @@ int boot_request_upgrade(int permanent) bool boot_is_img_confirmed(void) { - return boot_image_ok_read(FLASH_BANK0_OFFSET) == BOOT_FLAG_SET; + return boot_image_ok_read(FLASH_BANK0_ID) == BOOT_FLAG_SET; } int boot_write_img_confirmed(void) { int rc; - if (boot_image_ok_read(FLASH_BANK0_OFFSET) != BOOT_FLAG_UNSET) { + if (boot_image_ok_read(FLASH_BANK0_ID) != BOOT_FLAG_UNSET) { /* Already confirmed. */ return 0; } - rc = boot_image_ok_write(FLASH_BANK0_OFFSET); + rc = boot_image_ok_write(FLASH_BANK0_ID); return rc; } -int boot_erase_img_bank(u32_t bank_offset) +int boot_erase_img_bank(u8_t area_id) { + const struct flash_area *fa; int rc; - rc = flash_write_protection_set(flash_dev, false); + rc = flash_area_open(area_id, &fa); if (rc) { return rc; } - rc = flash_erase(flash_dev, bank_offset, FLASH_BANK_SIZE); - if (rc) { - return rc; - } + rc = flash_area_erase(fa, 0, fa->fa_size); - rc = flash_write_protection_set(flash_dev, true); + flash_area_close(fa); return rc; } - -static int boot_init(struct device *dev) -{ - ARG_UNUSED(dev); -#if defined(DT_FLASH_DEV_NAME) - flash_dev = device_get_binding(DT_FLASH_DEV_NAME); -#elif defined(DT_SPI_NOR_DRV_NAME) - flash_dev = device_get_binding(DT_SPI_NOR_DRV_NAME); -#endif - if (!flash_dev) { - return -ENODEV; - } - return 0; -} - -SYS_INIT(boot_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY); diff --git a/tests/subsys/dfu/mcuboot/nrf52840_pca10056.overlay b/tests/subsys/dfu/mcuboot/nrf52840_pca10056.overlay new file mode 100644 index 00000000000..4ef7773b4ae --- /dev/null +++ b/tests/subsys/dfu/mcuboot/nrf52840_pca10056.overlay @@ -0,0 +1,38 @@ +/* Copyright (c) 2019 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&flash0 { + /* + * For more information, see: + * http://docs.zephyrproject.org/latest/guides/dts/index.html#flash-partitions + */ + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x000000000 0x0000E000>; + }; + slot0_partition: partition@c000 { + label = "image-0"; + reg = <0x0000E000 0x000068000>; + }; + slot1_partition: partition@75000 { + label = "image-1"; + reg = <0x00076000 0x000068000>; + }; + scratch_partition: partition@de000 { + label = "image-scratch"; + reg = <0x000de000 0x0001e000>; + }; + storage_partition: partition@fc000 { + label = "storage"; + reg = <0x000fc000 0x00004000>; + }; + }; +}; diff --git a/tests/subsys/dfu/mcuboot/src/main.c b/tests/subsys/dfu/mcuboot/src/main.c index c6119acdd84..f41a99d9060 100644 --- a/tests/subsys/dfu/mcuboot/src/main.c +++ b/tests/subsys/dfu/mcuboot/src/main.c @@ -5,7 +5,7 @@ */ #include -#include +#include #include #define BOOT_MAGIC_VAL_W0 0xf395c277 @@ -17,44 +17,32 @@ void test_bank_erase(void) { - struct device *flash_dev; + const struct flash_area *fa; u32_t temp; - u32_t temp2 = 0x5a; + u32_t temp2 = 0x5a5a5a5a; off_t offs; int ret; - flash_dev = device_get_binding(DT_FLASH_DEV_NAME); - - for (offs = FLASH_AREA_IMAGE_1_OFFSET; - offs < FLASH_AREA_IMAGE_1_OFFSET + FLASH_AREA_IMAGE_1_SIZE; - offs += sizeof(temp)) { - ret = flash_read(flash_dev, offs, &temp, sizeof(temp)); - zassert_true(ret == 0, "Reading from flash"); - if (temp != 0xFFFFFFFF) { - ret = flash_write_protection_set(flash_dev, false); - zassert_true(ret == 0, "Disabling flash protection"); - - ret = flash_write(flash_dev, offs, &temp2, - sizeof(temp)); - zassert_true(ret == 0, "Writing to flash"); - - ret = flash_write_protection_set(flash_dev, true); - zassert_true(ret == 0, "Enabling flash protection"); - } - } - - zassert(boot_erase_img_bank(FLASH_AREA_IMAGE_1_OFFSET) == 0, - "pass", "fail"); - - if (!flash_dev) { - printf("Nordic nRF5 flash driver was not found!\n"); + ret = flash_area_open(DT_FLASH_AREA_IMAGE_1_ID, &fa); + if (ret) { + printf("Flash driver was not found!\n"); return; } - for (offs = FLASH_AREA_IMAGE_1_OFFSET; - offs < FLASH_AREA_IMAGE_1_OFFSET + FLASH_AREA_IMAGE_1_SIZE; - offs += sizeof(temp)) { - ret = flash_read(flash_dev, offs, &temp, sizeof(temp)); + for (offs = 0; offs < fa->fa_size; offs += sizeof(temp)) { + ret = flash_area_read(fa, offs, &temp, sizeof(temp)); + zassert_true(ret == 0, "Reading from flash"); + if (temp == 0xFFFFFFFF) { + ret = flash_area_write(fa, offs, &temp2, sizeof(temp)); + zassert_true(ret == 0, "Writing to flash"); + } + } + + zassert(boot_erase_img_bank(DT_FLASH_AREA_IMAGE_1_ID) == 0, + "pass", "fail"); + + for (offs = 0; offs < fa->fa_size; offs += sizeof(temp)) { + ret = flash_area_read(fa, offs, &temp, sizeof(temp)); zassert_true(ret == 0, "Reading from flash"); zassert(temp == 0xFFFFFFFF, "pass", "fail"); } @@ -62,7 +50,7 @@ void test_bank_erase(void) void test_request_upgrade(void) { - struct device *flash_dev; + const struct flash_area *fa; const u32_t expectation[6] = { 0xffffffff, 0xffffffff, @@ -74,25 +62,27 @@ void test_request_upgrade(void) u32_t readout[ARRAY_SIZE(expectation)]; int ret; - flash_dev = device_get_binding(DT_FLASH_DEV_NAME); + ret = flash_area_open(DT_FLASH_AREA_IMAGE_1_ID, &fa); + if (ret) { + printf("Flash driver was not found!\n"); + return; + } zassert(boot_request_upgrade(false) == 0, "pass", "fail"); - ret = flash_read(flash_dev, FLASH_AREA_IMAGE_1_OFFSET + - FLASH_AREA_IMAGE_1_SIZE - sizeof(expectation), - &readout, sizeof(readout)); + ret = flash_area_read(fa, fa->fa_size - sizeof(expectation), + &readout, sizeof(readout)); zassert_true(ret == 0, "Read from flash"); zassert(memcmp(expectation, readout, sizeof(expectation)) == 0, "pass", "fail"); - boot_erase_img_bank(FLASH_AREA_IMAGE_1_OFFSET); + boot_erase_img_bank(DT_FLASH_AREA_IMAGE_1_ID); zassert(boot_request_upgrade(true) == 0, "pass", "fail"); - ret = flash_read(flash_dev, FLASH_AREA_IMAGE_1_OFFSET + - FLASH_AREA_IMAGE_1_SIZE - sizeof(expectation), - &readout, sizeof(readout)); + ret = flash_area_read(fa, fa->fa_size - sizeof(expectation), + &readout, sizeof(readout)); zassert_true(ret == 0, "Read from flash"); zassert(memcmp(&expectation[2], &readout[2], sizeof(expectation) - @@ -105,37 +95,32 @@ void test_write_confirm(void) { const u32_t img_magic[4] = BOOT_MAGIC_VALUES; u32_t readout[ARRAY_SIZE(img_magic)]; - struct device *flash_dev; + const struct flash_area *fa; int ret; - flash_dev = device_get_binding(DT_FLASH_DEV_NAME); + ret = flash_area_open(DT_FLASH_AREA_IMAGE_0_ID, &fa); + if (ret) { + printf("Flash driver was not found!\n"); + return; + } - zassert(boot_erase_img_bank(FLASH_AREA_IMAGE_0_OFFSET) == 0, + zassert(boot_erase_img_bank(DT_FLASH_AREA_IMAGE_0_ID) == 0, "pass", "fail"); - ret = flash_read(flash_dev, FLASH_AREA_IMAGE_0_OFFSET + - FLASH_AREA_IMAGE_0_SIZE - sizeof(img_magic), &readout, - sizeof(img_magic)); + ret = flash_area_read(fa, fa->fa_size - sizeof(img_magic), + &readout, sizeof(img_magic)); zassert_true(ret == 0, "Read from flash"); if (memcmp(img_magic, readout, sizeof(img_magic)) != 0) { - ret = flash_write_protection_set(flash_dev, false); - zassert_true(ret == 0, "Disable flash protection"); - - ret = flash_write(flash_dev, FLASH_AREA_IMAGE_0_OFFSET + - FLASH_AREA_IMAGE_0_SIZE - 16, - img_magic, 16); + ret = flash_area_write(fa, fa->fa_size - 16, + img_magic, 16); zassert_true(ret == 0, "Write to flash"); - - ret = flash_write_protection_set(flash_dev, true); - zassert_true(ret == 0, "Enable flash protection"); } zassert(boot_write_img_confirmed() == 0, "pass", "fail"); - ret = flash_read(flash_dev, FLASH_AREA_IMAGE_0_OFFSET + - FLASH_AREA_IMAGE_0_SIZE - 24, readout, - sizeof(readout[0])); + ret = flash_area_read(fa, fa->fa_size - 24, readout, + sizeof(readout[0])); zassert_true(ret == 0, "Read from flash"); zassert_equal(1, readout[0] & 0xff, "confirmation error");