Skip to content

Commit 2ec2bcd

Browse files
committed
Fixed flag comparison selecting most recent flags
1 parent 3444c47 commit 2ec2bcd

File tree

2 files changed

+135
-14
lines changed

2 files changed

+135
-14
lines changed

src/libwolfboot.c

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,10 @@ static int RAMFUNCTION nvm_select_fresh_sector(int part)
249249
else if (word_0 != WOLFBOOT_MAGIC_TRAIL && word_1 == WOLFBOOT_MAGIC_TRAIL) {
250250
sel = 1;
251251
goto finish;
252+
} else if (word_0 != WOLFBOOT_MAGIC_TRAIL && word_1 != WOLFBOOT_MAGIC_TRAIL) {
253+
/* none of the partition has a valid trailer, default to '0' */
254+
sel = 0;
255+
goto finish;
252256
}
253257

254258
/* try the update magic as well */
@@ -271,10 +275,12 @@ static int RAMFUNCTION nvm_select_fresh_sector(int part)
271275
/* Default to last sector if no match is found */
272276
sel = 0;
273277

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));
278+
/* Select the sector with more flags set. Partition flag is at offset '4'.
279+
* Sector flags begin from offset '5'.
280+
*/
281+
for (off = 4; off < WOLFBOOT_SECTOR_SIZE; off++) {
282+
volatile uint8_t byte_0 = get_base_offset(base, off);
283+
volatile uint8_t byte_1 = get_base_offset(base, (WOLFBOOT_SECTOR_SIZE + off));
278284

279285
if (byte_0 == FLASH_BYTE_ERASED && byte_1 != FLASH_BYTE_ERASED) {
280286
sel = 1;
@@ -294,11 +300,6 @@ static int RAMFUNCTION nvm_select_fresh_sector(int part)
294300
continue;
295301
}
296302
#endif
297-
/* First time boot? Assume no pending update */
298-
if (off == 1) {
299-
sel=0;
300-
break;
301-
}
302303
/* Examine previous position one byte ahead */
303304
byte_0 = get_base_offset(base, (off - 1));
304305
byte_1 = get_base_offset(base, ((WOLFBOOT_SECTOR_SIZE + off) - 1));

tools/unit-tests/unit-nvm.c

Lines changed: 125 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,13 @@
1010
#include <sys/mman.h>
1111
#include <check.h>
1212

13-
static int locked = 0;
13+
static int locked = 1;
1414
static int erased_boot = 0;
1515
static int erased_update = 0;
1616
static int erased_nvm_bank0 = 0;
1717
static int erased_nvm_bank1 = 0;
1818

1919

20-
21-
22-
2320
/* Mocks */
2421
void hal_init(void)
2522
{
@@ -28,6 +25,7 @@ int hal_flash_write(haladdr_t address, const uint8_t *data, int len)
2825
{
2926
int i;
3027
uint8_t *a = (uint8_t *)address;
28+
fail_if(locked, "Attempting to write to a locked FLASH");
3129
if ((address >= WOLFBOOT_PARTITION_UPDATE_ADDRESS) &&
3230
(address < WOLFBOOT_PARTITION_UPDATE_ADDRESS + WOLFBOOT_PARTITION_SIZE)) {
3331
for (i = 0; i < len; i++) {
@@ -38,6 +36,7 @@ int hal_flash_write(haladdr_t address, const uint8_t *data, int len)
3836
}
3937
int hal_flash_erase(haladdr_t address, int len)
4038
{
39+
fail_if(locked, "Attempting to erase a locked FLASH");
4140
if ((address >= WOLFBOOT_PARTITION_BOOT_ADDRESS) &&
4241
(address < WOLFBOOT_PARTITION_BOOT_ADDRESS + WOLFBOOT_PARTITION_SIZE)) {
4342
erased_boot++;
@@ -119,13 +118,18 @@ Suite *wolfboot_suite(void);
119118

120119
START_TEST (test_nvm_select_fresh_sector)
121120
{
122-
int ret;
121+
int ret, i;
123122
const char BOOT[] = "BOOT";
124123
const uint32_t *boot_word = (const uint32_t *)BOOT;
125124
uint8_t st;
126125
uint32_t *magic;
126+
uint8_t *dst, *src;
127+
127128
ret = mmap_file("/tmp/wolfboot-unit-file.bin", MOCK_ADDRESS, NULL);
128129

130+
131+
/* unlock the flash to allow operations */
132+
hal_flash_unlock();
129133
erased_update = 0;
130134
wolfBoot_erase_partition(PART_UPDATE);
131135
fail_if(erased_update != 1);
@@ -202,6 +206,122 @@ START_TEST (test_nvm_select_fresh_sector)
202206
ret = nvm_select_fresh_sector(PART_UPDATE);
203207
fail_if(ret != 0, "Failed to select right sector after reading sector state\n");
204208

209+
/* Update sector flag, again. it should change nvm sector */
210+
erased_nvm_bank1 = 0;
211+
erased_nvm_bank0 = 0;
212+
wolfBoot_set_update_sector_flag(1, SECT_FLAG_SWAPPING);
213+
214+
/* Current selected should now be 1 */
215+
ret = nvm_select_fresh_sector(PART_UPDATE);
216+
fail_if(ret != 1, "Failed to select updating fresh sector\n");
217+
fail_if(erased_nvm_bank0 == 0, "Did not erase the non-selected bank");
218+
219+
/* Check sector state is read back correctly */
220+
ret = wolfBoot_get_update_sector_flag(1, &st);
221+
fail_if (ret != 0, "Failed to read sector flag state\n");
222+
fail_if (st != SECT_FLAG_SWAPPING, "Wrong sector flag state\n");
223+
224+
/* Check that reading did not change the current sector (1) */
225+
ret = nvm_select_fresh_sector(PART_UPDATE);
226+
fail_if(ret != 1, "Failed to select right sector after reading sector state\n");
227+
228+
/* Update sector flag, again. it should change nvm sector */
229+
erased_nvm_bank1 = 0;
230+
erased_nvm_bank0 = 0;
231+
wolfBoot_set_update_sector_flag(1, SECT_FLAG_UPDATED);
232+
233+
/* 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));
236+
for (i = 0; i < 8; i++)
237+
dst[i] = src[i];
238+
239+
/* Force-erase 4B of sector flags in 0 */
240+
dst = (uint8_t *)(WOLFBOOT_PARTITION_UPDATE_ADDRESS + WOLFBOOT_PARTITION_SIZE - 8);
241+
for (i = 0; i < 4; i++)
242+
dst[i] = 0xFF;
243+
244+
/* This should fall back to 1 */
245+
ret = nvm_select_fresh_sector(PART_UPDATE);
246+
fail_if(ret != 1, "Failed to select most recent sector after deleting flags\n");
247+
248+
/* Start over, update some sector flags */
249+
wolfBoot_erase_partition(PART_UPDATE);
250+
wolfBoot_set_update_sector_flag(0, SECT_FLAG_UPDATED);
251+
wolfBoot_set_update_sector_flag(1, SECT_FLAG_UPDATED);
252+
wolfBoot_set_update_sector_flag(2, SECT_FLAG_UPDATED);
253+
wolfBoot_set_update_sector_flag(3, SECT_FLAG_UPDATED);
254+
wolfBoot_set_update_sector_flag(4, SECT_FLAG_SWAPPING);
255+
st = IMG_STATE_UPDATING;
256+
wolfBoot_set_partition_state(PART_UPDATE, &st);
257+
258+
/* Current selected should now be 1 */
259+
ret = nvm_select_fresh_sector(PART_UPDATE);
260+
fail_if(ret != 1, "Failed to select updating fresh sector\n");
261+
fail_if(erased_nvm_bank0 == 0, "Did not erase the non-selected bank");
262+
263+
/* Check sector state is read back correctly */
264+
for (i = 0; i < 4; i++) {
265+
ret = wolfBoot_get_update_sector_flag(i, &st);
266+
fail_if (ret != 0, "Failed to read sector flag state\n");
267+
fail_if (st != SECT_FLAG_UPDATED, "Wrong sector flag state\n");
268+
269+
}
270+
ret = wolfBoot_get_update_sector_flag(4, &st);
271+
fail_if (ret != 0, "Failed to read sector flag state\n");
272+
fail_if (st != SECT_FLAG_SWAPPING, "Wrong sector flag state\n");
273+
274+
/* Check that reading did not change the current sector (1) */
275+
ret = nvm_select_fresh_sector(PART_UPDATE);
276+
fail_if(ret != 1, "Failed to select right sector after reading sector state\n");
277+
278+
/* 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);
281+
for (i = 0; i < 8; i++)
282+
dst[i] = src[i];
283+
284+
/* 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);
286+
dst[0] = 0xF0;
287+
288+
/* Check if still there */
289+
ret = wolfBoot_get_update_sector_flag(4, &st);
290+
fail_if (ret != 0, "Failed to read sector flag state\n");
291+
fail_if (st != SECT_FLAG_UPDATED, "Wrong sector flag state\n");
292+
293+
/* This should fall back to 0 */
294+
ret = nvm_select_fresh_sector(PART_UPDATE);
295+
fail_if(ret != 0, "Failed to select most recent sector after deleting flags\n");
296+
297+
298+
/* Erase partition and start over */
299+
erased_update = 0;
300+
wolfBoot_erase_partition(PART_UPDATE);
301+
fail_if(erased_update != 1);
302+
303+
ret = nvm_select_fresh_sector(PART_UPDATE);
304+
fail_if(ret != 0, "Failed to select right sector after reading sector state\n");
305+
306+
/* re-lock the flash: update_trigger implies unlocking/locking */
307+
hal_flash_lock();
308+
309+
/* Triggering update to set flags */
310+
wolfBoot_update_trigger();
311+
312+
/* Current selected should now be 0 */
313+
ret = nvm_select_fresh_sector(PART_UPDATE);
314+
fail_if(ret != 0, "Failed to select updating fresh sector\n");
315+
fail_if(erased_nvm_bank1 == 0, "Did not erase the non-selected bank");
316+
317+
magic = get_partition_magic(PART_UPDATE);
318+
fail_if(*magic != *boot_word,
319+
"Failed to read back 'BOOT' trailer at the end of the partition");
320+
321+
/* Sanity check at the end of the operations. */
322+
fail_unless(locked, "The FLASH was left unlocked.\n");
323+
324+
205325
}
206326
END_TEST
207327

0 commit comments

Comments
 (0)