modules: introduce MCUBOOT_BOOTUTIL module
Some parts of subsys/dfu/boot code are re-implementations of what is implemented in the MCUBoot repository. Mcuboot's repository already provide implementation of function required for application for interact with the MCUboot. This patch introduces new MCUBOOT_BOOTUTIL module which covers common code which is used in the bootloader and the chainnloaded application. dfu/boot: use MCUBoot's source code Module was reworked so it start using MCUBoot's bootutil_public API instead of copied code. Reworked boot_is_img_confirmed() used MCUBoot's API for determine image_ok flag. mcuboot_shell switchd to use MCUboot's boot_read_swap_state_by_id() This is MCUBoot function, use it for avoid linking conflict. test/subsys/mcuboot: fix `test_write_confirm` dfu/boot library was reworked so it uses MCUboot's bootutil_public library whenever it can. The library required that image was marked as copy-done before it can be pending. This patch adds such mark which fixes the test. Signed-off-by: Andrzej Puzdrowski <andrzej.puzdrowski@nordicsemi.no>
This commit is contained in:
parent
9bfee48d5d
commit
049dac2a8a
10 changed files with 101 additions and 535 deletions
|
@ -15,6 +15,8 @@
|
|||
|
||||
#include <sys/__assert.h>
|
||||
#include <sys/byteorder.h>
|
||||
|
||||
#include "bootutil/bootutil_public.h"
|
||||
#include <dfu/mcuboot.h>
|
||||
|
||||
#include "mcuboot_priv.h"
|
||||
|
@ -55,333 +57,6 @@ struct mcuboot_v1_raw_header {
|
|||
* End of strict defines
|
||||
*/
|
||||
|
||||
#define BOOT_FLAG_IMAGE_OK 0
|
||||
#define BOOT_FLAG_COPY_DONE 1
|
||||
|
||||
#define FLASH_MIN_WRITE_SIZE \
|
||||
DT_PROP(DT_CHOSEN(zephyr_flash), write_block_size)
|
||||
|
||||
#ifdef CONFIG_MCUBOOT_TRAILER_SWAP_TYPE
|
||||
#define SWAP_TYPE_OFFS(bank_area) ((bank_area)->fa_size -\
|
||||
BOOT_MAGIC_SZ - BOOT_MAX_ALIGN * 3)
|
||||
#endif
|
||||
|
||||
#define COPY_DONE_OFFS(bank_area) ((bank_area)->fa_size -\
|
||||
BOOT_MAGIC_SZ - BOOT_MAX_ALIGN * 2)
|
||||
|
||||
#define IMAGE_OK_OFFS(bank_area) ((bank_area)->fa_size - BOOT_MAGIC_SZ -\
|
||||
BOOT_MAX_ALIGN)
|
||||
#define MAGIC_OFFS(bank_area) ((bank_area)->fa_size - BOOT_MAGIC_SZ)
|
||||
|
||||
#if defined(CONFIG_BOOTLOADER_MCUBOOT) || defined(CONFIG_ZTEST)
|
||||
static const uint32_t boot_img_magic[4] = {
|
||||
0xf395c277,
|
||||
0x7fefd260,
|
||||
0x0f505235,
|
||||
0x8079b62c,
|
||||
};
|
||||
|
||||
#define BOOT_MAGIC_ARR_SZ ARRAY_SIZE(boot_img_magic)
|
||||
#endif
|
||||
|
||||
struct boot_swap_table {
|
||||
/** For each field, a value of 0 means "any". */
|
||||
uint8_t magic_primary_slot;
|
||||
uint8_t magic_secondary_slot;
|
||||
uint8_t image_ok_primary_slot;
|
||||
uint8_t image_ok_secondary_slot;
|
||||
uint8_t copy_done_primary_slot;
|
||||
|
||||
uint8_t swap_type;
|
||||
};
|
||||
|
||||
#ifdef FLASH_AREA_IMAGE_SECONDARY
|
||||
/**
|
||||
* This set of tables maps image trailer contents to swap operation type.
|
||||
* When searching for a match, these tables must be iterated sequentially.
|
||||
*
|
||||
* NOTE: the table order is very important. The settings in the secondary
|
||||
* slot always are priority to the primary slot and should be located
|
||||
* earlier in the table.
|
||||
*
|
||||
* The table lists only states where there is action needs to be taken by
|
||||
* the bootloader, as in starting/finishing a swap operation.
|
||||
*/
|
||||
static const struct boot_swap_table boot_swap_tables[] = {
|
||||
{
|
||||
/* | slot-0 | slot-1 |
|
||||
*----------+------------+------------|
|
||||
* magic | Any | Good |
|
||||
* image-ok | Any | Unset |
|
||||
* ---------+------------+------------+
|
||||
* swap: test |
|
||||
* -----------------------------------'
|
||||
*/
|
||||
.magic_primary_slot = BOOT_MAGIC_ANY,
|
||||
.magic_secondary_slot = BOOT_MAGIC_GOOD,
|
||||
.image_ok_primary_slot = BOOT_FLAG_ANY,
|
||||
.image_ok_secondary_slot = BOOT_FLAG_UNSET,
|
||||
.copy_done_primary_slot = BOOT_FLAG_ANY,
|
||||
.swap_type = BOOT_SWAP_TYPE_TEST,
|
||||
},
|
||||
{
|
||||
/* | slot-0 | slot-1 |
|
||||
*----------+------------+------------|
|
||||
* magic | Any | Good |
|
||||
* image-ok | Any | 0x01 |
|
||||
* ---------+------------+------------+
|
||||
* swap: permanent |
|
||||
* -----------------------------------'
|
||||
*/
|
||||
.magic_primary_slot = BOOT_MAGIC_ANY,
|
||||
.magic_secondary_slot = BOOT_MAGIC_GOOD,
|
||||
.image_ok_primary_slot = BOOT_FLAG_ANY,
|
||||
.image_ok_secondary_slot = BOOT_FLAG_SET,
|
||||
.copy_done_primary_slot = BOOT_FLAG_ANY,
|
||||
.swap_type = BOOT_SWAP_TYPE_PERM,
|
||||
},
|
||||
{
|
||||
/* | slot-0 | slot-1 |
|
||||
*----------+------------+------------|
|
||||
* magic | Good | Unset |
|
||||
* image-ok | Unset | Any |
|
||||
* ---------+------------+------------+
|
||||
* swap: revert (test image running) |
|
||||
* -----------------------------------'
|
||||
*/
|
||||
.magic_primary_slot = BOOT_MAGIC_GOOD,
|
||||
.magic_secondary_slot = BOOT_MAGIC_UNSET,
|
||||
.image_ok_primary_slot = BOOT_FLAG_UNSET,
|
||||
.image_ok_secondary_slot = BOOT_FLAG_ANY,
|
||||
.copy_done_primary_slot = BOOT_FLAG_SET,
|
||||
.swap_type = BOOT_SWAP_TYPE_REVERT,
|
||||
},
|
||||
};
|
||||
#define BOOT_SWAP_TABLES_COUNT (ARRAY_SIZE(boot_swap_tables))
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BOOTLOADER_MCUBOOT) || defined(CONFIG_ZTEST)
|
||||
static int boot_magic_decode(const uint32_t *magic)
|
||||
{
|
||||
if (memcmp(magic, boot_img_magic, BOOT_MAGIC_SZ) == 0) {
|
||||
return BOOT_MAGIC_GOOD;
|
||||
}
|
||||
|
||||
return BOOT_MAGIC_BAD;
|
||||
}
|
||||
|
||||
static int boot_flag_decode(uint8_t flag)
|
||||
{
|
||||
if (flag != BOOT_FLAG_SET) {
|
||||
return BOOT_FLAG_BAD;
|
||||
}
|
||||
|
||||
return BOOT_FLAG_SET;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BOOTLOADER_MCUBOOT) || defined(CONFIG_ZTEST)
|
||||
int flash_area_read_is_empty(const struct flash_area *fa, uint32_t off,
|
||||
void *dst, uint32_t len)
|
||||
{
|
||||
const uint8_t erase_val = flash_area_erased_val(fa);
|
||||
uint8_t *u8dst;
|
||||
uint8_t i;
|
||||
int rc;
|
||||
|
||||
rc = flash_area_read(fa, off, dst, len);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
for (i = 0, u8dst = (uint8_t *)dst; i < len; i++) {
|
||||
if (u8dst[i] != erase_val) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int erased_flag_val(uint8_t bank_id)
|
||||
{
|
||||
const struct flash_area *fa;
|
||||
int rc;
|
||||
|
||||
rc = flash_area_open(bank_id, &fa);
|
||||
if (rc) {
|
||||
return -EINVAL;
|
||||
}
|
||||
return flash_area_erased_val(fa);
|
||||
}
|
||||
|
||||
#if !defined(CONFIG_BOOTLOADER_MCUBOOT) && !defined(CONFIG_ZTEST)
|
||||
/* Provided by MCUBoot */
|
||||
int boot_magic_compatible_check(uint8_t tbl_val, uint8_t val);
|
||||
#else
|
||||
/**
|
||||
* Determines if a status source table is satisfied by the specified magic
|
||||
* code.
|
||||
*
|
||||
* @param tbl_val A magic field from a status source table.
|
||||
* @param val The magic value in a trailer, encoded as a
|
||||
* BOOT_MAGIC_[...].
|
||||
*
|
||||
* @return 1 if the two values are compatible;
|
||||
* 0 otherwise.
|
||||
*/
|
||||
int boot_magic_compatible_check(uint8_t tbl_val, uint8_t val)
|
||||
{
|
||||
switch (tbl_val) {
|
||||
case BOOT_MAGIC_ANY:
|
||||
return 1;
|
||||
|
||||
case BOOT_MAGIC_NOTGOOD:
|
||||
return val != BOOT_MAGIC_GOOD;
|
||||
|
||||
default:
|
||||
return tbl_val == val;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
static int boot_flag_offs(int flag, const struct flash_area *fa, uint32_t *offs)
|
||||
{
|
||||
switch (flag) {
|
||||
case BOOT_FLAG_COPY_DONE:
|
||||
*offs = COPY_DONE_OFFS(fa);
|
||||
return 0;
|
||||
case BOOT_FLAG_IMAGE_OK:
|
||||
*offs = IMAGE_OK_OFFS(fa);
|
||||
return 0;
|
||||
default:
|
||||
return -ENOTSUP;
|
||||
}
|
||||
}
|
||||
|
||||
static int boot_write_trailer_byte(const struct flash_area *fa, uint32_t off,
|
||||
uint8_t val)
|
||||
{
|
||||
uint8_t buf[BOOT_MAX_ALIGN];
|
||||
uint8_t align;
|
||||
uint8_t erased_val;
|
||||
int rc;
|
||||
|
||||
align = flash_area_align(fa);
|
||||
__ASSERT_NO_MSG(align <= BOOT_MAX_ALIGN);
|
||||
erased_val = flash_area_erased_val(fa);
|
||||
memset(buf, erased_val, BOOT_MAX_ALIGN);
|
||||
buf[0] = val;
|
||||
|
||||
rc = flash_area_write(fa, off, buf, align);
|
||||
if (rc != 0) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int boot_flag_write(int flag, uint8_t bank_id)
|
||||
{
|
||||
const struct flash_area *fa;
|
||||
uint32_t offs;
|
||||
int rc;
|
||||
|
||||
rc = flash_area_open(bank_id, &fa);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = boot_flag_offs(flag, fa, &offs);
|
||||
if (rc != 0) {
|
||||
flash_area_close(fa);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = boot_write_trailer_byte(fa, offs, BOOT_FLAG_SET);
|
||||
flash_area_close(fa);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int boot_flag_read(int flag, uint8_t bank_id)
|
||||
{
|
||||
const struct flash_area *fa;
|
||||
uint32_t offs;
|
||||
int rc;
|
||||
uint8_t flag_val;
|
||||
|
||||
rc = flash_area_open(bank_id, &fa);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = boot_flag_offs(flag, fa, &offs);
|
||||
if (rc != 0) {
|
||||
flash_area_close(fa);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = flash_area_read(fa, offs, &flag_val, sizeof(flag_val));
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
return flag_val;
|
||||
}
|
||||
|
||||
static int boot_image_ok_read(uint8_t bank_id)
|
||||
{
|
||||
return boot_flag_read(BOOT_FLAG_IMAGE_OK, bank_id);
|
||||
}
|
||||
|
||||
static int boot_image_ok_write(uint8_t bank_id)
|
||||
{
|
||||
return boot_flag_write(BOOT_FLAG_IMAGE_OK, bank_id);
|
||||
}
|
||||
|
||||
#ifdef FLASH_AREA_IMAGE_SECONDARY
|
||||
static int boot_magic_write(uint8_t bank_id)
|
||||
{
|
||||
const struct flash_area *fa;
|
||||
uint32_t offs;
|
||||
int rc;
|
||||
|
||||
rc = flash_area_open(bank_id, &fa);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
offs = MAGIC_OFFS(fa);
|
||||
|
||||
rc = flash_area_write(fa, offs, boot_img_magic, BOOT_MAGIC_SZ);
|
||||
flash_area_close(fa);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MCUBOOT_TRAILER_SWAP_TYPE
|
||||
static int boot_swap_type_write(uint8_t bank_id, uint8_t swap_type)
|
||||
{
|
||||
const struct flash_area *fa;
|
||||
uint32_t offs;
|
||||
int rc;
|
||||
|
||||
rc = flash_area_open(bank_id, &fa);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
offs = SWAP_TYPE_OFFS(fa);
|
||||
|
||||
rc = boot_write_trailer_byte(fa, offs, swap_type);
|
||||
flash_area_close(fa);
|
||||
|
||||
return rc;
|
||||
}
|
||||
#endif /* CONFIG_MCUBOOT_TRAILER_SWAP_TYPE */
|
||||
#endif /* FLASH_AREA_IMAGE_SECONDARY */
|
||||
|
||||
static int boot_read_v1_header(uint8_t area_id,
|
||||
struct mcuboot_v1_raw_header *v1_raw)
|
||||
{
|
||||
|
@ -469,221 +144,58 @@ int boot_read_bank_header(uint8_t area_id,
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BOOTLOADER_MCUBOOT) || defined(CONFIG_ZTEST)
|
||||
static int boot_read_swap_state(const struct flash_area *fa,
|
||||
struct boot_swap_state *state)
|
||||
{
|
||||
uint32_t magic[BOOT_MAGIC_ARR_SZ];
|
||||
uint32_t off;
|
||||
int rc;
|
||||
|
||||
off = MAGIC_OFFS(fa);
|
||||
rc = flash_area_read_is_empty(fa, off, magic, BOOT_MAGIC_SZ);
|
||||
if (rc < 0) {
|
||||
return -EIO;
|
||||
}
|
||||
if (rc == 1) {
|
||||
state->magic = BOOT_MAGIC_UNSET;
|
||||
} else {
|
||||
state->magic = boot_magic_decode(magic);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MCUBOOT_TRAILER_SWAP_TYPE
|
||||
off = SWAP_TYPE_OFFS(fa);
|
||||
rc = flash_area_read_is_empty(fa, off, &state->swap_type,
|
||||
sizeof(state->swap_type));
|
||||
if (rc < 0) {
|
||||
return -EIO;
|
||||
}
|
||||
if (rc == 1 || state->swap_type > BOOT_SWAP_TYPE_REVERT) {
|
||||
state->swap_type = BOOT_SWAP_TYPE_NONE;
|
||||
}
|
||||
|
||||
off = COPY_DONE_OFFS(fa);
|
||||
rc = flash_area_read_is_empty(fa, off, &state->copy_done,
|
||||
sizeof(state->copy_done));
|
||||
if (rc < 0) {
|
||||
return -EIO;
|
||||
}
|
||||
if (rc == 1) {
|
||||
state->copy_done = BOOT_FLAG_UNSET;
|
||||
} else {
|
||||
state->copy_done = boot_flag_decode(state->copy_done);
|
||||
}
|
||||
#else
|
||||
#ifdef FLASH_AREA_IMAGE_SCRATCH
|
||||
if (fa->fa_id != FLASH_AREA_IMAGE_SCRATCH) {
|
||||
#endif
|
||||
off = COPY_DONE_OFFS(fa);
|
||||
rc = flash_area_read_is_empty(fa, off, &state->copy_done,
|
||||
sizeof(state->copy_done));
|
||||
if (rc < 0) {
|
||||
return -EIO;
|
||||
}
|
||||
if (rc == 1) {
|
||||
state->copy_done = BOOT_FLAG_UNSET;
|
||||
} else {
|
||||
state->copy_done = boot_flag_decode(state->copy_done);
|
||||
}
|
||||
#ifdef FLASH_AREA_IMAGE_SCRATCH
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
off = IMAGE_OK_OFFS(fa);
|
||||
rc = flash_area_read_is_empty(fa, off, &state->image_ok,
|
||||
sizeof(state->image_ok));
|
||||
if (rc < 0) {
|
||||
return -EIO;
|
||||
}
|
||||
if (rc == 1) {
|
||||
state->image_ok = BOOT_FLAG_UNSET;
|
||||
} else {
|
||||
state->image_ok = boot_flag_decode(state->image_ok);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BOOTLOADER_MCUBOOT) || defined(CONFIG_ZTEST)
|
||||
/**
|
||||
* Reads the image trailer from the scratch area.
|
||||
*/
|
||||
int
|
||||
boot_read_swap_state_by_id(int flash_area_id, struct boot_swap_state *state)
|
||||
{
|
||||
const struct flash_area *fap;
|
||||
int rc;
|
||||
|
||||
switch (flash_area_id) {
|
||||
#ifdef FLASH_AREA_IMAGE_SCRATCH
|
||||
case FLASH_AREA_IMAGE_SCRATCH:
|
||||
#endif
|
||||
case FLASH_AREA_IMAGE_PRIMARY:
|
||||
#ifdef FLASH_AREA_IMAGE_SECONDARY
|
||||
case FLASH_AREA_IMAGE_SECONDARY:
|
||||
#endif
|
||||
rc = flash_area_open(flash_area_id, &fap);
|
||||
if (rc != 0) {
|
||||
return -EIO;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = boot_read_swap_state(fap, state);
|
||||
flash_area_close(fap);
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
/* equivalent of boot_swap_type() in mcuboot bootutil_misc.c */
|
||||
int mcuboot_swap_type(void)
|
||||
{
|
||||
#ifdef FLASH_AREA_IMAGE_SECONDARY
|
||||
const struct boot_swap_table *table;
|
||||
struct boot_swap_state primary_slot;
|
||||
struct boot_swap_state secondary_slot;
|
||||
int rc;
|
||||
size_t i;
|
||||
|
||||
rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_PRIMARY,
|
||||
&primary_slot);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_SECONDARY,
|
||||
&secondary_slot);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
for (i = 0; i < BOOT_SWAP_TABLES_COUNT; i++) {
|
||||
table = boot_swap_tables + i;
|
||||
|
||||
if (boot_magic_compatible_check(table->magic_primary_slot,
|
||||
primary_slot.magic)
|
||||
&&
|
||||
boot_magic_compatible_check(table->magic_secondary_slot,
|
||||
secondary_slot.magic)
|
||||
&&
|
||||
(table->image_ok_primary_slot == BOOT_FLAG_ANY ||
|
||||
table->image_ok_primary_slot == primary_slot.image_ok)
|
||||
&&
|
||||
(table->image_ok_secondary_slot == BOOT_FLAG_ANY ||
|
||||
table->image_ok_secondary_slot == secondary_slot.image_ok)
|
||||
&&
|
||||
(table->copy_done_primary_slot == BOOT_FLAG_ANY ||
|
||||
table->copy_done_primary_slot == primary_slot.copy_done)) {
|
||||
|
||||
__ASSERT_NO_MSG(table->swap_type == BOOT_SWAP_TYPE_TEST ||
|
||||
table->swap_type == BOOT_SWAP_TYPE_PERM ||
|
||||
table->swap_type == BOOT_SWAP_TYPE_REVERT);
|
||||
return table->swap_type;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return boot_swap_type();
|
||||
#else
|
||||
return BOOT_SWAP_TYPE_NONE;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
int boot_request_upgrade(int permanent)
|
||||
{
|
||||
#ifdef FLASH_AREA_IMAGE_SECONDARY
|
||||
#ifdef CONFIG_MCUBOOT_TRAILER_SWAP_TYPE
|
||||
uint8_t swap_type;
|
||||
#endif
|
||||
int rc;
|
||||
|
||||
rc = boot_magic_write(FLASH_AREA_IMAGE_SECONDARY);
|
||||
rc = boot_set_pending(permanent);
|
||||
if (rc) {
|
||||
goto op_end;
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (permanent) {
|
||||
rc = boot_image_ok_write(FLASH_AREA_IMAGE_SECONDARY);
|
||||
|
||||
#ifdef CONFIG_MCUBOOT_TRAILER_SWAP_TYPE
|
||||
if (rc) {
|
||||
goto op_end;
|
||||
}
|
||||
|
||||
swap_type = BOOT_SWAP_TYPE_PERM;
|
||||
} else {
|
||||
swap_type = BOOT_SWAP_TYPE_TEST;
|
||||
}
|
||||
|
||||
rc = boot_swap_type_write(FLASH_AREA_IMAGE_SECONDARY, swap_type);
|
||||
#else
|
||||
}
|
||||
#endif
|
||||
op_end:
|
||||
return rc;
|
||||
#else
|
||||
return 0;
|
||||
#endif /* FLASH_AREA_IMAGE_SECONDARY */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool boot_is_img_confirmed(void)
|
||||
{
|
||||
return boot_image_ok_read(FLASH_AREA_IMAGE_PRIMARY) == BOOT_FLAG_SET;
|
||||
const struct flash_area *fa;
|
||||
int rc;
|
||||
uint8_t flag_val;
|
||||
|
||||
rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY, &fa);
|
||||
if (rc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
rc = boot_read_image_ok(fa, &flag_val);
|
||||
if (rc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return flag_val == BOOT_FLAG_SET;
|
||||
}
|
||||
|
||||
int boot_write_img_confirmed(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (boot_image_ok_read(FLASH_AREA_IMAGE_PRIMARY) !=
|
||||
erased_flag_val(FLASH_AREA_IMAGE_PRIMARY)) {
|
||||
/* Already confirmed. */
|
||||
return 0;
|
||||
rc = boot_set_confirmed();
|
||||
if (rc) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
rc = boot_image_ok_write(FLASH_AREA_IMAGE_PRIMARY);
|
||||
|
||||
return rc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int boot_erase_img_bank(uint8_t area_id)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue