DFU: add module for store the image
Store image in sequence of certain blocks. Module is intended to be use by a higher-level image management protocol module Signed-off-by: Michael Scott <michael.scott@linaro.org> Signed-off-by: Marti Bolivar <marti.bolivar@linaro.org> Signed-off-by: Andrzej Puzdrowski <andrzej.puzdrowski@nordicsemi.no>
This commit is contained in:
parent
49fccdd2ea
commit
25c6610a65
5 changed files with 231 additions and 0 deletions
63
include/dfu/flash_img.h
Normal file
63
include/dfu/flash_img.h
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017 Nordic Semiconductor ASA
|
||||||
|
* Copyright (c) 2017 Linaro Limited
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __FLASH_IMG_H__
|
||||||
|
#define __FLASH_IMG_H__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct flash_img_context {
|
||||||
|
u8_t buf[CONFIG_IMG_BLOCK_BUF_SIZE];
|
||||||
|
struct device *dev;
|
||||||
|
size_t bytes_written;
|
||||||
|
u16_t buf_bytes;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize context needed for writing the image to the flash.
|
||||||
|
*
|
||||||
|
* @param ctx context to be initialized
|
||||||
|
* @param dev flash driver to used while writing the image
|
||||||
|
*/
|
||||||
|
void flash_img_init(struct flash_img_context *ctx, struct device *dev);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Read number of bytes of the image written to the flash.
|
||||||
|
*
|
||||||
|
* @param ctx context
|
||||||
|
*
|
||||||
|
* @return Number of bytes written to the image flash.
|
||||||
|
*/
|
||||||
|
size_t flash_img_bytes_written(struct flash_img_context *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Process input buffers to be written to the image slot 1. flash
|
||||||
|
* memory in single blocks. Will store remainder between calls.
|
||||||
|
*
|
||||||
|
* A final call to this function with flush set to true
|
||||||
|
* will write out the remaining block buffer to flash. Since flash is written to
|
||||||
|
* in blocks, the contents of flash from the last byte written up to the next
|
||||||
|
* multiple of CONFIG_IMG_BLOCK_BUF_SIZE is padded with 0xff.
|
||||||
|
*
|
||||||
|
* @param ctx context
|
||||||
|
* @param data data to write
|
||||||
|
* @param len Number of bytes to write
|
||||||
|
* @param flush when true this forces any buffered
|
||||||
|
* data to be written to flash
|
||||||
|
*
|
||||||
|
* @return 0 on success, negative errno code on fail
|
||||||
|
*/
|
||||||
|
int flash_img_buffered_write(struct flash_img_context *ctx, u8_t *data,
|
||||||
|
size_t len, bool flush);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __FLASH_IMG_H__ */
|
|
@ -32,4 +32,31 @@ config MCUBOOT_IMG_MANAGER
|
||||||
Enable support for managing DFU image downloaded using mcuboot.
|
Enable support for managing DFU image downloaded using mcuboot.
|
||||||
endchoice
|
endchoice
|
||||||
|
|
||||||
|
config IMG_BLOCK_BUF_SIZE
|
||||||
|
int
|
||||||
|
depends on MCUBOOT_IMG_MANAGER
|
||||||
|
prompt "Image writer buffer size"
|
||||||
|
default 512
|
||||||
|
help
|
||||||
|
Size (in Bytes) of buffer for image writer. Must be a multiple of
|
||||||
|
the access alignment required by used flash driver.
|
||||||
|
|
||||||
|
config SYS_LOG_IMG_MANAGER_LEVEL
|
||||||
|
int "Image manager Log level"
|
||||||
|
depends on SYS_LOG && MCUBOOT_IMG_MANAGER
|
||||||
|
default 0
|
||||||
|
range 0 4
|
||||||
|
help
|
||||||
|
Sets log level for the image manager.
|
||||||
|
Levels are:
|
||||||
|
|
||||||
|
- 0 OFF: do not write
|
||||||
|
|
||||||
|
- 1 ERROR: only write SYS_LOG_ERR
|
||||||
|
|
||||||
|
- 2 WARNING: write SYS_LOG_WRN in addition to previous level
|
||||||
|
|
||||||
|
- 3 INFO: write SYS_LOG_INF in addition to previous levels
|
||||||
|
|
||||||
|
- 4 DEBUG: write SYS_LOG_DBG in addition to previous levels
|
||||||
endmenu
|
endmenu
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
obj-$(CONFIG_MCUBOOT_IMG_MANAGER) += boot/
|
obj-$(CONFIG_MCUBOOT_IMG_MANAGER) += boot/
|
||||||
|
obj-$(CONFIG_MCUBOOT_IMG_MANAGER) += img_util/
|
||||||
|
|
3
subsys/dfu/img_util/Makefile
Normal file
3
subsys/dfu/img_util/Makefile
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
obj-$(CONFIG_MCUBOOT_IMG_MANAGER) += flash_img.o
|
||||||
|
ccflags-$(CONFIG_MCUBOOT_IMG_MANAGER) += -I${ZEPHYR_BASE}/include/dfu
|
||||||
|
ccflags-$(CONFIG_MCUBOOT_IMG_MANAGER) += -I${ZEPHYR_BASE}/subsys/dfu
|
137
subsys/dfu/img_util/flash_img.c
Normal file
137
subsys/dfu/img_util/flash_img.c
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017 Nordic Semiconductor ASA
|
||||||
|
* Copyright (c) 2017 Linaro Limited
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define SYS_LOG_DOMAIN "fota/flash_block"
|
||||||
|
#define SYS_LOG_LEVEL CONFIG_SYS_LOG_IMG_MANAGER_LEVEL
|
||||||
|
#include <logging/sys_log.h>
|
||||||
|
|
||||||
|
#include <zephyr/types.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <flash.h>
|
||||||
|
#include "boot/mcuboot_constraints.h"
|
||||||
|
#include "flash_img.h"
|
||||||
|
|
||||||
|
BUILD_ASSERT_MSG((CONFIG_IMG_BLOCK_BUF_SIZE % FLASH_ALIGN == 0),
|
||||||
|
"CONFIG_IMG_BLOCK_BUF_SIZE is not multiple of FLASH_ALIGN");
|
||||||
|
|
||||||
|
static bool flash_verify(struct device *dev, 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_read(dev, offset, &temp, size);
|
||||||
|
if (rc) {
|
||||||
|
SYS_LOG_ERR("flash_read error %d offset=0x%08x",
|
||||||
|
rc, offset);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memcmp(data, &temp, size)) {
|
||||||
|
SYS_LOG_ERR("offset=0x%08x VERIFY FAIL. "
|
||||||
|
"expected: 0x%08x, actual: 0x%08x",
|
||||||
|
offset, temp, *(__packed u32_t*)data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
len -= size;
|
||||||
|
offset += size;
|
||||||
|
data += size;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (len == 0) ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* buffer data into block writes */
|
||||||
|
static int flash_block_write(struct flash_img_context *ctx, off_t offset,
|
||||||
|
u8_t *data, size_t len, bool finished)
|
||||||
|
{
|
||||||
|
int processed = 0;
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
while ((len - processed) >
|
||||||
|
(CONFIG_IMG_BLOCK_BUF_SIZE - ctx->buf_bytes)) {
|
||||||
|
memcpy(ctx->buf + ctx->buf_bytes, data + processed,
|
||||||
|
(CONFIG_IMG_BLOCK_BUF_SIZE - ctx->buf_bytes));
|
||||||
|
|
||||||
|
flash_write_protection_set(ctx->dev, false);
|
||||||
|
rc = flash_write(ctx->dev, offset + ctx->bytes_written,
|
||||||
|
ctx->buf, CONFIG_IMG_BLOCK_BUF_SIZE);
|
||||||
|
flash_write_protection_set(ctx->dev, true);
|
||||||
|
if (rc) {
|
||||||
|
SYS_LOG_ERR("flash_write error %d offset=0x%08x",
|
||||||
|
rc, offset + ctx->bytes_written);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!flash_verify(ctx->dev, offset + ctx->bytes_written,
|
||||||
|
ctx->buf, CONFIG_IMG_BLOCK_BUF_SIZE)) {
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->bytes_written += CONFIG_IMG_BLOCK_BUF_SIZE;
|
||||||
|
processed += (CONFIG_IMG_BLOCK_BUF_SIZE - ctx->buf_bytes);
|
||||||
|
ctx->buf_bytes = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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 (finished && ctx->buf_bytes > 0) {
|
||||||
|
/* pad the rest of ctx->buf and write it out */
|
||||||
|
memset(ctx->buf + ctx->buf_bytes, 0xFF,
|
||||||
|
CONFIG_IMG_BLOCK_BUF_SIZE - ctx->buf_bytes);
|
||||||
|
|
||||||
|
flash_write_protection_set(ctx->dev, false);
|
||||||
|
rc = flash_write(ctx->dev, offset + ctx->bytes_written,
|
||||||
|
ctx->buf, CONFIG_IMG_BLOCK_BUF_SIZE);
|
||||||
|
flash_write_protection_set(ctx->dev, true);
|
||||||
|
if (rc) {
|
||||||
|
SYS_LOG_ERR("flash_write error %d offset=0x%08x",
|
||||||
|
rc, offset + ctx->bytes_written);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!flash_verify(ctx->dev, offset + ctx->bytes_written,
|
||||||
|
ctx->buf, CONFIG_IMG_BLOCK_BUF_SIZE)) {
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->bytes_written = ctx->bytes_written + ctx->buf_bytes;
|
||||||
|
ctx->buf_bytes = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t flash_img_bytes_written(struct flash_img_context *ctx)
|
||||||
|
{
|
||||||
|
return ctx->bytes_written;
|
||||||
|
}
|
||||||
|
|
||||||
|
void flash_img_init(struct flash_img_context *ctx, struct device *dev)
|
||||||
|
{
|
||||||
|
ctx->dev = dev;
|
||||||
|
ctx->bytes_written = 0;
|
||||||
|
ctx->buf_bytes = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int flash_img_buffered_write(struct flash_img_context *ctx, u8_t *data,
|
||||||
|
size_t len, bool flush)
|
||||||
|
{
|
||||||
|
return flash_block_write(ctx, FLASH_AREA_IMAGE_1_OFFSET, data, len,
|
||||||
|
flush);
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue