/*
 * Copyright (c) 2017 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 <logging/log.h>
LOG_MODULE_REGISTER(LOG_MODULE_NAME);

#include <zephyr/types.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <dfu/flash_img.h>
#include <inttypes.h>

#ifdef CONFIG_IMG_ERASE_PROGRESSIVELY
#include <dfu/mcuboot.h>
#include <drivers/flash.h>
#endif

#include <devicetree.h>
/* DT_FLASH_AREA_IMAGE_XX_YY values used below are auto-generated by DT */
#ifdef CONFIG_TRUSTED_EXECUTION_NONSECURE
#define FLASH_AREA_IMAGE_SECONDARY DT_FLASH_AREA_IMAGE_1_NONSECURE_ID
#else
#define FLASH_AREA_IMAGE_SECONDARY DT_FLASH_AREA_IMAGE_1_ID
#endif /* CONFIG_TRUSTED_EXECUTION_NONSECURE */

BUILD_ASSERT_MSG((CONFIG_IMG_BLOCK_BUF_SIZE % DT_FLASH_WRITE_BLOCK_SIZE == 0),
		 "CONFIG_IMG_BLOCK_BUF_SIZE is not a multiple of "
		 "DT_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, &sector);
	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;
	}

	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,
				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 ctx->bytes_written;
}

int flash_img_init(struct flash_img_context *ctx)
{
	ctx->bytes_written = 0;
	ctx->buf_bytes = 0U;
#ifdef CONFIG_IMG_ERASE_PROGRESSIVELY
	ctx->off_last = -1;
#endif
	return flash_area_open(FLASH_AREA_IMAGE_SECONDARY,
			       (const struct flash_area **)&(ctx->flash_area));
}
