Skip to content

Commit 04111a6

Browse files
committed
Added unit tests for FLAGS_HOME + fix NVM election
Taking into account the additional offset for PART_UPDATE_FLAGS at the end of each flags sector when comparing two redundant flag sectors in NVM_FLASH_WRITEONCE + FLAGS_HOME
1 parent 2ec2bcd commit 04111a6

File tree

4 files changed

+92
-55
lines changed

4 files changed

+92
-55
lines changed

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: 5 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -192,17 +192,12 @@ static int RAMFUNCTION nvm_select_fresh_sector(int part)
192192
uintptr_t off;
193193
uint8_t *base;
194194
uint8_t* addrErase;
195+
uint32_t magic_off = 0;
195196
uint32_t word_0;
196197
uint32_t word_1;
197198

198199
hal_cache_invalidate();
199200

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
206201
if (part == PART_BOOT) {
207202
base = (uint8_t *)PART_BOOT_ENDFLAGS;
208203
addrErase = (uint8_t *)WOLFBOOT_PARTITION_BOOT_ADDRESS +
@@ -213,7 +208,6 @@ static int RAMFUNCTION nvm_select_fresh_sector(int part)
213208
addrErase = (uint8_t *)WOLFBOOT_PARTITION_UPDATE_ADDRESS +
214209
WOLFBOOT_PARTITION_SIZE - WOLFBOOT_SECTOR_SIZE;
215210
}
216-
#endif
217211

218212
#ifdef EXT_ENCRYPTED
219213
#ifndef FLAGS_HOME
@@ -239,8 +233,9 @@ static int RAMFUNCTION nvm_select_fresh_sector(int part)
239233
#endif
240234

241235
/* 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)));
236+
word_0 = *((uint32_t*)((uintptr_t)base - (magic_off + sizeof(uint32_t))));
237+
word_1 = *((uint32_t*)((uintptr_t)base - (WOLFBOOT_SECTOR_SIZE + magic_off +
238+
sizeof(uint32_t))));
244239

245240
if (word_0 == WOLFBOOT_MAGIC_TRAIL && word_1 != WOLFBOOT_MAGIC_TRAIL) {
246241
sel = 0;
@@ -255,30 +250,13 @@ static int RAMFUNCTION nvm_select_fresh_sector(int part)
255250
goto finish;
256251
}
257252

258-
/* try the update magic as well */
259-
#ifdef FLAGS_HOME
260-
/* check magic in case the sector is corrupt */
261-
word_0 = *((uint32_t*)(PART_UPDATE_ENDFLAGS - sizeof(uint32_t)));
262-
word_1 = *((uint32_t*)(PART_UPDATE_ENDFLAGS - WOLFBOOT_SECTOR_SIZE -
263-
sizeof(uint32_t)));
264-
265-
if (word_0 == WOLFBOOT_MAGIC_TRAIL && word_1 != WOLFBOOT_MAGIC_TRAIL) {
266-
sel = 0;
267-
goto finish;
268-
}
269-
else if (word_0 != WOLFBOOT_MAGIC_TRAIL && word_1 == WOLFBOOT_MAGIC_TRAIL) {
270-
sel = 1;
271-
goto finish;
272-
}
273-
#endif
274-
275253
/* Default to last sector if no match is found */
276254
sel = 0;
277255

278256
/* Select the sector with more flags set. Partition flag is at offset '4'.
279257
* Sector flags begin from offset '5'.
280258
*/
281-
for (off = 4; off < WOLFBOOT_SECTOR_SIZE; off++) {
259+
for (off = 4 + magic_off; off < WOLFBOOT_SECTOR_SIZE; off++) {
282260
volatile uint8_t byte_0 = get_base_offset(base, off);
283261
volatile uint8_t byte_1 = get_base_offset(base, (WOLFBOOT_SECTOR_SIZE + off));
284262

@@ -292,14 +270,6 @@ static int RAMFUNCTION nvm_select_fresh_sector(int part)
292270
}
293271
else if ((byte_0 == FLASH_BYTE_ERASED) &&
294272
(byte_1 == FLASH_BYTE_ERASED)) {
295-
#ifdef FLAGS_HOME
296-
/* if we're still checking boot flags, check update flags */
297-
if (base - off > (uint8_t*)PART_UPDATE_ENDFLAGS) {
298-
base = (uint8_t *)PART_UPDATE_ENDFLAGS;
299-
off = 0;
300-
continue;
301-
}
302-
#endif
303273
/* Examine previous position one byte ahead */
304274
byte_0 = get_base_offset(base, (off - 1));
305275
byte_1 = get_base_offset(base, ((WOLFBOOT_SECTOR_SIZE + off) - 1));

tools/unit-tests/Makefile

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ WOLFCRYPT=../../lib/wolfssl/
1717

1818

1919
TESTS:=unit-parser unit-extflash unit-aes128 unit-aes256 unit-chacha20 unit-pci \
20-
unit-mock-state unit-sectorflags unit-image unit-nvm
20+
unit-mock-state unit-sectorflags unit-image unit-nvm unit-nvm-flagshome
2121

2222
all: $(TESTS)
2323

@@ -40,6 +40,7 @@ unit-aes256:CFLAGS+=-DEXT_ENCRYPTED -DENCRYPT_WITH_AES256
4040
unit-chacha20:CFLAGS+=-DEXT_ENCRYPTED -DENCRYPT_WITH_CHACHA
4141
unit-parser:CFLAGS+=-DNVM_FLASH_WRITEONCE
4242
unit-nvm:CFLAGS+=-DNVM_FLASH_WRITEONCE -DMOCK_PARTITIONS
43+
unit-nvm-flagshome:CFLAGS+=-DNVM_FLASH_WRITEONCE -DMOCK_PARTITIONS -DFLAGS_HOME
4344

4445

4546
WOLFCRYPT_SRC:=$(WOLFCRYPT)/wolfcrypt/src/sha.c \
@@ -90,6 +91,9 @@ unit-image: unit-image.c unit-common.c $(WOLFCRYPT_SRC)
9091
unit-nvm: ../../include/target.h unit-nvm.c
9192
gcc -o $@ unit-nvm.c $(CFLAGS) $(LDFLAGS)
9293

94+
unit-nvm-flagshome: ../../include/target.h unit-nvm.c
95+
gcc -o $@ unit-nvm.c $(CFLAGS) $(LDFLAGS)
96+
9397
%.o:%.c
9498
gcc -c -o $@ $^ $(CFLAGS)
9599

tools/unit-tests/unit-nvm.c

Lines changed: 78 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
#define UNIT_TEST
44
#define WC_NO_HARDEN
55
#define MOCK_ADDRESS 0xCC000000
6+
#define MOCK_ADDRESS_BOOT 0xCD000000
7+
#define MOCK_ADDRESS_SWAP 0xCE000000
68
#include <stdio.h>
79
#include "libwolfboot.c"
810
#include <fcntl.h>
@@ -13,8 +15,10 @@
1315
static int locked = 1;
1416
static int erased_boot = 0;
1517
static int erased_update = 0;
18+
static int erased_swap = 0;
1619
static int erased_nvm_bank0 = 0;
1720
static int erased_nvm_bank1 = 0;
21+
const char *argv0;
1822

1923

2024
/* Mocks */
@@ -32,6 +36,14 @@ int hal_flash_write(haladdr_t address, const uint8_t *data, int len)
3236
a[i] = data[i];
3337
}
3438
}
39+
#ifdef FLAGS_HOME
40+
if ((address >= WOLFBOOT_PARTITION_BOOT_ADDRESS) &&
41+
(address < WOLFBOOT_PARTITION_BOOT_ADDRESS + WOLFBOOT_PARTITION_SIZE)) {
42+
for (i = 0; i < len; i++) {
43+
a[i] = data[i];
44+
}
45+
}
46+
#endif
3547
return 0;
3648
}
3749
int hal_flash_erase(haladdr_t address, int len)
@@ -40,6 +52,14 @@ int hal_flash_erase(haladdr_t address, int len)
4052
if ((address >= WOLFBOOT_PARTITION_BOOT_ADDRESS) &&
4153
(address < WOLFBOOT_PARTITION_BOOT_ADDRESS + WOLFBOOT_PARTITION_SIZE)) {
4254
erased_boot++;
55+
#ifdef FLAGS_HOME
56+
memset(address, 0xFF, len);
57+
if (address >= WOLFBOOT_PARTITION_BOOT_ADDRESS + WOLFBOOT_PARTITION_SIZE - WOLFBOOT_SECTOR_SIZE) {
58+
erased_nvm_bank0++;
59+
} else if (address >= WOLFBOOT_PARTITION_BOOT_ADDRESS + WOLFBOOT_PARTITION_SIZE - 2 * WOLFBOOT_SECTOR_SIZE) {
60+
erased_nvm_bank1++;
61+
}
62+
#endif
4363
} else if ((address >= WOLFBOOT_PARTITION_UPDATE_ADDRESS) &&
4464
(address < WOLFBOOT_PARTITION_UPDATE_ADDRESS + WOLFBOOT_PARTITION_SIZE)) {
4565
erased_update++;
@@ -49,6 +69,10 @@ int hal_flash_erase(haladdr_t address, int len)
4969
} else if (address >= WOLFBOOT_PARTITION_UPDATE_ADDRESS + WOLFBOOT_PARTITION_SIZE - 2 * WOLFBOOT_SECTOR_SIZE) {
5070
erased_nvm_bank1++;
5171
}
72+
} else if ((address >= WOLFBOOT_PARTITION_SWAP_ADDRESS) &&
73+
(address < WOLFBOOT_PARTITION_SWAP_ADDRESS + WOLFBOOT_SECTOR_SIZE)) {
74+
erased_swap++;
75+
memset(address, 0xFF, len);
5276
} else {
5377
fail("Invalid address\n");
5478
return -1;
@@ -71,7 +95,8 @@ void hal_prepare_boot(void)
7195
}
7296

7397
/* A simple mock memory */
74-
static int mmap_file(const char *path, uint8_t *address, uint8_t** ret_address)
98+
static int mmap_file(const char *path, uint8_t *address, uint32_t len,
99+
uint8_t** ret_address)
75100
{
76101
struct stat st = { 0 };
77102
uint8_t *mmaped_addr;
@@ -88,13 +113,13 @@ static int mmap_file(const char *path, uint8_t *address, uint8_t** ret_address)
88113
return -1;
89114
}
90115
fprintf(stderr, "Open file: %s success.\n", path);
91-
for (i = 0; i < WOLFBOOT_PARTITION_SIZE; i+=4) {
116+
for (i = 0; i < len; i+=4) {
92117
const uint32_t erased_word = 0xBADBADBA;
93118
write(fd, &erased_word, 4);
94119
}
95120
lseek(fd, SEEK_SET, 0);
96121

97-
mmaped_addr = mmap(address, WOLFBOOT_PARTITION_SIZE, PROT_READ | PROT_WRITE,
122+
mmaped_addr = mmap(address, len, PROT_READ | PROT_WRITE,
98123
MAP_SHARED, fd, 0);
99124
if (mmaped_addr == MAP_FAILED) {
100125
fprintf(stderr, "MMAP failed.\n");
@@ -124,15 +149,46 @@ START_TEST (test_nvm_select_fresh_sector)
124149
uint8_t st;
125150
uint32_t *magic;
126151
uint8_t *dst, *src;
127-
128-
ret = mmap_file("/tmp/wolfboot-unit-file.bin", MOCK_ADDRESS, NULL);
129-
152+
uint8_t part = PART_UPDATE;
153+
uint32_t base_addr = WOLFBOOT_PARTITION_UPDATE_ADDRESS;
154+
uint32_t home_off = 0;
155+
156+
ret = mmap_file("/tmp/wolfboot-unit-file.bin", MOCK_ADDRESS,
157+
WOLFBOOT_PARTITION_SIZE, NULL);
158+
fail_if(ret < 0);
159+
#ifdef FLAGS_HOME
160+
ret = mmap_file("/tmp/wolfboot-unit-int-file.bin", MOCK_ADDRESS_BOOT,
161+
WOLFBOOT_PARTITION_SIZE, NULL);
162+
fail_if(ret < 0);
163+
part = PART_BOOT;
164+
base_addr = WOLFBOOT_PARTITION_BOOT_ADDRESS;
165+
home_off = PART_BOOT_ENDFLAGS - PART_UPDATE_ENDFLAGS;
166+
#endif
167+
ret = mmap_file("/tmp/wolfboot-unit-swap.bin", MOCK_ADDRESS_SWAP,
168+
WOLFBOOT_SECTOR_SIZE, NULL);
169+
fail_if(ret < 0);
170+
171+
/* Sanity */
172+
fail_if(home_off > WOLFBOOT_SECTOR_SIZE);
130173

131174
/* unlock the flash to allow operations */
132175
hal_flash_unlock();
176+
177+
/* Check swap erase */
178+
wolfBoot_erase_partition(PART_SWAP);
179+
fail_if(erased_swap != 1);
180+
for (i = 0; i < WOLFBOOT_SECTOR_SIZE; i+=4) {
181+
uint32_t *word = ((uint32_t *)(WOLFBOOT_PARTITION_SWAP_ADDRESS + i));
182+
fail_if(*word != 0xFFFFFFFF);
183+
}
184+
133185
erased_update = 0;
134-
wolfBoot_erase_partition(PART_UPDATE);
186+
wolfBoot_erase_partition(part);
187+
#ifndef FLAGS_HOME
135188
fail_if(erased_update != 1);
189+
#else
190+
fail_if(erased_boot != 1);
191+
#endif
136192
/* Erased flag sectors: select '0' by default */
137193
ret = nvm_select_fresh_sector(PART_UPDATE);
138194
fail_if(ret != 0, "Failed to select default fresh sector\n");
@@ -231,13 +287,13 @@ START_TEST (test_nvm_select_fresh_sector)
231287
wolfBoot_set_update_sector_flag(1, SECT_FLAG_UPDATED);
232288

233289
/* Copy flags from 0 to 1 */
234-
src = (uint8_t *)(WOLFBOOT_PARTITION_UPDATE_ADDRESS + WOLFBOOT_PARTITION_SIZE - 8);
235-
dst = (uint8_t *)(WOLFBOOT_PARTITION_UPDATE_ADDRESS + WOLFBOOT_PARTITION_SIZE - (8 + WOLFBOOT_SECTOR_SIZE));
290+
src = (uint8_t *)(base_addr + WOLFBOOT_PARTITION_SIZE - (8 + home_off));
291+
dst = (uint8_t *)(base_addr + WOLFBOOT_PARTITION_SIZE - (8 + home_off + WOLFBOOT_SECTOR_SIZE));
236292
for (i = 0; i < 8; i++)
237293
dst[i] = src[i];
238294

239295
/* Force-erase 4B of sector flags in 0 */
240-
dst = (uint8_t *)(WOLFBOOT_PARTITION_UPDATE_ADDRESS + WOLFBOOT_PARTITION_SIZE - 8);
296+
dst = (uint8_t *)(base_addr + WOLFBOOT_PARTITION_SIZE - (8 + home_off));
241297
for (i = 0; i < 4; i++)
242298
dst[i] = 0xFF;
243299

@@ -276,13 +332,13 @@ START_TEST (test_nvm_select_fresh_sector)
276332
fail_if(ret != 1, "Failed to select right sector after reading sector state\n");
277333

278334
/* Copy flags from 1 to 0 */
279-
src = (uint8_t *)(WOLFBOOT_PARTITION_UPDATE_ADDRESS + WOLFBOOT_PARTITION_SIZE - (8 + WOLFBOOT_SECTOR_SIZE));
280-
dst = (uint8_t *)(WOLFBOOT_PARTITION_UPDATE_ADDRESS + WOLFBOOT_PARTITION_SIZE - 8);
335+
src = (uint8_t *)(base_addr + WOLFBOOT_PARTITION_SIZE - (8 + home_off + WOLFBOOT_SECTOR_SIZE));
336+
dst = (uint8_t *)(base_addr + WOLFBOOT_PARTITION_SIZE - (8 + home_off));
281337
for (i = 0; i < 8; i++)
282338
dst[i] = src[i];
283339

284340
/* Force to F0 last sector flag in 0, so that the sector '4' is 'updated' */
285-
dst = (uint8_t *)(WOLFBOOT_PARTITION_UPDATE_ADDRESS + WOLFBOOT_PARTITION_SIZE - 8);
341+
dst = (uint8_t *)(base_addr + WOLFBOOT_PARTITION_SIZE - (8 + home_off));
286342
dst[0] = 0xF0;
287343

288344
/* Check if still there */
@@ -297,8 +353,13 @@ START_TEST (test_nvm_select_fresh_sector)
297353

298354
/* Erase partition and start over */
299355
erased_update = 0;
300-
wolfBoot_erase_partition(PART_UPDATE);
356+
erased_boot = 0;
357+
wolfBoot_erase_partition(part);
358+
#ifndef FLAGS_HOME
301359
fail_if(erased_update != 1);
360+
#else
361+
fail_if(erased_boot != 1);
362+
#endif
302363

303364
ret = nvm_select_fresh_sector(PART_UPDATE);
304365
fail_if(ret != 0, "Failed to select right sector after reading sector state\n");
@@ -328,9 +389,8 @@ END_TEST
328389

329390
Suite *wolfboot_suite(void)
330391
{
331-
332392
/* Suite initialization */
333-
Suite *s = suite_create("wolfBoot-NVM-workarounds");
393+
Suite *s = suite_create("wolfboot");
334394

335395
/* Test cases */
336396
TCase *nvm_select_fresh_sector = tcase_create("NVM select fresh sector");
@@ -341,9 +401,10 @@ Suite *wolfboot_suite(void)
341401
}
342402

343403

344-
int main(void)
404+
int main(int argc, char *argv[])
345405
{
346406
int fails;
407+
argv0 = strdup(argv[0]);
347408
Suite *s = wolfboot_suite();
348409
SRunner *sr = srunner_create(s);
349410
srunner_run_all(sr, CK_NORMAL);

0 commit comments

Comments
 (0)