mirror of https://github.com/wolfSSL/wolfBoot.git
Fixed image swap, tested fail-recovery from interrupted update
parent
45056aa95e
commit
ab35c7f8fe
52
hal/nrf52.c
52
hal/nrf52.c
|
@ -53,46 +53,30 @@ static void flash_wait_complete(void)
|
|||
|
||||
int hal_flash_write(uint32_t address, const uint8_t *data, int len)
|
||||
{
|
||||
int i;
|
||||
uint8_t off = address & 0x03;
|
||||
int words, align;
|
||||
int i = 0;
|
||||
uint32_t *src, *dst;
|
||||
|
||||
if (off != 0) {
|
||||
uint32_t first = *((uint32_t *)(address - off));
|
||||
uint8_t *firstbytes = (uint8_t *)(&first);
|
||||
for (i = 0; i < 4 - off; i++) {
|
||||
firstbytes[i + off] = data[i];
|
||||
}
|
||||
NVMC_CONFIG = NVMC_CONFIG_WEN;
|
||||
flash_wait_complete();
|
||||
*((uint32_t *)(address - off)) = first;
|
||||
flash_wait_complete();
|
||||
address += 4 - off;
|
||||
data += 4 - off;
|
||||
len -= 4 - off;
|
||||
}
|
||||
if (len > 3) {
|
||||
uint32_t *src = (uint32_t *)data;
|
||||
uint32_t *dst = (uint32_t *)address;
|
||||
words = len / 4;
|
||||
align = words * 4;
|
||||
for (i = 0; i < words; i ++) {
|
||||
while (i < len) {
|
||||
if ((len - i > 3) && ((((address + i) & 0x03) == 0) && ((((uint32_t)data) + i) & 0x03) == 0)) {
|
||||
src = (uint32_t *)data;
|
||||
dst = (uint32_t *)address;
|
||||
NVMC_CONFIG = NVMC_CONFIG_WEN;
|
||||
flash_wait_complete();
|
||||
dst[i] = src[i];
|
||||
dst[i >> 2] = src[i >> 2];
|
||||
flash_wait_complete();
|
||||
}
|
||||
if (len > align) {
|
||||
uint32_t last = dst[words];
|
||||
uint8_t *lastbytes = (uint8_t *)(&last);
|
||||
for (i = off; i < 4; i++) {
|
||||
if (i < len - align)
|
||||
lastbytes[3 - i] = data[align + i];
|
||||
}
|
||||
i+=4;
|
||||
} else {
|
||||
uint32_t val;
|
||||
uint8_t *vbytes = (uint8_t *)(&val);
|
||||
int off = (address + i) - (((address + i) >> 2) << 2);
|
||||
dst = (uint32_t *)(address - off);
|
||||
val = dst[i >> 2];
|
||||
vbytes[off] = data[i];
|
||||
NVMC_CONFIG = NVMC_CONFIG_WEN;
|
||||
flash_wait_complete();
|
||||
dst[words] = last;
|
||||
dst[i >> 2] = val;
|
||||
flash_wait_complete();
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
@ -109,7 +93,7 @@ void hal_flash_lock(void)
|
|||
|
||||
int hal_flash_erase(uint32_t address, int len)
|
||||
{
|
||||
uint32_t end = address + len;
|
||||
uint32_t end = address + len - 1;
|
||||
uint32_t p;
|
||||
for (p = address; p <= end; p += FLASH_PAGE_SIZE) {
|
||||
NVMC_CONFIG = NVMC_CONFIG_EEN;
|
||||
|
|
|
@ -195,15 +195,17 @@ int wolfBoot_verify_authenticity(struct wolfBoot_image *img)
|
|||
|
||||
int wolfBoot_copy(uint32_t src, uint32_t dst, uint32_t size)
|
||||
{
|
||||
uint32_t *content;
|
||||
uint32_t *orig, *copy;
|
||||
uint32_t pos = 0;
|
||||
if (src == dst)
|
||||
return 0;
|
||||
if ((src & 0x03) || (dst & 0x03))
|
||||
return -1;
|
||||
while (pos < size) {
|
||||
content = (uint32_t *)(src + pos);
|
||||
hal_flash_write(dst + pos, (void *)content, sizeof(uint32_t));
|
||||
orig = (uint32_t *)(src + pos);
|
||||
copy = (uint32_t *)(dst + pos);
|
||||
while (*orig != *copy)
|
||||
hal_flash_write(dst + pos, (void *)orig, sizeof(uint32_t));
|
||||
pos += sizeof(uint32_t);
|
||||
}
|
||||
return pos;
|
||||
|
|
39
src/loader.c
39
src/loader.c
|
@ -27,21 +27,40 @@ extern void do_boot(const uint32_t *app_offset);
|
|||
|
||||
static int wolfBoot_update(void)
|
||||
{
|
||||
uint32_t total_size;
|
||||
uint32_t total_size = 0;
|
||||
uint32_t sector_size = WOLFBOOT_SECTOR_SIZE;
|
||||
uint32_t sector = 0;
|
||||
uint8_t flag, st;
|
||||
struct wolfBoot_image update;
|
||||
struct wolfBoot_image boot, update;
|
||||
|
||||
if ((wolfBoot_open_image(&update, PART_UPDATE) < 0) ||
|
||||
(wolfBoot_verify_integrity(&update) < 0) ||
|
||||
(wolfBoot_verify_authenticity(&update) < 0)) {
|
||||
/* Use biggest size for the swap */
|
||||
if ((wolfBoot_open_image(&update, PART_UPDATE) == 0) && (update.fw_size + IMAGE_HEADER_SIZE) > total_size)
|
||||
total_size = update.fw_size + IMAGE_HEADER_SIZE;
|
||||
if ((wolfBoot_open_image(&boot, PART_BOOT) == 0) && (boot.fw_size + IMAGE_HEADER_SIZE) > total_size)
|
||||
total_size = boot.fw_size + IMAGE_HEADER_SIZE;
|
||||
|
||||
if (total_size < IMAGE_HEADER_SIZE)
|
||||
return -1;
|
||||
|
||||
/* Check the first sector to detect interrupted update */
|
||||
if ((wolfBoot_get_sector_flag(PART_UPDATE, 0, &flag) < 0) || (flag == SECT_FLAG_NEW))
|
||||
{
|
||||
/* In case this is a new update, check
|
||||
* integrity/authenticity of the firmware update
|
||||
* before starting the swap
|
||||
*/
|
||||
if (!update.hdr_ok || (wolfBoot_verify_integrity(&update) < 0)
|
||||
|| (wolfBoot_verify_authenticity(&update) < 0)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
total_size = update.fw_size + IMAGE_HEADER_SIZE;
|
||||
hal_flash_unlock();
|
||||
|
||||
/* Interruptible swap
|
||||
* The status is saved in the sector flags of the update partition.
|
||||
* If something goes wrong, the operation will be resumed upon reboot.
|
||||
*/
|
||||
while ((sector * sector_size) < total_size) {
|
||||
if ((wolfBoot_get_sector_flag(PART_UPDATE, sector, &flag) != 0) || (flag == SECT_FLAG_NEW)) {
|
||||
flag = SECT_FLAG_SWAPPING;
|
||||
|
@ -94,12 +113,16 @@ static int wolfBoot_update(void)
|
|||
static void wolfBoot_start(void)
|
||||
{
|
||||
uint8_t st;
|
||||
struct wolfBoot_image boot;
|
||||
struct wolfBoot_image boot, update;
|
||||
if ((wolfBoot_get_partition_state(PART_UPDATE, &st) == 0) && (st == IMG_STATE_UPDATING)) {
|
||||
wolfBoot_update();
|
||||
} else if ((wolfBoot_get_partition_state(PART_BOOT, &st) == 0) && (st == IMG_STATE_TESTING)) {
|
||||
wolfBoot_update_trigger();
|
||||
wolfBoot_update();
|
||||
if ((wolfBoot_open_image(&update, PART_UPDATE) < 0) ||
|
||||
(wolfBoot_verify_integrity(&update) < 0) ||
|
||||
(wolfBoot_verify_authenticity(&update) < 0)) {
|
||||
wolfBoot_update();
|
||||
}
|
||||
}
|
||||
if ((wolfBoot_open_image(&boot, PART_BOOT) < 0) ||
|
||||
(wolfBoot_verify_integrity(&boot) < 0) ||
|
||||
|
|
Loading…
Reference in New Issue