Skip to content

Commit f0c4252

Browse files
authored
Merge pull request #470 from danielinux/nvm-writeonce-flags-compare
Fixed flag comparison selecting most recent flags
2 parents 3444c47 + aaf40aa commit f0c4252

File tree

12 files changed

+777
-123
lines changed

12 files changed

+777
-123
lines changed

.github/workflows/test-build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ on:
1717
jobs:
1818

1919
build:
20-
runs-on: ubuntu-latest
20+
runs-on: ubuntu-24.04
2121

2222
steps:
2323
- uses: actions/checkout@v3

hal/sim.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,11 @@ int hal_flash_write(uintptr_t address, const uint8_t *data, int len)
116116
else {
117117
for (i = 0; i < len; i++) {
118118
#ifdef NVM_FLASH_WRITEONCE
119-
if (((uint8_t*)address)[i] != FLASH_BYTE_ERASED) {
119+
uint8_t *addr = (uint8_t *)address;
120+
if (addr[i] != FLASH_BYTE_ERASED) {
120121
/* no writing to non-erased page in NVM_FLASH_WRITEONCE */
121-
printf("NVM_FLASH_WRITEONCE non-erased write detected!\n");
122+
printf("NVM_FLASH_WRITEONCE non-erased write detected at address %p!\n", addr);
123+
printf("Address[%d] = %02x\n", i, addr[i]);
122124
return -1;
123125
}
124126
#endif

src/libwolfboot.c

Lines changed: 57 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
*/
2828
#include <stdint.h>
2929

30-
3130
#include "hal.h"
3231
#include "wolfboot/wolfboot.h"
3332
#include "image.h"
@@ -191,56 +190,37 @@ static int RAMFUNCTION nvm_select_fresh_sector(int part)
191190
int sel;
192191
uintptr_t off;
193192
uint8_t *base;
194-
uint8_t* addrErase;
193+
uint8_t* addrErase = 0;
195194
uint32_t word_0;
196195
uint32_t word_1;
197196

197+
#if defined(EXT_FLASH) && !defined(FLAGS_HOME)
198+
if ((part == PART_UPDATE) && FLAGS_UPDATE_EXT()) {
199+
return 0;
200+
}
201+
#endif
202+
198203
hal_cache_invalidate();
199204

200-
/* if FLAGS_HOME check both boot and update for changes */
201-
#ifdef FLAGS_HOME
202-
base = (uint8_t *)PART_BOOT_ENDFLAGS;
203-
addrErase = (uint8_t *)WOLFBOOT_PARTITION_BOOT_ADDRESS +
204-
WOLFBOOT_PARTITION_SIZE - WOLFBOOT_SECTOR_SIZE;
205-
#else
206205
if (part == PART_BOOT) {
207206
base = (uint8_t *)PART_BOOT_ENDFLAGS;
208207
addrErase = (uint8_t *)WOLFBOOT_PARTITION_BOOT_ADDRESS +
209208
WOLFBOOT_PARTITION_SIZE - WOLFBOOT_SECTOR_SIZE;
210209
}
211210
else {
212211
base = (uint8_t *)PART_UPDATE_ENDFLAGS;
212+
#ifdef FLAGS_HOME
213+
addrErase = (uint8_t *)WOLFBOOT_PARTITION_BOOT_ADDRESS +
214+
WOLFBOOT_PARTITION_SIZE - WOLFBOOT_SECTOR_SIZE;
215+
#else
213216
addrErase = (uint8_t *)WOLFBOOT_PARTITION_UPDATE_ADDRESS +
214217
WOLFBOOT_PARTITION_SIZE - WOLFBOOT_SECTOR_SIZE;
215-
}
216-
#endif
217-
218-
#ifdef EXT_ENCRYPTED
219-
#ifndef FLAGS_HOME
220-
if (part == PART_BOOT)
221218
#endif
222-
{
223-
word_0 = *((uint32_t *)(ENCRYPT_TMP_SECRET_OFFSET +
224-
WOLFBOOT_PARTITION_BOOT_ADDRESS));
225-
word_1 = *((uint32_t *)(ENCRYPT_TMP_SECRET_OFFSET +
226-
WOLFBOOT_PARTITION_BOOT_ADDRESS - WOLFBOOT_SECTOR_SIZE));
227-
228-
if (word_0 == FLASH_WORD_ERASED && word_1 !=
229-
FLASH_WORD_ERASED) {
230-
sel = 1;
231-
goto finish;
232-
}
233-
else if (word_0 != FLASH_WORD_ERASED && word_1 ==
234-
FLASH_WORD_ERASED) {
235-
sel = 0;
236-
goto finish;
237-
}
238219
}
239-
#endif
240220

241221
/* check magic in case the sector is corrupt */
242-
word_0 = *((uint32_t*)((uintptr_t)base - sizeof(uint32_t)));
243-
word_1 = *((uint32_t*)((uintptr_t)base - WOLFBOOT_SECTOR_SIZE - sizeof(uint32_t)));
222+
word_0 = *((uint32_t*)((uintptr_t)base - sizeof(uint32_t)));
223+
word_1 = *((uint32_t*)((uintptr_t)base - (WOLFBOOT_SECTOR_SIZE + sizeof(uint32_t))));
244224

245225
if (word_0 == WOLFBOOT_MAGIC_TRAIL && word_1 != WOLFBOOT_MAGIC_TRAIL) {
246226
sel = 0;
@@ -249,32 +229,21 @@ static int RAMFUNCTION nvm_select_fresh_sector(int part)
249229
else if (word_0 != WOLFBOOT_MAGIC_TRAIL && word_1 == WOLFBOOT_MAGIC_TRAIL) {
250230
sel = 1;
251231
goto finish;
252-
}
253-
254-
/* try the update magic as well */
255-
#ifdef FLAGS_HOME
256-
/* check magic in case the sector is corrupt */
257-
word_0 = *((uint32_t*)(PART_UPDATE_ENDFLAGS - sizeof(uint32_t)));
258-
word_1 = *((uint32_t*)(PART_UPDATE_ENDFLAGS - WOLFBOOT_SECTOR_SIZE -
259-
sizeof(uint32_t)));
260-
261-
if (word_0 == WOLFBOOT_MAGIC_TRAIL && word_1 != WOLFBOOT_MAGIC_TRAIL) {
232+
} else if (word_0 != WOLFBOOT_MAGIC_TRAIL && word_1 != WOLFBOOT_MAGIC_TRAIL) {
233+
/* none of the partition has a valid trailer, default to '0' */
262234
sel = 0;
263235
goto finish;
264236
}
265-
else if (word_0 != WOLFBOOT_MAGIC_TRAIL && word_1 == WOLFBOOT_MAGIC_TRAIL) {
266-
sel = 1;
267-
goto finish;
268-
}
269-
#endif
270237

271238
/* Default to last sector if no match is found */
272239
sel = 0;
273240

274-
/* Select the sector with more flags set */
275-
for (off = 1; off < WOLFBOOT_SECTOR_SIZE; off++) {
276-
uint8_t byte_0 = get_base_offset(base, off);
277-
uint8_t byte_1 = get_base_offset(base, (WOLFBOOT_SECTOR_SIZE + off));
241+
/* Select the sector with more flags set. Partition flag is at offset '4'.
242+
* Sector flags begin from offset '5'.
243+
*/
244+
for (off = 4; off < WOLFBOOT_SECTOR_SIZE; off++) {
245+
volatile uint8_t byte_0 = get_base_offset(base, off);
246+
volatile uint8_t byte_1 = get_base_offset(base, (WOLFBOOT_SECTOR_SIZE + off));
278247

279248
if (byte_0 == FLASH_BYTE_ERASED && byte_1 != FLASH_BYTE_ERASED) {
280249
sel = 1;
@@ -286,19 +255,6 @@ static int RAMFUNCTION nvm_select_fresh_sector(int part)
286255
}
287256
else if ((byte_0 == FLASH_BYTE_ERASED) &&
288257
(byte_1 == FLASH_BYTE_ERASED)) {
289-
#ifdef FLAGS_HOME
290-
/* if we're still checking boot flags, check update flags */
291-
if (base - off > (uint8_t*)PART_UPDATE_ENDFLAGS) {
292-
base = (uint8_t *)PART_UPDATE_ENDFLAGS;
293-
off = 0;
294-
continue;
295-
}
296-
#endif
297-
/* First time boot? Assume no pending update */
298-
if (off == 1) {
299-
sel=0;
300-
break;
301-
}
302258
/* Examine previous position one byte ahead */
303259
byte_0 = get_base_offset(base, (off - 1));
304260
byte_1 = get_base_offset(base, ((WOLFBOOT_SECTOR_SIZE + off) - 1));
@@ -376,6 +332,7 @@ static int RAMFUNCTION partition_magic_write(uint8_t part, uintptr_t addr)
376332
uintptr_t base = (uintptr_t)addr - off;
377333
uintptr_t addr_read, addr_write;
378334
int ret;
335+
379336
nvm_cached_sector = nvm_select_fresh_sector(part);
380337
addr_read = base - (nvm_cached_sector * NVM_CACHE_SIZE);
381338
addr_write = base - (!nvm_cached_sector * NVM_CACHE_SIZE);
@@ -766,8 +723,7 @@ void RAMFUNCTION wolfBoot_erase_partition(uint8_t part)
766723
void RAMFUNCTION wolfBoot_update_trigger(void)
767724
{
768725
uint8_t st = IMG_STATE_UPDATING;
769-
uintptr_t lastSector = PART_UPDATE_ENDFLAGS -
770-
(PART_UPDATE_ENDFLAGS % WOLFBOOT_SECTOR_SIZE);
726+
uintptr_t lastSector = ((PART_UPDATE_ENDFLAGS - 1) / WOLFBOOT_SECTOR_SIZE) * WOLFBOOT_SECTOR_SIZE;
771727
#ifdef NVM_FLASH_WRITEONCE
772728
uint8_t selSec = 0;
773729
#endif
@@ -795,11 +751,10 @@ void RAMFUNCTION wolfBoot_update_trigger(void)
795751
hal_flash_erase(lastSector, SECTOR_FLAGS_SIZE);
796752
#else
797753
selSec = nvm_select_fresh_sector(PART_UPDATE);
798-
XMEMCPY(NVM_CACHE,
799-
(uint8_t*)(lastSector - WOLFBOOT_SECTOR_SIZE * selSec),
800-
WOLFBOOT_SECTOR_SIZE);
801-
XMEMSET(NVM_CACHE, FLASH_BYTE_ERASED, SECTOR_FLAGS_SIZE);
754+
lastSector -= selSec * WOLFBOOT_SECTOR_SIZE;
755+
XMEMCPY(NVM_CACHE, (uint8_t*)lastSector, WOLFBOOT_SECTOR_SIZE);
802756
/* write to the non selected sector */
757+
hal_flash_erase(lastSector - WOLFBOOT_SECTOR_SIZE * !selSec, WOLFBOOT_SECTOR_SIZE);
803758
hal_flash_write(lastSector - WOLFBOOT_SECTOR_SIZE * !selSec, NVM_CACHE,
804759
WOLFBOOT_SECTOR_SIZE);
805760
/* erase the previously selected sector */
@@ -1391,6 +1346,7 @@ static int RAMFUNCTION hal_set_key(const uint8_t *k, const uint8_t *nonce)
13911346
uintptr_t addr, addr_align, addr_off;
13921347
int ret = 0;
13931348
int sel_sec = 0;
1349+
uint32_t trailer_relative_off = 4;
13941350
#ifdef MMU
13951351
XMEMCPY(ENCRYPT_KEY, k, ENCRYPT_KEY_SIZE);
13961352
XMEMCPY(ENCRYPT_KEY + ENCRYPT_KEY_SIZE, nonce, ENCRYPT_NONCE_SIZE);
@@ -1419,14 +1375,33 @@ static int RAMFUNCTION hal_set_key(const uint8_t *k, const uint8_t *nonce)
14191375
if (ret != 0)
14201376
return ret;
14211377
#endif
1378+
1379+
/* Populate key + nonce in the cache */
14221380
XMEMCPY(ENCRYPT_CACHE + addr_off, k, ENCRYPT_KEY_SIZE);
14231381
XMEMCPY(ENCRYPT_CACHE + addr_off + ENCRYPT_KEY_SIZE, nonce,
14241382
ENCRYPT_NONCE_SIZE);
1383+
1384+
/* Add a valid trailer */
1385+
XMEMCPY(ENCRYPT_CACHE + addr_off - trailer_relative_off,
1386+
&wolfboot_magic_trail, 4);
1387+
#ifdef FLAGS_HOME
1388+
/* If flags are stored in BOOT partition, take into account the offset
1389+
* of the flags used for the update partition too, to avoid erasing the
1390+
* sector.
1391+
*/
1392+
trailer_relative_off += (PART_BOOT_ENDFLAGS - PART_UPDATE_ENDFLAGS);
1393+
XMEMCPY(ENCRYPT_CACHE + addr_off - trailer_relative_off,
1394+
&wolfboot_magic_trail, 4);
1395+
#endif
1396+
1397+
/* Writing cache back to sector "!sel_sec" */
14251398
ret = hal_flash_write(addr_align, ENCRYPT_CACHE, WOLFBOOT_SECTOR_SIZE);
14261399
#ifdef NVM_FLASH_WRITEONCE
1427-
/* now erase the old populated sector */
14281400
if (ret != 0)
14291401
return ret;
1402+
/* Erasing original sector "sel_sec",
1403+
* same one returned from by nvm_select.
1404+
*/
14301405
addr_align = addr & (~(WOLFBOOT_SECTOR_SIZE - 1));
14311406
addr_align -= (sel_sec * WOLFBOOT_SECTOR_SIZE);
14321407
ret = hal_flash_erase(addr_align, WOLFBOOT_SECTOR_SIZE);
@@ -1508,7 +1483,7 @@ int RAMFUNCTION wolfBoot_erase_encrypt_key(void)
15081483
sel_sec = nvm_select_fresh_sector(PART_BOOT);
15091484
mem -= (sel_sec * WOLFBOOT_SECTOR_SIZE);
15101485
#endif
1511-
XMEMSET(ff, 0xFF, ENCRYPT_KEY_SIZE + ENCRYPT_NONCE_SIZE);
1486+
XMEMSET(ff, FLASH_BYTE_ERASED, ENCRYPT_KEY_SIZE + ENCRYPT_NONCE_SIZE);
15121487
if (XMEMCMP(mem, ff, ENCRYPT_KEY_SIZE + ENCRYPT_NONCE_SIZE) != 0)
15131488
hal_set_key(ff, ff + ENCRYPT_KEY_SIZE);
15141489
#endif
@@ -1717,10 +1692,6 @@ int RAMFUNCTION ext_flash_encrypt_write(uintptr_t address, const uint8_t *data,
17171692
if (sz < ENCRYPT_BLOCK_SIZE) {
17181693
sz = ENCRYPT_BLOCK_SIZE;
17191694
}
1720-
if (!encrypt_initialized) {
1721-
if (crypto_init() < 0)
1722-
return -1;
1723-
}
17241695
part = part_address(address);
17251696
switch (part) {
17261697
case PART_UPDATE:
@@ -1731,6 +1702,10 @@ int RAMFUNCTION ext_flash_encrypt_write(uintptr_t address, const uint8_t *data,
17311702
ENCRYPT_BLOCK_SIZE) {
17321703
return ext_flash_write(address, data, len);
17331704
}
1705+
if (!encrypt_initialized) {
1706+
if (crypto_init() < 0)
1707+
return -1;
1708+
}
17341709
crypto_set_iv(encrypt_iv_nonce, iv_counter);
17351710
break;
17361711
case PART_SWAP:
@@ -1799,10 +1774,6 @@ int RAMFUNCTION ext_flash_decrypt_read(uintptr_t address, uint8_t *data, int len
17991774
if (row_offset != 0) {
18001775
row_address = address & ~(ENCRYPT_BLOCK_SIZE - 1);
18011776
}
1802-
if (!encrypt_initialized) {
1803-
if (crypto_init() < 0)
1804-
return -1;
1805-
}
18061777
part = part_address(row_address);
18071778
switch (part) {
18081779
case PART_UPDATE:
@@ -1813,6 +1784,11 @@ int RAMFUNCTION ext_flash_decrypt_read(uintptr_t address, uint8_t *data, int len
18131784
ENCRYPT_BLOCK_SIZE) {
18141785
return ext_flash_read(address, data, len);
18151786
}
1787+
if (!encrypt_initialized) {
1788+
if (crypto_init() < 0) {
1789+
return -1;
1790+
}
1791+
}
18161792
crypto_set_iv(encrypt_iv_nonce, iv_counter);
18171793
break;
18181794
case PART_SWAP:
@@ -1894,18 +1870,15 @@ int wolfBoot_ram_decrypt(uint8_t *src, uint8_t *dst)
18941870
uint32_t dst_offset = 0, iv_counter = 0;
18951871
uint32_t magic, len;
18961872

1897-
wolfBoot_printf("Decrypting %p to %p\n", src, dst);
18981873

18991874
if (!encrypt_initialized) {
19001875
if (crypto_init() < 0) {
1901-
wolfBoot_printf("Error initializing crypto!\n");
19021876
return -1;
19031877
}
19041878
}
19051879

19061880
/* Attempt to decrypt firmware header */
19071881
if (decrypt_header(src) != 0) {
1908-
wolfBoot_printf("Error decrypting header at %p!\n", src);
19091882
return -1;
19101883
}
19111884
len = *((uint32_t*)(dec_hdr + sizeof(uint32_t)));

src/update_flash.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,7 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed)
501501
uint32_t up_v;
502502
#endif
503503

504+
504505
/* No Safety check on open: we might be in the middle of a broken update */
505506
wolfBoot_open_image(&update, PART_UPDATE);
506507
wolfBoot_open_image(&boot, PART_BOOT);
@@ -819,7 +820,8 @@ void RAMFUNCTION wolfBoot_start(void)
819820
bootRet = wolfBoot_get_partition_state(PART_BOOT, &bootState);
820821
updateRet = wolfBoot_get_partition_state(PART_UPDATE, &updateState);
821822

822-
#ifndef DISABLE_BACKUP
823+
824+
#if !defined(DISABLE_BACKUP)
823825
/* resume the final erase in case the power failed before it finished */
824826
resumedFinalErase = wolfBoot_swap_and_final_erase(1);
825827
if (resumedFinalErase != 0)

test-app/ARM-stm32f7.ld

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ SECTIONS
1717
. = ALIGN(4);
1818
_end_text = .;
1919
} > FLASH
20+
.edidx :
21+
{
22+
. = ALIGN(4);
23+
*(.ARM.exidx*)
24+
} > FLASH
2025

2126
_stored_data = .;
2227

test-app/app_sim.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,12 @@ int do_cmd(const char *cmd)
6161
printf("%d\n", wolfBoot_current_firmware_version());
6262
return 0;
6363
}
64+
if (strcmp(cmd, "get_state") == 0) {
65+
uint8_t st = 0;
66+
wolfBoot_get_partition_state(PART_UPDATE, &st);
67+
printf("%02x\n", st);
68+
return 0;
69+
}
6470
if (strcmp(cmd, "success") == 0) {
6571
wolfBoot_success();
6672
return 0;

tools/lms/lms_common.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,7 @@ static int lms_write_key(const byte * priv, word32 privSz, void * context)
4848
/* Create the file if it didn't exist. */
4949
file = fopen(filename, "w+");
5050
if (!file) {
51-
fprintf(stderr, "error: fopen(%s, \"w+\") failed: %d\n", filename,
52-
ferror(file));
51+
fprintf(stderr, "error: fopen(%s, \"w+\") failed.\n", filename);
5352
return WC_LMS_RC_WRITE_FAIL;
5453
}
5554
}
@@ -72,8 +71,7 @@ static int lms_write_key(const byte * priv, word32 privSz, void * context)
7271
* storage correctly. */
7372
file = fopen(filename, "r+");
7473
if (!file) {
75-
fprintf(stderr, "error: fopen(%s, \"r+\") failed: %d\n", filename,
76-
ferror(file));
74+
fprintf(stderr, "error: fopen(%s, \"r+\") failed.\n", filename);
7775
return WC_LMS_RC_WRITE_FAIL;
7876
}
7977

tools/scripts/sim-sunnyday-update.sh

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
#!/bin/bash
2-
32
V=`./wolfboot.elf update_trigger get_version 2>/dev/null`
43
if [ "x$V" != "x1" ]; then
54
echo "Failed first boot with update_trigger"

0 commit comments

Comments
 (0)