mirror of https://github.com/wolfSSL/wolfBoot.git
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_HOMEpull/470/head
parent
2ec2bcdf79
commit
04111a67b4
|
|
@ -116,9 +116,11 @@ int hal_flash_write(uintptr_t address, const uint8_t *data, int len)
|
|||
else {
|
||||
for (i = 0; i < len; i++) {
|
||||
#ifdef NVM_FLASH_WRITEONCE
|
||||
if (((uint8_t*)address)[i] != FLASH_BYTE_ERASED) {
|
||||
uint8_t *addr = (uint8_t *)address;
|
||||
if (addr[i] != FLASH_BYTE_ERASED) {
|
||||
/* no writing to non-erased page in NVM_FLASH_WRITEONCE */
|
||||
printf("NVM_FLASH_WRITEONCE non-erased write detected!\n");
|
||||
printf("NVM_FLASH_WRITEONCE non-erased write detected at address %p!\n", addr);
|
||||
printf("Address[%d] = %02x\n", i, addr[i]);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -192,17 +192,12 @@ static int RAMFUNCTION nvm_select_fresh_sector(int part)
|
|||
uintptr_t off;
|
||||
uint8_t *base;
|
||||
uint8_t* addrErase;
|
||||
uint32_t magic_off = 0;
|
||||
uint32_t word_0;
|
||||
uint32_t word_1;
|
||||
|
||||
hal_cache_invalidate();
|
||||
|
||||
/* if FLAGS_HOME check both boot and update for changes */
|
||||
#ifdef FLAGS_HOME
|
||||
base = (uint8_t *)PART_BOOT_ENDFLAGS;
|
||||
addrErase = (uint8_t *)WOLFBOOT_PARTITION_BOOT_ADDRESS +
|
||||
WOLFBOOT_PARTITION_SIZE - WOLFBOOT_SECTOR_SIZE;
|
||||
#else
|
||||
if (part == PART_BOOT) {
|
||||
base = (uint8_t *)PART_BOOT_ENDFLAGS;
|
||||
addrErase = (uint8_t *)WOLFBOOT_PARTITION_BOOT_ADDRESS +
|
||||
|
|
@ -213,7 +208,6 @@ static int RAMFUNCTION nvm_select_fresh_sector(int part)
|
|||
addrErase = (uint8_t *)WOLFBOOT_PARTITION_UPDATE_ADDRESS +
|
||||
WOLFBOOT_PARTITION_SIZE - WOLFBOOT_SECTOR_SIZE;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef EXT_ENCRYPTED
|
||||
#ifndef FLAGS_HOME
|
||||
|
|
@ -239,8 +233,9 @@ static int RAMFUNCTION nvm_select_fresh_sector(int part)
|
|||
#endif
|
||||
|
||||
/* check magic in case the sector is corrupt */
|
||||
word_0 = *((uint32_t*)((uintptr_t)base - sizeof(uint32_t)));
|
||||
word_1 = *((uint32_t*)((uintptr_t)base - WOLFBOOT_SECTOR_SIZE - sizeof(uint32_t)));
|
||||
word_0 = *((uint32_t*)((uintptr_t)base - (magic_off + sizeof(uint32_t))));
|
||||
word_1 = *((uint32_t*)((uintptr_t)base - (WOLFBOOT_SECTOR_SIZE + magic_off +
|
||||
sizeof(uint32_t))));
|
||||
|
||||
if (word_0 == WOLFBOOT_MAGIC_TRAIL && word_1 != WOLFBOOT_MAGIC_TRAIL) {
|
||||
sel = 0;
|
||||
|
|
@ -255,30 +250,13 @@ static int RAMFUNCTION nvm_select_fresh_sector(int part)
|
|||
goto finish;
|
||||
}
|
||||
|
||||
/* try the update magic as well */
|
||||
#ifdef FLAGS_HOME
|
||||
/* check magic in case the sector is corrupt */
|
||||
word_0 = *((uint32_t*)(PART_UPDATE_ENDFLAGS - sizeof(uint32_t)));
|
||||
word_1 = *((uint32_t*)(PART_UPDATE_ENDFLAGS - WOLFBOOT_SECTOR_SIZE -
|
||||
sizeof(uint32_t)));
|
||||
|
||||
if (word_0 == WOLFBOOT_MAGIC_TRAIL && word_1 != WOLFBOOT_MAGIC_TRAIL) {
|
||||
sel = 0;
|
||||
goto finish;
|
||||
}
|
||||
else if (word_0 != WOLFBOOT_MAGIC_TRAIL && word_1 == WOLFBOOT_MAGIC_TRAIL) {
|
||||
sel = 1;
|
||||
goto finish;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Default to last sector if no match is found */
|
||||
sel = 0;
|
||||
|
||||
/* Select the sector with more flags set. Partition flag is at offset '4'.
|
||||
* Sector flags begin from offset '5'.
|
||||
*/
|
||||
for (off = 4; off < WOLFBOOT_SECTOR_SIZE; off++) {
|
||||
for (off = 4 + magic_off; off < WOLFBOOT_SECTOR_SIZE; off++) {
|
||||
volatile uint8_t byte_0 = get_base_offset(base, off);
|
||||
volatile uint8_t byte_1 = get_base_offset(base, (WOLFBOOT_SECTOR_SIZE + off));
|
||||
|
||||
|
|
@ -292,14 +270,6 @@ static int RAMFUNCTION nvm_select_fresh_sector(int part)
|
|||
}
|
||||
else if ((byte_0 == FLASH_BYTE_ERASED) &&
|
||||
(byte_1 == FLASH_BYTE_ERASED)) {
|
||||
#ifdef FLAGS_HOME
|
||||
/* if we're still checking boot flags, check update flags */
|
||||
if (base - off > (uint8_t*)PART_UPDATE_ENDFLAGS) {
|
||||
base = (uint8_t *)PART_UPDATE_ENDFLAGS;
|
||||
off = 0;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
/* Examine previous position one byte ahead */
|
||||
byte_0 = get_base_offset(base, (off - 1));
|
||||
byte_1 = get_base_offset(base, ((WOLFBOOT_SECTOR_SIZE + off) - 1));
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ WOLFCRYPT=../../lib/wolfssl/
|
|||
|
||||
|
||||
TESTS:=unit-parser unit-extflash unit-aes128 unit-aes256 unit-chacha20 unit-pci \
|
||||
unit-mock-state unit-sectorflags unit-image unit-nvm
|
||||
unit-mock-state unit-sectorflags unit-image unit-nvm unit-nvm-flagshome
|
||||
|
||||
all: $(TESTS)
|
||||
|
||||
|
|
@ -40,6 +40,7 @@ unit-aes256:CFLAGS+=-DEXT_ENCRYPTED -DENCRYPT_WITH_AES256
|
|||
unit-chacha20:CFLAGS+=-DEXT_ENCRYPTED -DENCRYPT_WITH_CHACHA
|
||||
unit-parser:CFLAGS+=-DNVM_FLASH_WRITEONCE
|
||||
unit-nvm:CFLAGS+=-DNVM_FLASH_WRITEONCE -DMOCK_PARTITIONS
|
||||
unit-nvm-flagshome:CFLAGS+=-DNVM_FLASH_WRITEONCE -DMOCK_PARTITIONS -DFLAGS_HOME
|
||||
|
||||
|
||||
WOLFCRYPT_SRC:=$(WOLFCRYPT)/wolfcrypt/src/sha.c \
|
||||
|
|
@ -90,6 +91,9 @@ unit-image: unit-image.c unit-common.c $(WOLFCRYPT_SRC)
|
|||
unit-nvm: ../../include/target.h unit-nvm.c
|
||||
gcc -o $@ unit-nvm.c $(CFLAGS) $(LDFLAGS)
|
||||
|
||||
unit-nvm-flagshome: ../../include/target.h unit-nvm.c
|
||||
gcc -o $@ unit-nvm.c $(CFLAGS) $(LDFLAGS)
|
||||
|
||||
%.o:%.c
|
||||
gcc -c -o $@ $^ $(CFLAGS)
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
#define UNIT_TEST
|
||||
#define WC_NO_HARDEN
|
||||
#define MOCK_ADDRESS 0xCC000000
|
||||
#define MOCK_ADDRESS_BOOT 0xCD000000
|
||||
#define MOCK_ADDRESS_SWAP 0xCE000000
|
||||
#include <stdio.h>
|
||||
#include "libwolfboot.c"
|
||||
#include <fcntl.h>
|
||||
|
|
@ -13,8 +15,10 @@
|
|||
static int locked = 1;
|
||||
static int erased_boot = 0;
|
||||
static int erased_update = 0;
|
||||
static int erased_swap = 0;
|
||||
static int erased_nvm_bank0 = 0;
|
||||
static int erased_nvm_bank1 = 0;
|
||||
const char *argv0;
|
||||
|
||||
|
||||
/* Mocks */
|
||||
|
|
@ -32,6 +36,14 @@ int hal_flash_write(haladdr_t address, const uint8_t *data, int len)
|
|||
a[i] = data[i];
|
||||
}
|
||||
}
|
||||
#ifdef FLAGS_HOME
|
||||
if ((address >= WOLFBOOT_PARTITION_BOOT_ADDRESS) &&
|
||||
(address < WOLFBOOT_PARTITION_BOOT_ADDRESS + WOLFBOOT_PARTITION_SIZE)) {
|
||||
for (i = 0; i < len; i++) {
|
||||
a[i] = data[i];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
int hal_flash_erase(haladdr_t address, int len)
|
||||
|
|
@ -40,6 +52,14 @@ int hal_flash_erase(haladdr_t address, int len)
|
|||
if ((address >= WOLFBOOT_PARTITION_BOOT_ADDRESS) &&
|
||||
(address < WOLFBOOT_PARTITION_BOOT_ADDRESS + WOLFBOOT_PARTITION_SIZE)) {
|
||||
erased_boot++;
|
||||
#ifdef FLAGS_HOME
|
||||
memset(address, 0xFF, len);
|
||||
if (address >= WOLFBOOT_PARTITION_BOOT_ADDRESS + WOLFBOOT_PARTITION_SIZE - WOLFBOOT_SECTOR_SIZE) {
|
||||
erased_nvm_bank0++;
|
||||
} else if (address >= WOLFBOOT_PARTITION_BOOT_ADDRESS + WOLFBOOT_PARTITION_SIZE - 2 * WOLFBOOT_SECTOR_SIZE) {
|
||||
erased_nvm_bank1++;
|
||||
}
|
||||
#endif
|
||||
} else if ((address >= WOLFBOOT_PARTITION_UPDATE_ADDRESS) &&
|
||||
(address < WOLFBOOT_PARTITION_UPDATE_ADDRESS + WOLFBOOT_PARTITION_SIZE)) {
|
||||
erased_update++;
|
||||
|
|
@ -49,6 +69,10 @@ int hal_flash_erase(haladdr_t address, int len)
|
|||
} else if (address >= WOLFBOOT_PARTITION_UPDATE_ADDRESS + WOLFBOOT_PARTITION_SIZE - 2 * WOLFBOOT_SECTOR_SIZE) {
|
||||
erased_nvm_bank1++;
|
||||
}
|
||||
} else if ((address >= WOLFBOOT_PARTITION_SWAP_ADDRESS) &&
|
||||
(address < WOLFBOOT_PARTITION_SWAP_ADDRESS + WOLFBOOT_SECTOR_SIZE)) {
|
||||
erased_swap++;
|
||||
memset(address, 0xFF, len);
|
||||
} else {
|
||||
fail("Invalid address\n");
|
||||
return -1;
|
||||
|
|
@ -71,7 +95,8 @@ void hal_prepare_boot(void)
|
|||
}
|
||||
|
||||
/* A simple mock memory */
|
||||
static int mmap_file(const char *path, uint8_t *address, uint8_t** ret_address)
|
||||
static int mmap_file(const char *path, uint8_t *address, uint32_t len,
|
||||
uint8_t** ret_address)
|
||||
{
|
||||
struct stat st = { 0 };
|
||||
uint8_t *mmaped_addr;
|
||||
|
|
@ -88,13 +113,13 @@ static int mmap_file(const char *path, uint8_t *address, uint8_t** ret_address)
|
|||
return -1;
|
||||
}
|
||||
fprintf(stderr, "Open file: %s success.\n", path);
|
||||
for (i = 0; i < WOLFBOOT_PARTITION_SIZE; i+=4) {
|
||||
for (i = 0; i < len; i+=4) {
|
||||
const uint32_t erased_word = 0xBADBADBA;
|
||||
write(fd, &erased_word, 4);
|
||||
}
|
||||
lseek(fd, SEEK_SET, 0);
|
||||
|
||||
mmaped_addr = mmap(address, WOLFBOOT_PARTITION_SIZE, PROT_READ | PROT_WRITE,
|
||||
mmaped_addr = mmap(address, len, PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED, fd, 0);
|
||||
if (mmaped_addr == MAP_FAILED) {
|
||||
fprintf(stderr, "MMAP failed.\n");
|
||||
|
|
@ -124,15 +149,46 @@ START_TEST (test_nvm_select_fresh_sector)
|
|||
uint8_t st;
|
||||
uint32_t *magic;
|
||||
uint8_t *dst, *src;
|
||||
uint8_t part = PART_UPDATE;
|
||||
uint32_t base_addr = WOLFBOOT_PARTITION_UPDATE_ADDRESS;
|
||||
uint32_t home_off = 0;
|
||||
|
||||
ret = mmap_file("/tmp/wolfboot-unit-file.bin", MOCK_ADDRESS, NULL);
|
||||
ret = mmap_file("/tmp/wolfboot-unit-file.bin", MOCK_ADDRESS,
|
||||
WOLFBOOT_PARTITION_SIZE, NULL);
|
||||
fail_if(ret < 0);
|
||||
#ifdef FLAGS_HOME
|
||||
ret = mmap_file("/tmp/wolfboot-unit-int-file.bin", MOCK_ADDRESS_BOOT,
|
||||
WOLFBOOT_PARTITION_SIZE, NULL);
|
||||
fail_if(ret < 0);
|
||||
part = PART_BOOT;
|
||||
base_addr = WOLFBOOT_PARTITION_BOOT_ADDRESS;
|
||||
home_off = PART_BOOT_ENDFLAGS - PART_UPDATE_ENDFLAGS;
|
||||
#endif
|
||||
ret = mmap_file("/tmp/wolfboot-unit-swap.bin", MOCK_ADDRESS_SWAP,
|
||||
WOLFBOOT_SECTOR_SIZE, NULL);
|
||||
fail_if(ret < 0);
|
||||
|
||||
/* Sanity */
|
||||
fail_if(home_off > WOLFBOOT_SECTOR_SIZE);
|
||||
|
||||
/* unlock the flash to allow operations */
|
||||
hal_flash_unlock();
|
||||
|
||||
/* Check swap erase */
|
||||
wolfBoot_erase_partition(PART_SWAP);
|
||||
fail_if(erased_swap != 1);
|
||||
for (i = 0; i < WOLFBOOT_SECTOR_SIZE; i+=4) {
|
||||
uint32_t *word = ((uint32_t *)(WOLFBOOT_PARTITION_SWAP_ADDRESS + i));
|
||||
fail_if(*word != 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
erased_update = 0;
|
||||
wolfBoot_erase_partition(PART_UPDATE);
|
||||
wolfBoot_erase_partition(part);
|
||||
#ifndef FLAGS_HOME
|
||||
fail_if(erased_update != 1);
|
||||
#else
|
||||
fail_if(erased_boot != 1);
|
||||
#endif
|
||||
/* Erased flag sectors: select '0' by default */
|
||||
ret = nvm_select_fresh_sector(PART_UPDATE);
|
||||
fail_if(ret != 0, "Failed to select default fresh sector\n");
|
||||
|
|
@ -231,13 +287,13 @@ START_TEST (test_nvm_select_fresh_sector)
|
|||
wolfBoot_set_update_sector_flag(1, SECT_FLAG_UPDATED);
|
||||
|
||||
/* Copy flags from 0 to 1 */
|
||||
src = (uint8_t *)(WOLFBOOT_PARTITION_UPDATE_ADDRESS + WOLFBOOT_PARTITION_SIZE - 8);
|
||||
dst = (uint8_t *)(WOLFBOOT_PARTITION_UPDATE_ADDRESS + WOLFBOOT_PARTITION_SIZE - (8 + WOLFBOOT_SECTOR_SIZE));
|
||||
src = (uint8_t *)(base_addr + WOLFBOOT_PARTITION_SIZE - (8 + home_off));
|
||||
dst = (uint8_t *)(base_addr + WOLFBOOT_PARTITION_SIZE - (8 + home_off + WOLFBOOT_SECTOR_SIZE));
|
||||
for (i = 0; i < 8; i++)
|
||||
dst[i] = src[i];
|
||||
|
||||
/* Force-erase 4B of sector flags in 0 */
|
||||
dst = (uint8_t *)(WOLFBOOT_PARTITION_UPDATE_ADDRESS + WOLFBOOT_PARTITION_SIZE - 8);
|
||||
dst = (uint8_t *)(base_addr + WOLFBOOT_PARTITION_SIZE - (8 + home_off));
|
||||
for (i = 0; i < 4; i++)
|
||||
dst[i] = 0xFF;
|
||||
|
||||
|
|
@ -276,13 +332,13 @@ START_TEST (test_nvm_select_fresh_sector)
|
|||
fail_if(ret != 1, "Failed to select right sector after reading sector state\n");
|
||||
|
||||
/* Copy flags from 1 to 0 */
|
||||
src = (uint8_t *)(WOLFBOOT_PARTITION_UPDATE_ADDRESS + WOLFBOOT_PARTITION_SIZE - (8 + WOLFBOOT_SECTOR_SIZE));
|
||||
dst = (uint8_t *)(WOLFBOOT_PARTITION_UPDATE_ADDRESS + WOLFBOOT_PARTITION_SIZE - 8);
|
||||
src = (uint8_t *)(base_addr + WOLFBOOT_PARTITION_SIZE - (8 + home_off + WOLFBOOT_SECTOR_SIZE));
|
||||
dst = (uint8_t *)(base_addr + WOLFBOOT_PARTITION_SIZE - (8 + home_off));
|
||||
for (i = 0; i < 8; i++)
|
||||
dst[i] = src[i];
|
||||
|
||||
/* Force to F0 last sector flag in 0, so that the sector '4' is 'updated' */
|
||||
dst = (uint8_t *)(WOLFBOOT_PARTITION_UPDATE_ADDRESS + WOLFBOOT_PARTITION_SIZE - 8);
|
||||
dst = (uint8_t *)(base_addr + WOLFBOOT_PARTITION_SIZE - (8 + home_off));
|
||||
dst[0] = 0xF0;
|
||||
|
||||
/* Check if still there */
|
||||
|
|
@ -297,8 +353,13 @@ START_TEST (test_nvm_select_fresh_sector)
|
|||
|
||||
/* Erase partition and start over */
|
||||
erased_update = 0;
|
||||
wolfBoot_erase_partition(PART_UPDATE);
|
||||
erased_boot = 0;
|
||||
wolfBoot_erase_partition(part);
|
||||
#ifndef FLAGS_HOME
|
||||
fail_if(erased_update != 1);
|
||||
#else
|
||||
fail_if(erased_boot != 1);
|
||||
#endif
|
||||
|
||||
ret = nvm_select_fresh_sector(PART_UPDATE);
|
||||
fail_if(ret != 0, "Failed to select right sector after reading sector state\n");
|
||||
|
|
@ -328,9 +389,8 @@ END_TEST
|
|||
|
||||
Suite *wolfboot_suite(void)
|
||||
{
|
||||
|
||||
/* Suite initialization */
|
||||
Suite *s = suite_create("wolfBoot-NVM-workarounds");
|
||||
Suite *s = suite_create("wolfboot");
|
||||
|
||||
/* Test cases */
|
||||
TCase *nvm_select_fresh_sector = tcase_create("NVM select fresh sector");
|
||||
|
|
@ -341,9 +401,10 @@ Suite *wolfboot_suite(void)
|
|||
}
|
||||
|
||||
|
||||
int main(void)
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int fails;
|
||||
argv0 = strdup(argv[0]);
|
||||
Suite *s = wolfboot_suite();
|
||||
SRunner *sr = srunner_create(s);
|
||||
srunner_run_all(sr, CK_NORMAL);
|
||||
|
|
|
|||
Loading…
Reference in New Issue