diff --git a/include/dfu/flash_img.h b/include/dfu/flash_img.h index 413df07e1ad..5b390a44067 100644 --- a/include/dfu/flash_img.h +++ b/include/dfu/flash_img.h @@ -8,7 +8,7 @@ #ifndef ZEPHYR_INCLUDE_DFU_FLASH_IMG_H_ #define ZEPHYR_INCLUDE_DFU_FLASH_IMG_H_ -#include +#include #ifdef __cplusplus extern "C" { @@ -17,11 +17,7 @@ extern "C" { struct flash_img_context { u8_t buf[CONFIG_IMG_BLOCK_BUF_SIZE]; const struct flash_area *flash_area; - size_t bytes_written; - u16_t buf_bytes; -#ifdef CONFIG_IMG_ERASE_PROGRESSIVELY - off_t off_last; -#endif + struct stream_flash_ctx stream; }; /** diff --git a/subsys/dfu/Kconfig b/subsys/dfu/Kconfig index 8c0772d6a83..7de91f0dbc4 100644 --- a/subsys/dfu/Kconfig +++ b/subsys/dfu/Kconfig @@ -9,6 +9,7 @@ menuconfig IMG_MANAGER bool "DFU image manager" + select STREAM_FLASH help Enable support for managing DFU image. @@ -48,10 +49,10 @@ config IMG_BLOCK_BUF_SIZE Size (in Bytes) of buffer for image writer. Must be a multiple of the access alignment required by used flash driver. -config IMG_ERASE_PROGRESSIVELY +config IMG_ERASE_PROGRESSIVELY bool "Erase flash progressively when receiving new firmware" depends on MCUBOOT_IMG_MANAGER - select FLASH_PAGE_LAYOUT + select STREAM_FLASH_ERASE help If enabled, flash is erased as necessary when receiving new firmware, instead of erasing the whole image slot at once. This is necessary diff --git a/subsys/dfu/img_util/flash_img.c b/subsys/dfu/img_util/flash_img.c index d437ecff6b4..83ff72bde93 100644 --- a/subsys/dfu/img_util/flash_img.c +++ b/subsys/dfu/img_util/flash_img.c @@ -1,26 +1,19 @@ /* - * Copyright (c) 2017 Nordic Semiconductor ASA + * Copyright (c) 2017, 2020 Nordic Semiconductor ASA * Copyright (c) 2017 Linaro Limited * * SPDX-License-Identifier: Apache-2.0 */ - -#define LOG_MODULE_NAME fota_flash_block -#define LOG_LEVEL CONFIG_IMG_MANAGER_LOG_LEVEL -#include -LOG_MODULE_REGISTER(LOG_MODULE_NAME); - #include #include #include #include -#include #include -#include +#include +#include #ifdef CONFIG_IMG_ERASE_PROGRESSIVELY #include -#include #endif #include @@ -38,181 +31,19 @@ BUILD_ASSERT((CONFIG_IMG_BLOCK_BUF_SIZE % FLASH_WRITE_BLOCK_SIZE == 0), "CONFIG_IMG_BLOCK_BUF_SIZE is not a multiple of " "FLASH_WRITE_BLOCK_SIZE"); -static bool flash_verify(const struct flash_area *fa, off_t offset, - u8_t *data, size_t len) -{ - size_t size; - u32_t temp; - int rc; - - while (len) { - size = (len >= sizeof(temp)) ? sizeof(temp) : len; - rc = flash_area_read(fa, offset, &temp, size); - if (rc) { - LOG_ERR("flash_read error %d offset=0x%08lx", - rc, (long)offset); - break; - } - - if (memcmp(data, &temp, size)) { - LOG_ERR("offset=0x%08lx VERIFY FAIL. " - "expected: 0x%08x, actual: 0x%08x", - (long)offset, temp, UNALIGNED_GET(data)); - break; - } - len -= size; - offset += size; - data += size; - } - - return (len == 0) ? true : false; -} - -#ifdef CONFIG_IMG_ERASE_PROGRESSIVELY - -static int flash_sector_from_off(struct flash_area const *fap, off_t off, - struct flash_sector *sector) -{ - struct flash_pages_info page; - struct device *flash_dev; - int rc = -ENODEV; - - flash_dev = flash_area_get_device(fap); - - off += fap->fa_off; /* flash driver uses offset from memory beginning */ - - if (flash_dev) { - rc = flash_get_page_info_by_offs(flash_dev, off, &page); - if (rc == 0) { - sector->fs_off = page.start_offset; - sector->fs_size = page.size; - } - } - - return rc; -} - -/** - * Erase the image slot progressively - * - * This function erases a flash page to which offset belongs if only this page - * wasn't erased before. - * - * @param[in] ctx context of the image collection process. - * @param[in] off offset from the beginning of the image flash area beginning - * - * @return 0 on success, negative errno code on fail. - */ -static int flash_progressive_erase(struct flash_img_context *ctx, off_t off) -{ - struct flash_sector sector; - int rc; - - rc = flash_sector_from_off(ctx->flash_area, off, §or); - if (rc) { - LOG_ERR("Unable to determine flash sector size"); - } else { - if (ctx->off_last != sector.fs_off) { - ctx->off_last = sector.fs_off; - LOG_INF("Erasing sector at offset 0x%08lx", - (long)sector.fs_off); - rc = flash_area_erase(ctx->flash_area, - sector.fs_off - - ctx->flash_area->fa_off, - sector.fs_size); - if (rc) { - LOG_ERR("Error %d while erasing sector", rc); - } - } - } - - return rc; -} - -#endif /* CONFIG_IMG_ERASE_PROGRESSIVELY */ - -static int flash_sync(struct flash_img_context *ctx) -{ - int rc = 0; - - if (ctx->buf_bytes < CONFIG_IMG_BLOCK_BUF_SIZE) { - (void)memset(ctx->buf + ctx->buf_bytes, 0xFF, - CONFIG_IMG_BLOCK_BUF_SIZE - ctx->buf_bytes); - } - -#ifdef CONFIG_IMG_ERASE_PROGRESSIVELY - rc = flash_progressive_erase(ctx, ctx->bytes_written + - CONFIG_IMG_BLOCK_BUF_SIZE); - if (rc) { - LOG_ERR("flash_progressive_erase error %d offset=0x%08zx", rc, - ctx->bytes_written); - return rc; - } -#endif - - rc = flash_area_write(ctx->flash_area, ctx->bytes_written, ctx->buf, - CONFIG_IMG_BLOCK_BUF_SIZE); - if (rc) { - LOG_ERR("flash_write error %d offset=0x%08zx", rc, - ctx->bytes_written); - return rc; - } - - if (!flash_verify(ctx->flash_area, ctx->bytes_written, ctx->buf, - CONFIG_IMG_BLOCK_BUF_SIZE)) { - return -EIO; - } - - ctx->bytes_written += ctx->buf_bytes; - ctx->buf_bytes = 0U; - - return rc; -} - int flash_img_buffered_write(struct flash_img_context *ctx, u8_t *data, size_t len, bool flush) { - int processed = 0; - int rc = 0; - int buf_empty_bytes; - - while ((len - processed) >= - (buf_empty_bytes = CONFIG_IMG_BLOCK_BUF_SIZE - ctx->buf_bytes)) { - memcpy(ctx->buf + ctx->buf_bytes, data + processed, - buf_empty_bytes); - - ctx->buf_bytes = CONFIG_IMG_BLOCK_BUF_SIZE; - rc = flash_sync(ctx); - - if (rc) { - return rc; - } - - processed += buf_empty_bytes; - } - - /* place rest of the data into ctx->buf */ - if (processed < len) { - memcpy(ctx->buf + ctx->buf_bytes, - data + processed, len - processed); - ctx->buf_bytes += len - processed; - } + int rc; + rc = stream_flash_buffered_write(&ctx->stream, data, len, flush); if (!flush) { return rc; } - if (ctx->buf_bytes > 0) { - /* pad the rest of ctx->buf and write it out */ - rc = flash_sync(ctx); - - if (rc) { - return rc; - } - } #ifdef CONFIG_IMG_ERASE_PROGRESSIVELY - /* erase the image trailer area if it was not erased */ - rc = flash_progressive_erase(ctx, + rc = stream_flash_erase_page(&ctx->stream, + ctx->flash_area->fa_off + BOOT_TRAILER_IMG_STATUS_OFFS(ctx->flash_area)); if (rc) { return rc; @@ -227,30 +58,28 @@ int flash_img_buffered_write(struct flash_img_context *ctx, u8_t *data, size_t flash_img_bytes_written(struct flash_img_context *ctx) { - return ctx->bytes_written; -} - -static void init_ctx(struct flash_img_context *ctx) -{ - ctx->bytes_written = 0; - ctx->buf_bytes = 0U; -#ifdef CONFIG_IMG_ERASE_PROGRESSIVELY - ctx->off_last = -1; -#endif + return stream_flash_bytes_written(&ctx->stream); } int flash_img_init_id(struct flash_img_context *ctx, u8_t area_id) { - init_ctx(ctx); + int rc; + struct device *flash_dev; - return flash_area_open(area_id, + rc = flash_area_open(area_id, (const struct flash_area **)&(ctx->flash_area)); + if (rc) { + return rc; + } + + flash_dev = flash_area_get_device(ctx->flash_area); + + return stream_flash_init(&ctx->stream, flash_dev, ctx->buf, + CONFIG_IMG_BLOCK_BUF_SIZE, ctx->flash_area->fa_off, + ctx->flash_area->fa_size, NULL); } int flash_img_init(struct flash_img_context *ctx) { - init_ctx(ctx); - - return flash_area_open(FLASH_AREA_IMAGE_SECONDARY, - (const struct flash_area **)&(ctx->flash_area)); + return flash_img_init_id(ctx, FLASH_AREA_IMAGE_SECONDARY); }