mirror of https://github.com/wolfSSL/wolfBoot.git
Added test for delta-update-ext
parent
dbc8ea9589
commit
aaf780fae9
|
@ -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
|
|
@ -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;
|
||||
|
|
44
src/delta.c
44
src/delta.c
|
@ -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++;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue