Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | /*
* 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>
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%08"PRIx32,
rc, (u32_t)offset);
break;
}
if (memcmp(data, &temp, size)) {
LOG_ERR("offset=0x%08"PRIx32" VERIFY FAIL. "
"expected: 0x%08x, actual: 0x%08x",
(u32_t)offset, temp, UNALIGNED_GET(data));
break;
}
len -= size;
offset += size;
data += size;
}
return (len == 0) ? true : false;
}
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);
}
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%08" PRIx32, rc,
(u32_t)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;
}
}
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;
return flash_area_open(DT_FLASH_AREA_IMAGE_1_ID,
(const struct flash_area **)&(ctx->flash_area));
}
|