Added test for delta-update-ext

pull/150/head
Daniele Lacamera 2021-10-05 21:13:07 +02:00
parent dbc8ea9589
commit aaf780fae9
6 changed files with 137 additions and 46 deletions

View File

@ -0,0 +1,14 @@
TARGET=stm32wb
SIGN=ECC256
HASH=SHA256
WOLFBOOT_SECTOR_SIZE=0x1000
WOLFBOOT_PARTITION_SIZE=0x20000
WOLFBOOT_PARTITION_BOOT_ADDRESS=0x0800C000
WOLFBOOT_PARTITION_UPDATE_ADDRESS=0
WOLFBOOT_PARTITION_SWAP_ADDRESS=0x20000
NVM_FLASH_WRITEONCE=1
DELTA_UPDATES=1
EXT_FLASH=1
UART_FLASH=1
PKA=0
DEBUG=0

View File

@ -36,7 +36,7 @@
#define WOLFBOOT_DELTA_H
#include "target.h"
#define DELTA_PATCH_BLOCK_SIZE 32
#define DELTA_PATCH_BLOCK_SIZE 1024
struct wb_patch_ctx {
uint8_t *src_base;

View File

@ -46,8 +46,8 @@ struct BLOCK_HDR_PACKED block_hdr {
# define WOLFBOOT_SECTOR_SIZE 0x1000
#endif
int wb_patch_init(WB_PATCH_CTX *bm, uint8_t *src, uint32_t ssz, uint8_t *patch, uint32_t psz)
int wb_patch_init(WB_PATCH_CTX *bm, uint8_t *src, uint32_t ssz, uint8_t *patch,
uint32_t psz)
{
if (!bm || ssz == 0 || psz == 0) {
return -1;
@ -57,24 +57,33 @@ int wb_patch_init(WB_PATCH_CTX *bm, uint8_t *src, uint32_t ssz, uint8_t *patch,
bm->src_size = ssz;
bm->patch_base = patch;
bm->patch_size = psz;
#ifdef EXT_FLASH
bm->patch_cache_start = 0xFFFFFFFF;
#endif
return 0;
}
#ifdef EXT_FLASH
#define PATCH_CACHE_SIZE 256
#define DELTA_SWAP_CACHE_SIZE 1024
static inline uint8_t *patch_read_cache(WB_PATCH_CTX *ctx)
{
ext_flash_check_read(
(uintptr_t)WOLFBOOT_PARTITION_UPDATE_ADDRESS + ctx->p_off,
ctx->patch_cache, DELTA_PATCH_BLOCK_SIZE);
if (ctx->patch_cache_start != 0xFFFFFFFF) {
if (ctx->patch_cache_start == ctx->p_off)
return ctx->patch_cache;
if (ctx->p_off < ctx->patch_cache_start +
(DELTA_PATCH_BLOCK_SIZE - BLOCK_HDR_SIZE))
return ctx->patch_cache + ctx->p_off;
}
ctx->patch_cache_start = ctx->p_off;
ext_flash_check_read(
(uintptr_t)(ctx->patch_base + ctx->p_off),
ctx->patch_cache, DELTA_PATCH_BLOCK_SIZE);
return ctx->patch_cache;
}
static inline void store_patched(void *address, const uint8_t *data, int len)
{
(void)ext_flash_check_write((uintptr_t)address, data, len);
}
#else
@ -83,11 +92,6 @@ static inline uint8_t *patch_read_cache(WB_PATCH_CTX *ctx)
return ctx->patch_base + ctx->p_off;
}
static inline void store_patched(void *address, const uint8_t *data, int len)
{
memcpy(address, data, len);
}
#endif
int wb_patch(WB_PATCH_CTX *ctx, uint8_t *dst, uint32_t len)
@ -103,17 +107,13 @@ int wb_patch(WB_PATCH_CTX *ctx, uint8_t *dst, uint32_t len)
return -1;
while ( ( (ctx->matching != 0) || (ctx->p_off < ctx->patch_size)) && (dst_off < len)) {
#ifdef EXT_FLASH
uint8_t *pp = patch_read_cache(ctx);
#else
uint8_t *pp = (ctx->patch_base + ctx->p_off);
#endif
if (ctx->matching) {
/* Resume matching block from previous sector */
sz = ctx->blk_sz;
if (sz > len)
sz = len;
store_patched((void *)(dst + dst_off), ctx->src_base + ctx->blk_off, sz);
memcpy(dst + dst_off, ctx->src_base + ctx->blk_off, sz);
if (ctx->blk_sz > len) {
ctx->blk_sz -= len;
ctx->blk_off += len;
@ -127,7 +127,7 @@ int wb_patch(WB_PATCH_CTX *ctx, uint8_t *dst, uint32_t len)
}
if (*pp == ESC) {
if (*(pp + 1) == ESC) {
store_patched((void *)(dst + dst_off), pp + 1, 1);
*(dst + dst_off) = ESC;
/* Two bytes of the patch have been consumed to produce ESC */
ctx->p_off += 2;
dst_off++;
@ -145,7 +145,7 @@ int wb_patch(WB_PATCH_CTX *ctx, uint8_t *dst, uint32_t len)
} else {
copy_sz = sz;
}
store_patched(dst + dst_off, ctx->src_base + src_off, copy_sz);
memcpy(dst + dst_off, ctx->src_base + src_off, copy_sz);
if (sz == copy_sz) {
/* End of the block, reset counters and matching state */
ctx->matching = 0;
@ -155,7 +155,7 @@ int wb_patch(WB_PATCH_CTX *ctx, uint8_t *dst, uint32_t len)
dst_off += copy_sz;
}
} else {
store_patched((void *)(dst + dst_off), pp, 1);
*(dst + dst_off) = *pp;
dst_off++;
ctx->p_off++;
}

View File

@ -154,7 +154,7 @@ static int RAMFUNCTION wolfBoot_copy_sector(struct wolfBoot_image *src, struct w
#ifdef DELTA_UPDATES
#ifndef DELTA_BLOCK_SIZE
# define DELTA_BLOCK_SIZE 256
# define DELTA_BLOCK_SIZE 1024
#endif
static int wolfBoot_delta_update(struct wolfBoot_image *boot,
@ -169,7 +169,16 @@ static int wolfBoot_delta_update(struct wolfBoot_image *boot,
uint16_t ptr_len;
uint32_t img_offset;
uint16_t img_size;
uint32_t total_size;
WB_PATCH_CTX ctx;
/* Use biggest size for the swap */
total_size = boot->fw_size + IMAGE_HEADER_SIZE;
if ((update->fw_size + IMAGE_HEADER_SIZE) > total_size)
total_size = update->fw_size + IMAGE_HEADER_SIZE;
if (total_size <= IMAGE_HEADER_SIZE)
return -1;
hal_flash_unlock();
#ifdef EXT_FLASH
@ -179,7 +188,6 @@ static int wolfBoot_delta_update(struct wolfBoot_image *boot,
#ifdef EXT_ENCRYPTED
wolfBoot_get_encrypt_key(key, nonce);
#endif
WB_PATCH_CTX ctx;
if (wolfBoot_get_delta_info(PART_UPDATE, inverse, &img_offset, &img_size) < 0) {
return -1;
}
@ -201,7 +209,7 @@ static int wolfBoot_delta_update(struct wolfBoot_image *boot,
if (ret < 0)
return ret;
while((sector * WOLFBOOT_SECTOR_SIZE) < WOLFBOOT_PARTITION_SIZE) {
while((sector * WOLFBOOT_SECTOR_SIZE) < (int)total_size) {
if ((wolfBoot_get_update_sector_flag(sector, &flag) != 0) || (flag == SECT_FLAG_NEW)) {
uint32_t len = 0;
wb_flash_erase(swap, 0, WOLFBOOT_SECTOR_SIZE);
@ -237,9 +245,35 @@ static int wolfBoot_delta_update(struct wolfBoot_image *boot,
if (((sector + 1) * WOLFBOOT_SECTOR_SIZE) < WOLFBOOT_PARTITION_SIZE)
wolfBoot_set_update_sector_flag(sector, flag);
}
#if 0
if (sector == 0) {
/* New total image size after first sector is patched */
volatile uint32_t update_size;
update_size =
wolfBoot_image_size((uint8_t *)WOLFBOOT_PARTITION_BOOT_ADDRESS)
+ IMAGE_HEADER_SIZE;
if (update_size > total_size)
total_size = update_size;
if (total_size <= IMAGE_HEADER_SIZE) {
ret = -1;
goto out;
}
if (total_size > WOLFBOOT_PARTITION_SIZE) {
ret = -1;
goto out;
}
}
#endif
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);
sector++;
}
//wb_flash_erase(swap, 0, WOLFBOOT_SECTOR_SIZE);
st = IMG_STATE_TESTING;
wolfBoot_set_partition_state(PART_BOOT, st);
out:
@ -264,6 +298,7 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed)
uint32_t sector = 0;
uint8_t flag, st;
struct wolfBoot_image boot, update, swap;
uint16_t update_type;
#ifdef EXT_ENCRYPTED
uint8_t key[ENCRYPT_KEY_SIZE];
uint8_t nonce[ENCRYPT_NONCE_SIZE];
@ -282,17 +317,22 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed)
if (total_size <= IMAGE_HEADER_SIZE)
return -1;
/* In case this is a new update, do the required
* checks on the firmware update
* before starting the swap
*/
update_type = wolfBoot_get_image_type(PART_UPDATE);
#ifdef DELTA_UPDATES
if ((update_type & 0x00F0) == HDR_IMG_TYPE_DIFF) {
return wolfBoot_delta_update(&boot, &update, &swap, fallback_allowed);
}
#endif
/* Check the first sector to detect interrupted update */
if ((wolfBoot_get_update_sector_flag(0, &flag) < 0) || (flag == SECT_FLAG_NEW))
{
uint16_t update_type;
/* In case this is a new update, do the required
* checks on the firmware update
* before starting the swap
*/
update_type = wolfBoot_get_image_type(PART_UPDATE);
if (((update_type & 0x000F) != HDR_IMG_TYPE_APP) || ((update_type & 0xFF00) != HDR_IMG_TYPE_AUTH))
return -1;
if (!update.hdr_ok || (wolfBoot_verify_integrity(&update) < 0)
@ -303,15 +343,9 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed)
if ( !fallback_allowed &&
(wolfBoot_update_firmware_version() <= wolfBoot_current_firmware_version()) )
return -1;
#endif
#ifdef DELTA_UPDATES
if ((update_type & 0x00F0) == HDR_IMG_TYPE_DIFF) {
return wolfBoot_delta_update(&boot, &update, &swap, fallback_allowed);
}
#endif
}
hal_flash_unlock();
#ifdef EXT_FLASH
ext_flash_unlock();

View File

@ -4,9 +4,15 @@ test-delta-update:USBTTY?=/dev/ttyACM0
test-delta-update:TIMEOUT?=60
test-delta-update:EXPVER=tools/test-expect-version/test-expect-version /dev/ttyACM0
test-delta-update-ext:SIGN_ARGS?=--ecc256
test-delta-update-ext:SIGN_DELTA_ARGS?=--ecc256 --encrypt /tmp/enc_key.der
test-delta-update-ext:USBTTY?=/dev/ttyACM0
test-delta-update-ext:TIMEOUT?=30
test-delta-update-ext:EXPVER=tools/test-expect-version/test-expect-version /dev/ttyACM0
test-delta-update: factory.bin test-app/image.bin tools/uart-flash-server/ufserver tools/delta/bmdiff tools/test-expect-version/test-expect-version
@st-flash erase
@st-flash reset
@st-flash erase || st-flash erase
@diff .config config/examples/stm32wb-delta.config || (echo "\n\n*** Error: please copy config/examples/stm32wb-delta.config to .config to run this test\n\n" && exit 1)
$(SIGN_TOOL) $(SIGN_ARGS) --delta test-app/image_v1_signed.bin test-app/image.bin \
$(PRIVATE_KEY) 7
@ -16,13 +22,11 @@ test-delta-update: factory.bin test-app/image.bin tools/uart-flash-server/ufserv
@echo Expecting version '1'
@(test `$(EXPVER)` -eq 1)
@echo
@sleep 2
@st-flash write test-app/image_v7_signed_diff.bin 0x0802C000
@sleep 1
@st-flash reset
@echo Expecting version '1'
@(test `$(EXPVER)` -eq 1)
@sleep 2
@st-flash reset
@sleep 20
@echo Expecting version '7'
@(test `$(EXPVER)` -eq 7)
@sleep 2
@ -33,8 +37,8 @@ test-delta-update: factory.bin test-app/image.bin tools/uart-flash-server/ufserv
@st-flash reset
@echo Expecting version '1'
@(test `$(EXPVER)` -eq 1)
@st-flash erase
@st-flash reset
@st-flash erase || st-flash erase
@st-flash write factory.bin 0x08000000
@echo Expecting version '1'
@(test `$(EXPVER)` -eq 1)
@ -53,3 +57,25 @@ test-delta-update: factory.bin test-app/image.bin tools/uart-flash-server/ufserv
@(test `$(EXPVER)` -eq 2)
@echo "TEST SUCCESSFUL"
test-delta-update-ext: factory.bin test-app/image.bin tools/uart-flash-server/ufserver tools/delta/bmdiff tools/test-expect-version/test-expect-version
@st-flash reset
@st-flash erase || st-flash erase
@diff .config config/examples/stm32wb-delta-ext.config || (echo "\n\n*** Error: please copy config/examples/stm32wb-delta-ext.config to .config to run this test\n\n" && exit 1)
$(SIGN_TOOL) $(SIGN_ARGS) --delta test-app/image_v1_signed.bin test-app/image.bin \
$(PRIVATE_KEY) 7
@(tools/uart-flash-server/ufserver test-app/image_v7_signed_diff.bin $(USBTTY))&
@st-flash write factory.bin 0x08000000
@sync
@echo Waiting $(TIMEOUT) seconds...
@sleep $(TIMEOUT)
@st-flash reset
@sleep 3
@killall ufserver
@st-flash reset
@st-flash read boot_full.bin 0x0800C000 0x8000
@SIZE=`wc -c test-app/image_v7_signed.bin | cut -d" " -f 1`; \
dd if=boot_full.bin of=boot.bin bs=1 count=$$SIZE
@diff boot.bin test-app/image_v7_signed.bin || (echo "TEST FAILED" && exit 1)
@rm boot.bin boot_full.bin
@echo "TEST SUCCESSFUL"

View File

@ -45,6 +45,7 @@
#define CMD_HDR_WOLF 'W'
#define CMD_HDR_VER 'V'
#define CMD_APP_VER '*'
#define CMD_HDR_WRITE 0x01
#define CMD_HDR_READ 0x02
#define CMD_HDR_ERASE 0x03
@ -279,6 +280,7 @@ static void uart_flash_erase(uint8_t *base, int ud)
} else {
printmsg(msgEraseSwap);
}
printf("Erase @%x\n", address);
for (i = 0; i < len; i++) {
base[address + i] = 0xFF;
}
@ -305,6 +307,7 @@ static void uart_flash_read(uint8_t *base, int ud)
} else {
printmsg(msgReadSwap);
}
printf("Read @%x\n", address);
if (address + len > (FIRMWARE_PARTITION_SIZE + SWAP_SIZE))
return;
for (i = 0; i < len; i++) {
@ -327,6 +330,7 @@ static void uart_flash_write(uint8_t *base, int ud)
} else {
printmsg(msgWriteSwap);
}
printf("Write @%x\n", address);
if (address + len > (FIRMWARE_PARTITION_SIZE + SWAP_SIZE))
return;
for (i = 0; i < len; i++) {
@ -355,10 +359,23 @@ static void serve_update(uint8_t *base, const char *uart_dev)
if (ret == 0)
continue;
if ((buf[0] != CMD_HDR_WOLF) && (buf[0] != CMD_HDR_VER)) {
if ((buf[0] != CMD_HDR_WOLF) && (buf[0] != CMD_HDR_VER) && (buf[0] != CMD_APP_VER)) {
printf("bad hdr: %02x\n", buf[0]);
continue;
}
if (buf[0] == CMD_APP_VER) {
uint32_t v = 0;
int idx = 1;
while (idx < 5) {
ret = read(ud, buf + idx, 1);
if (ret == 1)
idx++;
}
v = buf[4] + (buf[3] << 8) + (buf[2] << 16) + (buf[1] << 24);
printf("Bootloader version from test app: %u\n", v);
continue;
}
if (buf[0] == CMD_HDR_VER) {
uint32_t v;
int idx = 1;