Skip to content

Commit ab35c7f

Browse files
committed
Fixed image swap, tested fail-recovery from interrupted update
1 parent 45056aa commit ab35c7f

3 files changed

Lines changed: 55 additions & 46 deletions

File tree

hal/nrf52.c

Lines changed: 19 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -53,46 +53,30 @@ static void flash_wait_complete(void)
5353

5454
int hal_flash_write(uint32_t address, const uint8_t *data, int len)
5555
{
56-
int i;
57-
uint8_t off = address & 0x03;
58-
int words, align;
59-
60-
if (off != 0) {
61-
uint32_t first = *((uint32_t *)(address - off));
62-
uint8_t *firstbytes = (uint8_t *)(&first);
63-
for (i = 0; i < 4 - off; i++) {
64-
firstbytes[i + off] = data[i];
65-
}
66-
NVMC_CONFIG = NVMC_CONFIG_WEN;
67-
flash_wait_complete();
68-
*((uint32_t *)(address - off)) = first;
69-
flash_wait_complete();
70-
address += 4 - off;
71-
data += 4 - off;
72-
len -= 4 - off;
73-
}
74-
if (len > 3) {
75-
uint32_t *src = (uint32_t *)data;
76-
uint32_t *dst = (uint32_t *)address;
77-
words = len / 4;
78-
align = words * 4;
79-
for (i = 0; i < words; i ++) {
56+
int i = 0;
57+
uint32_t *src, *dst;
58+
59+
while (i < len) {
60+
if ((len - i > 3) && ((((address + i) & 0x03) == 0) && ((((uint32_t)data) + i) & 0x03) == 0)) {
61+
src = (uint32_t *)data;
62+
dst = (uint32_t *)address;
8063
NVMC_CONFIG = NVMC_CONFIG_WEN;
8164
flash_wait_complete();
82-
dst[i] = src[i];
65+
dst[i >> 2] = src[i >> 2];
8366
flash_wait_complete();
84-
}
85-
if (len > align) {
86-
uint32_t last = dst[words];
87-
uint8_t *lastbytes = (uint8_t *)(&last);
88-
for (i = off; i < 4; i++) {
89-
if (i < len - align)
90-
lastbytes[3 - i] = data[align + i];
91-
}
67+
i+=4;
68+
} else {
69+
uint32_t val;
70+
uint8_t *vbytes = (uint8_t *)(&val);
71+
int off = (address + i) - (((address + i) >> 2) << 2);
72+
dst = (uint32_t *)(address - off);
73+
val = dst[i >> 2];
74+
vbytes[off] = data[i];
9275
NVMC_CONFIG = NVMC_CONFIG_WEN;
9376
flash_wait_complete();
94-
dst[words] = last;
77+
dst[i >> 2] = val;
9578
flash_wait_complete();
79+
i++;
9680
}
9781
}
9882
return 0;
@@ -109,7 +93,7 @@ void hal_flash_lock(void)
10993

11094
int hal_flash_erase(uint32_t address, int len)
11195
{
112-
uint32_t end = address + len;
96+
uint32_t end = address + len - 1;
11397
uint32_t p;
11498
for (p = address; p <= end; p += FLASH_PAGE_SIZE) {
11599
NVMC_CONFIG = NVMC_CONFIG_EEN;

src/image.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -195,15 +195,17 @@ int wolfBoot_verify_authenticity(struct wolfBoot_image *img)
195195

196196
int wolfBoot_copy(uint32_t src, uint32_t dst, uint32_t size)
197197
{
198-
uint32_t *content;
198+
uint32_t *orig, *copy;
199199
uint32_t pos = 0;
200200
if (src == dst)
201201
return 0;
202202
if ((src & 0x03) || (dst & 0x03))
203203
return -1;
204204
while (pos < size) {
205-
content = (uint32_t *)(src + pos);
206-
hal_flash_write(dst + pos, (void *)content, sizeof(uint32_t));
205+
orig = (uint32_t *)(src + pos);
206+
copy = (uint32_t *)(dst + pos);
207+
while (*orig != *copy)
208+
hal_flash_write(dst + pos, (void *)orig, sizeof(uint32_t));
207209
pos += sizeof(uint32_t);
208210
}
209211
return pos;

src/loader.c

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,21 +27,40 @@ extern void do_boot(const uint32_t *app_offset);
2727

2828
static int wolfBoot_update(void)
2929
{
30-
uint32_t total_size;
30+
uint32_t total_size = 0;
3131
uint32_t sector_size = WOLFBOOT_SECTOR_SIZE;
3232
uint32_t sector = 0;
3333
uint8_t flag, st;
34-
struct wolfBoot_image update;
34+
struct wolfBoot_image boot, update;
3535

36-
if ((wolfBoot_open_image(&update, PART_UPDATE) < 0) ||
37-
(wolfBoot_verify_integrity(&update) < 0) ||
38-
(wolfBoot_verify_authenticity(&update) < 0)) {
36+
/* Use biggest size for the swap */
37+
if ((wolfBoot_open_image(&update, PART_UPDATE) == 0) && (update.fw_size + IMAGE_HEADER_SIZE) > total_size)
38+
total_size = update.fw_size + IMAGE_HEADER_SIZE;
39+
if ((wolfBoot_open_image(&boot, PART_BOOT) == 0) && (boot.fw_size + IMAGE_HEADER_SIZE) > total_size)
40+
total_size = boot.fw_size + IMAGE_HEADER_SIZE;
41+
42+
if (total_size < IMAGE_HEADER_SIZE)
3943
return -1;
44+
45+
/* Check the first sector to detect interrupted update */
46+
if ((wolfBoot_get_sector_flag(PART_UPDATE, 0, &flag) < 0) || (flag == SECT_FLAG_NEW))
47+
{
48+
/* In case this is a new update, check
49+
* integrity/authenticity of the firmware update
50+
* before starting the swap
51+
*/
52+
if (!update.hdr_ok || (wolfBoot_verify_integrity(&update) < 0)
53+
|| (wolfBoot_verify_authenticity(&update) < 0)) {
54+
return -1;
55+
}
4056
}
4157

42-
total_size = update.fw_size + IMAGE_HEADER_SIZE;
4358
hal_flash_unlock();
4459

60+
/* Interruptible swap
61+
* The status is saved in the sector flags of the update partition.
62+
* If something goes wrong, the operation will be resumed upon reboot.
63+
*/
4564
while ((sector * sector_size) < total_size) {
4665
if ((wolfBoot_get_sector_flag(PART_UPDATE, sector, &flag) != 0) || (flag == SECT_FLAG_NEW)) {
4766
flag = SECT_FLAG_SWAPPING;
@@ -94,12 +113,16 @@ static int wolfBoot_update(void)
94113
static void wolfBoot_start(void)
95114
{
96115
uint8_t st;
97-
struct wolfBoot_image boot;
116+
struct wolfBoot_image boot, update;
98117
if ((wolfBoot_get_partition_state(PART_UPDATE, &st) == 0) && (st == IMG_STATE_UPDATING)) {
99118
wolfBoot_update();
100119
} else if ((wolfBoot_get_partition_state(PART_BOOT, &st) == 0) && (st == IMG_STATE_TESTING)) {
101120
wolfBoot_update_trigger();
102-
wolfBoot_update();
121+
if ((wolfBoot_open_image(&update, PART_UPDATE) < 0) ||
122+
(wolfBoot_verify_integrity(&update) < 0) ||
123+
(wolfBoot_verify_authenticity(&update) < 0)) {
124+
wolfBoot_update();
125+
}
103126
}
104127
if ((wolfBoot_open_image(&boot, PART_BOOT) < 0) ||
105128
(wolfBoot_verify_integrity(&boot) < 0) ||

0 commit comments

Comments
 (0)