change the final steps of wolfBoot_update into

repeatable steps so that power failure wont erase the encryption key and wont cause skipping the testing phase of boot. this is done by marking the update partition as final swap when erasing the final sector and backing up the key in boot sector 0 after swaping the real boot sector 0 to swap. then when a power failure occurs the encryption key will be available in either boot sector 0 or the normal location. the intermediate phase also prevents skipping the testing phase since the last sector, which holds the boot state, is erased and then set repeatably, since the final swap state is set on the update partition
pull/379/head
John Bland 2023-08-22 21:59:23 -04:00 committed by Daniele Lacamera
parent ffc7a435e5
commit 00a9572b94
6 changed files with 374 additions and 65 deletions

View File

@ -64,6 +64,8 @@ void aes_set_iv(uint8_t *nonce, uint32_t address);
#endif /* ENCRYPT_WITH_CHACHA */
/* Internal read/write functions (not exported in the libwolfboot API) */
int ext_flash_encrypt_write_ex(uintptr_t address,
const uint8_t *data, int len, int forcedEnc);
int ext_flash_encrypt_write(uintptr_t address, const uint8_t *data, int len);
int ext_flash_decrypt_read(uintptr_t address, uint8_t *data, int len);

View File

@ -616,10 +616,18 @@ static inline int wb_flash_erase(struct wolfBoot_image *img, uint32_t off,
}
static inline int wb_flash_write(struct wolfBoot_image *img, uint32_t off,
const void *data, uint32_t size)
const void *data, uint32_t size, int forcedEncrypt)
{
if (PART_IS_EXT(img))
return ext_flash_check_write((uintptr_t)(img->hdr) + off, data, size);
if (PART_IS_EXT(img)) {
#if defined(EXT_ENCRYPTED) && (defined(__WOLFBOOT) || defined(UNIT_TEST))
if (forcedEncrypt == 1)
return ext_flash_encrypt_write_ex((uintptr_t)(img->hdr) + off, data,
size, forcedEncrypt);
else
#endif
return ext_flash_check_write((uintptr_t)(img->hdr) + off, data,
size);
}
else
return hal_flash_write((uintptr_t)(img->hdr) + off, data, size);
}
@ -657,7 +665,7 @@ static inline int wb_flash_write_verify_word(struct wolfBoot_image *img,
# define PARTN_IS_EXT(x) (0)
# define wb_flash_erase(im, of, siz) \
hal_flash_erase(((uintptr_t)(((im)->hdr)) + of), siz)
# define wb_flash_write(im, of, dat, siz) \
# define wb_flash_write(im, of, dat, siz, I) \
hal_flash_write(((uintptr_t)((im)->hdr)) + of, dat, siz)
#endif /* EXT_FLASH */

View File

@ -244,6 +244,7 @@ extern "C" {
#ifndef WOLFBOOT_FLAGS_INVERT
#define IMG_STATE_NEW 0xFF
#define IMG_STATE_UPDATING 0x70
#define IMG_STATE_FINAL_SWAP 0x30
#define IMG_STATE_TESTING 0x10
#define IMG_STATE_SUCCESS 0x00
#define FLASH_BYTE_ERASED 0xFF
@ -251,6 +252,7 @@ extern "C" {
#else
#define IMG_STATE_NEW 0x00
#define IMG_STATE_UPDATING 0x8F
#define IMG_STATE_FINAL_SWAP 0xBF
#define IMG_STATE_TESTING 0xEF
#define IMG_STATE_SUCCESS 0xFF
#define FLASH_BYTE_ERASED 0x00
@ -314,9 +316,15 @@ int wolfBoot_get_diffbase_hdr(uint8_t part, uint8_t **ptr);
#endif
int wolfBoot_set_encrypt_key(const uint8_t *key, const uint8_t *nonce);
int wolfBoot_backup_encrypt_key(const uint8_t* key, const uint8_t* nonce);
int wolfBoot_get_encrypt_key(uint8_t *key, uint8_t *nonce);
int wolfBoot_erase_encrypt_key(void);
#ifdef FLAGS_HOME
int wolfBoot_flags_home_set_final_swap();
int wolfBoot_flags_home_get_final_swap();
#endif
#ifdef __cplusplus
}
#endif

View File

@ -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
@ -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
@ -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;
@ -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
@ -1385,14 +1431,31 @@ int RAMFUNCTION wolfBoot_set_encrypt_key(const uint8_t *key,
return 0;
}
int RAMFUNCTION wolfBoot_backup_encrypt_key(const uint8_t* key,
const uint8_t* nonce)
{
#ifndef MMU
uint32_t magic[2] = {WOLFBOOT_MAGIC, WOLFBOOT_MAGIC_TRAIL};
hal_flash_write(WOLFBOOT_PARTITION_BOOT_ADDRESS, key,
ENCRYPT_KEY_SIZE);
hal_flash_write(WOLFBOOT_PARTITION_BOOT_ADDRESS +
ENCRYPT_KEY_SIZE, nonce, ENCRYPT_NONCE_SIZE);
/* write magic so we know we finished in case of a powerfail */
hal_flash_write(WOLFBOOT_PARTITION_BOOT_ADDRESS +
ENCRYPT_KEY_SIZE + ENCRYPT_NONCE_SIZE, (uint8_t*)magic, sizeof(magic));
#endif
return 0;
}
#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.
@ -1400,21 +1463,39 @@ int RAMFUNCTION wolfBoot_set_encrypt_key(const uint8_t *key,
*/
int RAMFUNCTION wolfBoot_get_encrypt_key(uint8_t *k, uint8_t *nonce)
{
int ret = 0;
#if defined(MMU)
XMEMCPY(k, ENCRYPT_KEY, ENCRYPT_KEY_SIZE);
XMEMCPY(nonce, ENCRYPT_KEY + ENCRYPT_KEY_SIZE, ENCRYPT_NONCE_SIZE);
#else
uint8_t *mem = (uint8_t *)(ENCRYPT_TMP_SECRET_OFFSET +
WOLFBOOT_PARTITION_BOOT_ADDRESS);
int sel_sec = 0;
#ifdef NVM_FLASH_WRITEONCE
sel_sec = nvm_select_fresh_sector(PART_BOOT);
mem -= (sel_sec * WOLFBOOT_SECTOR_SIZE);
#endif
uint8_t* mem;
uint32_t magic[2];
/* see if we've backed up the key, this will only matter for final swap */
XMEMCPY(magic, (uint8_t*)WOLFBOOT_PARTITION_BOOT_ADDRESS +
ENCRYPT_KEY_SIZE + ENCRYPT_NONCE_SIZE, sizeof(magic));
if (magic[0] == WOLFBOOT_MAGIC && magic[1] == WOLFBOOT_MAGIC_TRAIL) {
mem = (uint8_t*)WOLFBOOT_PARTITION_BOOT_ADDRESS;
/* not a failure but finalize needs to know that it's safe to erase and
* write the key to the normal spot */
ret = 1;
}
else {
mem = (uint8_t *)(ENCRYPT_TMP_SECRET_OFFSET +
WOLFBOOT_PARTITION_BOOT_ADDRESS);
#ifdef NVM_FLASH_WRITEONCE
int sel_sec = 0;
sel_sec = nvm_select_fresh_sector(PART_BOOT);
mem -= (sel_sec * WOLFBOOT_SECTOR_SIZE);
#endif
}
XMEMCPY(k, mem, ENCRYPT_KEY_SIZE);
XMEMCPY(nonce, mem + ENCRYPT_KEY_SIZE, ENCRYPT_NONCE_SIZE);
#endif
return 0;
return ret;
}
#endif
/**
@ -1626,10 +1707,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_ex(uintptr_t address,
const uint8_t *data, int len, int forcedEnc)
{
uint8_t block[ENCRYPT_BLOCK_SIZE];
uint8_t enc_block[ENCRYPT_BLOCK_SIZE];
@ -1664,7 +1747,9 @@ int RAMFUNCTION ext_flash_encrypt_write(uintptr_t address, const uint8_t *data,
break;
case PART_SWAP:
/* data is coming from update and is already encrypted */
return ext_flash_write(address, data, len);
if (forcedEnc == 0)
return ext_flash_write(address, data, len);
break;
default:
return -1;
}
@ -1694,6 +1779,23 @@ int RAMFUNCTION ext_flash_encrypt_write(uintptr_t address, const uint8_t *data,
return ext_flash_write(address, ENCRYPT_CACHE, step);
}
/**
* @brief Write encrypted data to an external flash.
*
* This function calls ext_flash_encrypt_write_ex with forced encryption off
*
* @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.
*
* @return int 0 if successful, -1 on failure.
*/
int RAMFUNCTION ext_flash_encrypt_write(uintptr_t address, const uint8_t *data, int len)
{
return ext_flash_encrypt_write_ex(address, data, len, 0);
}
/**
* @brief Read and decrypt data from an external flash.
*
@ -1840,3 +1942,39 @@ int wolfBoot_ram_decrypt(uint8_t *src, uint8_t *dst)
}
#endif /* MMU */
#endif /* EXT_ENCRYPTED */
#ifdef FLAGS_HOME
/* we need to write a marker to update since the boot and update flags are all
* in the same sector so write magic to the first sector of boot */
int wolfBoot_flags_home_set_final_swap()
{
/* EXT_ENCRYPTED uses the first sector to store the key and magic, don't
* overwrite it */
#ifndef EXT_ENCRYPTED
uint32_t magic[2] = {WOLFBOOT_MAGIC, WOLFBOOT_MAGIC_TRAIL};
uintptr_t addr = (uintptr_t)WOLFBOOT_PARTITION_BOOT_ADDRESS;
hal_flash_write(addr, (uint8_t*)magic, sizeof(magic));
#endif /* !EXT_ENCRYPTED */
return 0;
}
int wolfBoot_flags_home_get_final_swap()
{
uint32_t magic[2];
uintptr_t addr = (uintptr_t)WOLFBOOT_PARTITION_BOOT_ADDRESS;
/* if encryption is on magic will be after the key and nonce */
#ifdef EXT_ENCRYPTED
addr += ENCRYPT_KEY_SIZE + ENCRYPT_NONCE_SIZE;
#endif
XMEMCPY((uint8_t*)magic, (uint8_t*)addr, sizeof(magic));
if (magic[0] == WOLFBOOT_MAGIC && magic[1] == WOLFBOOT_MAGIC_TRAIL)
return 1;
return 0;
}
#endif /* FLAGS_HOME */

View File

@ -123,7 +123,8 @@ void wolfBoot_check_self_update(void)
}
#endif /* RAM_CODE for self_update */
static int RAMFUNCTION wolfBoot_copy_sector(struct wolfBoot_image *src, struct wolfBoot_image *dst, uint32_t sector)
static int RAMFUNCTION wolfBoot_copy_sector(struct wolfBoot_image *src,
struct wolfBoot_image *dst, uint32_t sector, int forcedEncrypt)
{
uint32_t pos = 0;
uint32_t src_sector_offset = (sector * WOLFBOOT_SECTOR_SIZE);
@ -173,8 +174,8 @@ static int RAMFUNCTION wolfBoot_copy_sector(struct wolfBoot_image *src, struct w
(void *)buffer, FLASHBUFFER_SIZE);
}
wb_flash_write(dst,
dst_sector_offset + pos, buffer, FLASHBUFFER_SIZE);
wb_flash_write(dst, dst_sector_offset + pos, buffer,
FLASHBUFFER_SIZE, forcedEncrypt);
}
pos += FLASHBUFFER_SIZE;
}
@ -183,15 +184,108 @@ static int RAMFUNCTION wolfBoot_copy_sector(struct wolfBoot_image *src, struct w
#endif
wb_flash_erase(dst, dst_sector_offset, WOLFBOOT_SECTOR_SIZE);
while (pos < WOLFBOOT_SECTOR_SIZE) {
if (src_sector_offset + pos < (src->fw_size + IMAGE_HEADER_SIZE + FLASHBUFFER_SIZE)) {
if (src_sector_offset + pos < (src->fw_size + IMAGE_HEADER_SIZE +
FLASHBUFFER_SIZE)) {
uint8_t *orig = (uint8_t*)(src->hdr + src_sector_offset + pos);
wb_flash_write(dst, dst_sector_offset + pos, orig, FLASHBUFFER_SIZE);
wb_flash_write(dst, dst_sector_offset + pos, orig, FLASHBUFFER_SIZE,
forcedEncrypt);
}
pos += FLASHBUFFER_SIZE;
}
return pos;
}
static int wolfBoot_finalize(struct wolfBoot_image *boot,
struct wolfBoot_image *update, struct wolfBoot_image *swap)
{
uint8_t st;
uint32_t sector = (WOLFBOOT_PARTITION_SIZE / WOLFBOOT_SECTOR_SIZE) - 1;
#ifdef FLAGS_HOME
/* set the UPDATE state as FINAL_SWAP in case it was erased in a later
* step last boot */
st = IMG_STATE_FINAL_SWAP;
wolfBoot_set_partition_state(PART_UPDATE, st);
#endif
#ifdef EXT_ENCRYPTED
int ret = 0;
uint8_t key[ENCRYPT_KEY_SIZE];
uint8_t nonce[ENCRYPT_NONCE_SIZE];
/* get the encryption key, this will check the backup */
ret = wolfBoot_get_encrypt_key(key, nonce);
/* key came from the backup, this means it's safe and neccassary to erase
* and re-write the key to the normal spot */
if (ret == 1) {
hal_flash_lock();
wolfBoot_set_encrypt_key(key, nonce);
hal_flash_unlock();
}
/* erase the first sector of boot */
wb_flash_erase(boot, 0, WOLFBOOT_SECTOR_SIZE);
/* backup the key */
wolfBoot_backup_encrypt_key(key, nonce);
#elif defined(FLAGS_HOME)
/* erase the first sector of boot */
wb_flash_erase(boot, 0, WOLFBOOT_SECTOR_SIZE);
/* write magic to sector 0 so we know it's final swap */
wolfBoot_flags_home_set_final_swap();
#endif
#ifdef NVM_FLASH_WRITEONCE
/* erase the alternate sector */
wb_flash_erase(boot, (sector - 1) * WOLFBOOT_SECTOR_SIZE,
WOLFBOOT_SECTOR_SIZE);
#endif
/* erase the last sector of boot */
wb_flash_erase(boot, sector * WOLFBOOT_SECTOR_SIZE, WOLFBOOT_SECTOR_SIZE);
#ifdef EXT_ENCRYPTED
hal_flash_lock();
/* write the key back to the last sector */
wolfBoot_set_encrypt_key(key, nonce);
hal_flash_unlock();
#endif
#if defined(EXT_ENCRYPTED) || defined(FLAGS_HOME)
/* decrypt and copy the first sector back to boot */
wolfBoot_copy_sector(swap, boot, 0, 0);
#endif
/* set the boot state to testing */
st = IMG_STATE_TESTING;
wolfBoot_set_partition_state(PART_BOOT, st);
#ifdef NVM_FLASH_WRITEONCE
/* erase the alternate sector */
wb_flash_erase(update, (sector - 1) * WOLFBOOT_SECTOR_SIZE,
WOLFBOOT_SECTOR_SIZE);
#endif
/* erase the last sector of update */
wb_flash_erase(update, sector * WOLFBOOT_SECTOR_SIZE, WOLFBOOT_SECTOR_SIZE);
/* erase swap */
wb_flash_erase(swap, 0, WOLFBOOT_SECTOR_SIZE);
#ifdef EXT_FLASH
ext_flash_lock();
#endif
hal_flash_lock();
return 0;
}
#ifdef DELTA_UPDATES
#ifndef DELTA_BLOCK_SIZE
@ -276,7 +370,7 @@ static int wolfBoot_delta_update(struct wolfBoot_image *boot,
goto out;
}
#else
wb_flash_write(swap, len, delta_blk, ret);
wb_flash_write(swap, len, delta_blk, ret, 0);
#endif
len += ret;
} else if (ret == 0) {
@ -301,7 +395,7 @@ static int wolfBoot_delta_update(struct wolfBoot_image *boot,
}
}
if (flag == SECT_FLAG_SWAPPING) {
wolfBoot_copy_sector(swap, boot, sector);
wolfBoot_copy_sector(swap, boot, sector, 0);
flag = SECT_FLAG_UPDATED;
if (((sector + 1) * WOLFBOOT_SECTOR_SIZE) < WOLFBOOT_PARTITION_SIZE)
wolfBoot_set_update_sector_flag(sector, flag);
@ -329,27 +423,36 @@ static int wolfBoot_delta_update(struct wolfBoot_image *boot,
sector++;
}
ret = 0;
while((sector * WOLFBOOT_SECTOR_SIZE) < WOLFBOOT_PARTITION_SIZE) {
hal_flash_erase(WOLFBOOT_PARTITION_BOOT_ADDRESS +
sector * WOLFBOOT_SECTOR_SIZE, WOLFBOOT_SECTOR_SIZE);
/* erase to the last sector, writeonce has 2 sectors */
while((sector * WOLFBOOT_SECTOR_SIZE) < WOLFBOOT_PARTITION_SIZE -
WOLFBOOT_SECTOR_SIZE
#ifdef NVM_FLASH_WRITEONCE
* 2
#endif
) {
wb_flash_erase(boot, sector * WOLFBOOT_SECTOR_SIZE, WOLFBOOT_SECTOR_SIZE);
sector++;
}
st = IMG_STATE_TESTING;
wolfBoot_set_partition_state(PART_BOOT, st);
/* On success, reset all flags on update partition */
wb_flash_erase(update, WOLFBOOT_PARTITION_SIZE - WOLFBOOT_SECTOR_SIZE,
WOLFBOOT_SECTOR_SIZE);
out:
wb_flash_erase(swap, 0, WOLFBOOT_SECTOR_SIZE);
#ifdef EXT_FLASH
ext_flash_lock();
#if defined(EXT_ENCRYPTED) || defined(FLAGS_HOME)
/* copy the first sector of boot to swap so we can use it for the final
* swap, force encryption */
wolfBoot_copy_sector(boot, swap, 0, 1);
#endif
hal_flash_lock();
/* set the UPDATE state as FINAL_SWAP */
st = IMG_STATE_FINAL_SWAP;
wolfBoot_set_partition_state(PART_UPDATE, st);
/* Save the encryption key after swapping */
#ifdef EXT_ENCRYPTED
wolfBoot_set_encrypt_key(key, nonce);
#ifdef FLAGS_HOME
/* erase the first sector of boot */
wb_flash_erase(boot, 0, WOLFBOOT_SECTOR_SIZE);
/* set final swap */
wolfBoot_flags_home_set_final_swap();
#endif
/* finalize the boot sector */
wolfBoot_finalize(boot, update, swap);
out:
return ret;
}
@ -406,6 +509,26 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed)
wolfBoot_open_image(&boot, PART_BOOT);
wolfBoot_open_image(&swap, PART_SWAP);
#ifndef DISABLE_BACKUP
/* if we were on the final swap just finish it */
if ((wolfBoot_get_partition_state(PART_UPDATE, &st) == 0 &&
st == IMG_STATE_FINAL_SWAP)
#ifdef FLAGS_HOME
|| wolfBoot_flags_home_get_final_swap()
#endif
) {
hal_flash_unlock();
#ifdef EXT_FLASH
ext_flash_unlock();
#endif
wolfBoot_finalize(&boot, &update, &swap);
return 0;
}
#endif
/* get total size */
total_size = wolfBoot_get_total_size(&boot, &update);
@ -474,12 +597,6 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed)
ext_flash_unlock();
#endif
/* Read encryption key/IV before starting the update */
#ifdef EXT_ENCRYPTED
wolfBoot_get_encrypt_key(key, nonce);
#endif
#ifndef DISABLE_BACKUP
/* Interruptible swap
* The status is saved in the sector flags of the update partition.
@ -488,7 +605,7 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed)
while ((sector * sector_size) < total_size) {
if ((wolfBoot_get_update_sector_flag(sector, &flag) != 0) || (flag == SECT_FLAG_NEW)) {
flag = SECT_FLAG_SWAPPING;
wolfBoot_copy_sector(&update, &swap, sector);
wolfBoot_copy_sector(&update, &swap, sector, 0);
if (((sector + 1) * sector_size) < WOLFBOOT_PARTITION_SIZE)
wolfBoot_set_update_sector_flag(sector, flag);
}
@ -497,8 +614,8 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed)
if (size > sector_size)
size = sector_size;
flag = SECT_FLAG_BACKUP;
wolfBoot_copy_sector(&boot, &update, sector);
if (((sector + 1) * sector_size) < WOLFBOOT_PARTITION_SIZE)
wolfBoot_copy_sector(&boot, &update, sector, 0);
if (((sector + 1) * sector_size) < WOLFBOOT_PARTITION_SIZE)
wolfBoot_set_update_sector_flag(sector, flag);
}
if (flag == SECT_FLAG_BACKUP) {
@ -506,7 +623,7 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed)
if (size > sector_size)
size = sector_size;
flag = SECT_FLAG_UPDATED;
wolfBoot_copy_sector(&swap, &boot, sector);
wolfBoot_copy_sector(&swap, &boot, sector, 0);
if (((sector + 1) * sector_size) < WOLFBOOT_PARTITION_SIZE)
wolfBoot_set_update_sector_flag(sector, flag);
}
@ -531,16 +648,45 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed)
return -1;
}
}
while((sector * sector_size) < WOLFBOOT_PARTITION_SIZE) {
/* erase to the last sector, writeonce has 2 sectors */
while((sector * sector_size) < WOLFBOOT_PARTITION_SIZE -
sector_size
#ifdef NVM_FLASH_WRITEONCE
* 2
#endif
) {
wb_flash_erase(&boot, sector * sector_size, sector_size);
wb_flash_erase(&update, sector * sector_size, sector_size);
sector++;
}
wb_flash_erase(&swap, 0, WOLFBOOT_SECTOR_SIZE);
st = IMG_STATE_TESTING;
wolfBoot_set_partition_state(PART_BOOT, st);
#if defined(EXT_ENCRYPTED) || defined(FLAGS_HOME)
/* copy the first sector of boot to swap so we can use it for the final
* swap, force encryption */
wolfBoot_copy_sector(&boot, &swap, 0, 1);
#endif
/* set the UPDATE state as FINAL_SWAP */
st = IMG_STATE_FINAL_SWAP;
wolfBoot_set_partition_state(PART_UPDATE, st);
#ifdef FLAGS_HOME
/* erase the first sector of boot */
wb_flash_erase(&boot, 0, WOLFBOOT_SECTOR_SIZE);
/* set final swap */
wolfBoot_flags_home_set_final_swap();
#endif
/* finalize the boot sector */
wolfBoot_finalize(&boot, &update, &swap);
#else /* DISABLE_BACKUP */
#warning "Backup mechanism disabled! Update installation will not be interruptible"
/* Read encryption key/IV before starting the update */
#ifdef EXT_ENCRYPTED
wolfBoot_get_encrypt_key(key, nonce);
#endif
/* Directly copy the content of the UPDATE partition into the BOOT partition.
* This mechanism is not fail-safe, and will brick your device if interrupted
* before the copy is finished.
@ -548,7 +694,7 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed)
while ((sector * sector_size) < total_size) {
if ((wolfBoot_get_update_sector_flag(sector, &flag) != 0) || (flag == SECT_FLAG_NEW)) {
flag = SECT_FLAG_SWAPPING;
wolfBoot_copy_sector(&update, &boot, sector);
wolfBoot_copy_sector(&update, &boot, sector, 0);
if (((sector + 1) * sector_size) < WOLFBOOT_PARTITION_SIZE)
wolfBoot_set_update_sector_flag(sector, flag);
}
@ -560,7 +706,6 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed)
}
st = IMG_STATE_SUCCESS;
wolfBoot_set_partition_state(PART_BOOT, st);
#endif
#ifdef EXT_FLASH
ext_flash_lock();
@ -571,6 +716,8 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed)
#ifdef EXT_ENCRYPTED
wolfBoot_set_encrypt_key(key, nonce);
#endif
#endif /* DISABLE_BACKUP */
return 0;
}
@ -712,7 +859,14 @@ void RAMFUNCTION wolfBoot_start(void)
wolfBoot_update_trigger();
}
wolfBoot_update(1);
} else if ((wolfBoot_get_partition_state(PART_UPDATE, &st) == 0) && (st == IMG_STATE_UPDATING)) {
/* Check for new updates in the UPDATE partition or if we were
* interrupted during the final sector write */
} else if (((wolfBoot_get_partition_state(PART_UPDATE, &st) == 0) &&
(st == IMG_STATE_UPDATING || st == IMG_STATE_FINAL_SWAP))
#ifdef FLAGS_HOME
|| wolfBoot_flags_home_get_final_swap()
#endif
) {
/* Check for new updates in the UPDATE partition */
wolfBoot_update(0);
}

View File

@ -56,6 +56,9 @@ int do_cmd(const char *cmd)
return 0;
}
if (strcmp(cmd, "update_trigger") == 0) {
#if EXT_ENCRYPTED
wolfBoot_set_encrypt_key((uint8_t *)enc_key,(uint8_t *)(enc_key + 32));
#endif
wolfBoot_update_trigger();
return 0;
}
@ -74,10 +77,6 @@ int main(int argc, char *argv[]) {
hal_init();
#if EXT_ENCRYPTED
wolfBoot_set_encrypt_key((uint8_t *)enc_key,(uint8_t *)(enc_key + 32));
#endif
for (i = 1; i < argc; ++i) {
ret = do_cmd(argv[i]);
if (ret < 0)