Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add powerfail during final sector erase #354

Merged
merged 9 commits into from
Oct 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test-powerfail-simulator.yml
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ jobs:

- name: Build wolfboot.elf
run: |
make && make test-sim-internal-flash-with-delta-update
make clean && make test-sim-internal-flash-with-delta-update

- name: Run sunny day update test (DELTA)
run: |
Expand Down
2 changes: 2 additions & 0 deletions include/wolfboot/wolfboot.h
Original file line number Diff line number Diff line change
Expand Up @@ -244,13 +244,15 @@ extern "C" {
#ifndef WOLFBOOT_FLAGS_INVERT
#define IMG_STATE_NEW 0xFF
#define IMG_STATE_UPDATING 0x70
#define IMG_STATE_FINAL_FLAGS 0x30
#define IMG_STATE_TESTING 0x10
#define IMG_STATE_SUCCESS 0x00
#define FLASH_BYTE_ERASED 0xFF
#define FLASH_WORD_ERASED 0xFFFFFFFFUL
#else
#define IMG_STATE_NEW 0x00
#define IMG_STATE_UPDATING 0x8F
#define IMG_STATE_FINAL_FLAGS 0xBF
#define IMG_STATE_TESTING 0xEF
#define IMG_STATE_SUCCESS 0xFF
#define FLASH_BYTE_ERASED 0x00
Expand Down
89 changes: 69 additions & 20 deletions src/libwolfboot.c
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,8 @@ static int RAMFUNCTION nvm_select_fresh_sector(int part)
uintptr_t off;
uint8_t *base;
uint8_t* addrErase;
uint32_t word_0;
uint32_t word_1;

/* if FLAGS_HOME check both boot and update for changes */
#ifdef FLAGS_HOME
Expand All @@ -215,8 +217,6 @@ static int RAMFUNCTION nvm_select_fresh_sector(int part)
#endif

#ifdef EXT_ENCRYPTED
uint32_t word_0;
uint32_t word_1;
#ifndef FLAGS_HOME
if (part == PART_BOOT)
#endif
Expand All @@ -239,6 +239,36 @@ static int RAMFUNCTION nvm_select_fresh_sector(int part)
}
#endif

/* check magic in case the sector is corrupt */
word_0 = *((uint32_t*)(base - sizeof(uint32_t)));
word_1 = *((uint32_t*)(base - 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;
}

/* 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;

Expand Down Expand Up @@ -711,20 +741,16 @@ void RAMFUNCTION wolfBoot_erase_partition(uint8_t part)
void RAMFUNCTION wolfBoot_update_trigger(void)
{
uint8_t st = IMG_STATE_UPDATING;
#if defined(NVM_FLASH_WRITEONCE) || defined(WOLFBOOT_FLAGS_INVERT)
uintptr_t lastSector = PART_UPDATE_ENDFLAGS -
(PART_UPDATE_ENDFLAGS % WOLFBOOT_SECTOR_SIZE);
#ifdef NVM_FLASH_WRITEONCE
uint8_t selSec = 0;
#endif

#ifndef FLAGS_HOME
/* if PART_UPDATE_ENDFLAGS stradles a sector, (all non FLAGS_HOME builds)
* align it to the correct sector */
if (PART_UPDATE_ENDFLAGS % WOLFBOOT_SECTOR_SIZE == 0)
lastSector -= WOLFBOOT_SECTOR_SIZE;
#endif
#endif
#ifdef NVM_FLASH_WRITEONCE
uint8_t selSec = 0;
#endif

/* erase the sector flags */
if (FLAGS_UPDATE_EXT()) {
Expand All @@ -737,11 +763,12 @@ void RAMFUNCTION wolfBoot_update_trigger(void)
* partition based on how many flags are non-erased
* FLAGS_INVERT needs erased flags because the bin-assemble's fill byte may
* not match what's in wolfBoot */
#if defined(NVM_FLASH_WRITEONCE) || defined(WOLFBOOT_FLAGS_INVERT)
if (FLAGS_UPDATE_EXT()) {
ext_flash_erase(lastSector, SECTOR_FLAGS_SIZE);
} else {
#ifdef NVM_FLASH_WRITEONCE
#ifndef NVM_FLASH_WRITEONCE
hal_flash_erase(lastSector, SECTOR_FLAGS_SIZE);
#else
selSec = nvm_select_fresh_sector(PART_UPDATE);
XMEMCPY(NVM_CACHE,
(uint8_t*)(lastSector - WOLFBOOT_SECTOR_SIZE * selSec),
Expand All @@ -753,11 +780,8 @@ void RAMFUNCTION wolfBoot_update_trigger(void)
/* erase the previously selected sector */
hal_flash_erase(lastSector - WOLFBOOT_SECTOR_SIZE * selSec,
WOLFBOOT_SECTOR_SIZE);
#elif defined(WOLFBOOT_FLAGS_INVERT)
hal_flash_erase(lastSector, SECTOR_FLAGS_SIZE);
#endif
}
#endif

wolfBoot_set_partition_state(PART_UPDATE, st);

Expand All @@ -782,10 +806,16 @@ void RAMFUNCTION wolfBoot_success(void)
if (FLAGS_BOOT_EXT()) {
ext_flash_unlock();
wolfBoot_set_partition_state(PART_BOOT, st);
/* set update so IMG_STATE_FINAL_FLAGS isn't triggering pointless calls
* to wolfBoot update */
wolfBoot_set_partition_state(PART_UPDATE, st);
ext_flash_lock();
} else {
hal_flash_unlock();
wolfBoot_set_partition_state(PART_BOOT, st);
/* set update so IMG_STATE_FINAL_FLAGS isn't triggering pointless calls
* to wolfBoot update */
wolfBoot_set_partition_state(PART_UPDATE, st);
hal_flash_lock();
}
#ifdef EXT_ENCRYPTED
Expand Down Expand Up @@ -1347,21 +1377,37 @@ static int RAMFUNCTION hal_set_key(const uint8_t *k, const uint8_t *nonce)
addr_align = addr & (~(WOLFBOOT_SECTOR_SIZE - 1));
addr_off = addr & (WOLFBOOT_SECTOR_SIZE - 1);
#ifdef NVM_FLASH_WRITEONCE
/* we read from the populated sector, now write to the erased sector */
sel_sec = nvm_select_fresh_sector(PART_BOOT);
addr_align -= (sel_sec * WOLFBOOT_SECTOR_SIZE);
#endif
hal_flash_unlock();
/* casting to unsigned long to abide compilers on 64bit architectures */
XMEMCPY(ENCRYPT_CACHE,
(void*)(unsigned long)(addr_align) ,
(void*)(unsigned long)(addr_align),
WOLFBOOT_SECTOR_SIZE);
#ifdef NVM_FLASH_WRITEONCE
/* we read from the populated sector, now write to the erased sector */
addr_align = addr & (~(WOLFBOOT_SECTOR_SIZE - 1));
addr_align -= (!sel_sec * WOLFBOOT_SECTOR_SIZE);
#else
/* erase the old key */
ret = hal_flash_erase(addr_align, WOLFBOOT_SECTOR_SIZE);
if (ret != 0)
return ret;
#endif
XMEMCPY(ENCRYPT_CACHE + addr_off, k, ENCRYPT_KEY_SIZE);
XMEMCPY(ENCRYPT_CACHE + addr_off + ENCRYPT_KEY_SIZE, nonce,
ENCRYPT_NONCE_SIZE);
ret = hal_flash_write(addr_align, ENCRYPT_CACHE, WOLFBOOT_SECTOR_SIZE);
#ifdef NVM_FLASH_WRITEONCE
/* now erase the old populated sector */
if (ret != 0)
return ret;
addr_align = addr & (~(WOLFBOOT_SECTOR_SIZE - 1));
addr_align -= (sel_sec * WOLFBOOT_SECTOR_SIZE);
ret = hal_flash_erase(addr_align, WOLFBOOT_SECTOR_SIZE);
#endif
hal_flash_lock();
return ret;
#endif
Expand All @@ -1387,12 +1433,12 @@ int RAMFUNCTION wolfBoot_set_encrypt_key(const uint8_t *key,

#ifndef UNIT_TEST
/**
* @brief Set the encryption key.
* @brief Get the encryption key.
*
* This function sets the encryption key and nonce used for encrypting the
* firmware image. It stores the key and nonce in the designated memory location.
* This function gets the encryption key and nonce used for encrypting the
* firmware image.
*
* @param key Pointer to the encryption key.
* @param k Pointer to the encryption key.
* @param nonce Pointer to the encryption nonce.
*
* @return 0 if successful.
Expand Down Expand Up @@ -1626,10 +1672,12 @@ static uint8_t RAMFUNCTION part_address(uintptr_t a)
* @param address The address in the external flash to write the data to.
* @param data Pointer to the data buffer to be written.
* @param len The length of the data to be written.
* @param forcedEnc force writing encryption, used during final swap
*
* @return int 0 if successful, -1 on failure.
*/
int RAMFUNCTION ext_flash_encrypt_write(uintptr_t address, const uint8_t *data, int len)
int RAMFUNCTION ext_flash_encrypt_write(uintptr_t address, const uint8_t *data,
int len)
{
uint8_t block[ENCRYPT_BLOCK_SIZE];
uint8_t enc_block[ENCRYPT_BLOCK_SIZE];
Expand Down Expand Up @@ -1694,6 +1742,7 @@ int RAMFUNCTION ext_flash_encrypt_write(uintptr_t address, const uint8_t *data,

return ext_flash_write(address, ENCRYPT_CACHE, step);
}

/**
* @brief Read and decrypt data from an external flash.
*
Expand Down
Loading
Loading