blob: 3143a05b0be92226ad3a0fb63ce1684fe2aabd52 [file] [log] [blame]
/*
* Copyright (c) 2017, 2020 Nordic Semiconductor ASA
* Copyright (c) 2017 Linaro Limited
* Copyright (c) 2020 Gerson Fernando Budke <nandojve@gmail.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/types.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <zephyr/dfu/flash_img.h>
#include <zephyr/storage/flash_map.h>
#include <zephyr/storage/stream_flash.h>
#ifdef CONFIG_IMG_ERASE_PROGRESSIVELY
#include <zephyr/dfu/mcuboot.h>
#endif
#include <zephyr/devicetree.h>
/* FLASH_AREA_ID() values used below are auto-generated by DT */
#ifdef CONFIG_TRUSTED_EXECUTION_NONSECURE
#define UPLOAD_FLASH_AREA_ID FLASH_AREA_ID(image_1_nonsecure)
#else
#if FLASH_AREA_LABEL_EXISTS(image_1)
#define UPLOAD_FLASH_AREA_ID FLASH_AREA_ID(image_1)
#else
#define UPLOAD_FLASH_AREA_ID FLASH_AREA_ID(image_0)
#endif
#endif /* CONFIG_TRUSTED_EXECUTION_NONSECURE */
#define FLASH_WRITE_BLOCK_SIZE \
DT_PROP(DT_CHOSEN(zephyr_flash), write_block_size)
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");
int flash_img_buffered_write(struct flash_img_context *ctx, const uint8_t *data,
size_t len, bool flush)
{
int rc;
rc = stream_flash_buffered_write(&ctx->stream, data, len, flush);
if (!flush) {
return rc;
}
#ifdef CONFIG_IMG_ERASE_PROGRESSIVELY
rc = stream_flash_erase_page(&ctx->stream,
ctx->flash_area->fa_off +
BOOT_TRAILER_IMG_STATUS_OFFS(ctx->flash_area));
if (rc) {
return rc;
}
#endif
flash_area_close(ctx->flash_area);
ctx->flash_area = NULL;
return rc;
}
size_t flash_img_bytes_written(struct flash_img_context *ctx)
{
return stream_flash_bytes_written(&ctx->stream);
}
int flash_img_init_id(struct flash_img_context *ctx, uint8_t area_id)
{
int rc;
const struct device *flash_dev;
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)
{
return flash_img_init_id(ctx, UPLOAD_FLASH_AREA_ID);
}
#if defined(CONFIG_IMG_ENABLE_IMAGE_CHECK)
int flash_img_check(struct flash_img_context *ctx,
const struct flash_img_check *fic,
uint8_t area_id)
{
struct flash_area_check fac;
int rc;
if (!ctx || !fic) {
return -EINVAL;
}
rc = flash_area_open(area_id,
(const struct flash_area **)&(ctx->flash_area));
if (rc) {
return rc;
}
fac.match = fic->match;
fac.clen = fic->clen;
fac.off = 0;
fac.rbuf = ctx->buf;
fac.rblen = sizeof(ctx->buf);
rc = flash_area_check_int_sha256(ctx->flash_area, &fac);
flash_area_close(ctx->flash_area);
ctx->flash_area = NULL;
return rc;
}
#endif