From f26dd61e2364eff643ff347b1d0184a7ff7b8f55 Mon Sep 17 00:00:00 2001 From: Daniele Lacamera Date: Wed, 6 Oct 2021 15:20:39 +0200 Subject: [PATCH] Fixed delta updates from external devices (+ test) --- include/delta.h | 2 +- src/libwolfboot.c | 8 +++--- src/uart_flash.c | 4 +-- src/update_flash.c | 39 ++++++++++++++++-------------- tools/test-delta.mk | 29 +++++++++++++++------- tools/uart-flash-server/ufserver.c | 12 ++++++++- 6 files changed, 59 insertions(+), 35 deletions(-) diff --git a/include/delta.h b/include/delta.h index 4d81c505..19f101ad 100644 --- a/include/delta.h +++ b/include/delta.h @@ -67,7 +67,7 @@ int wb_diff_init(WB_DIFF_CTX *ctx, uint8_t *src_a, uint32_t len_a, uint8_t *src_ int wb_diff(WB_DIFF_CTX *ctx, uint8_t *patch, uint32_t len); int wb_patch_init(WB_PATCH_CTX *bm, uint8_t *src, uint32_t ssz, uint8_t *patch, uint32_t psz); int wb_patch(WB_PATCH_CTX *ctx, uint8_t *dst, uint32_t len); -int wolfBoot_get_delta_info(uint8_t part, int inverse, uint32_t *img_offset, uint16_t *img_size); +int wolfBoot_get_delta_info(uint8_t part, int inverse, uint32_t **img_offset, uint16_t **img_size); #endif diff --git a/src/libwolfboot.c b/src/libwolfboot.c index 02c7f1b5..13e15531 100644 --- a/src/libwolfboot.c +++ b/src/libwolfboot.c @@ -467,7 +467,7 @@ static inline uint16_t im2ns(uint16_t val) } #ifdef DELTA_UPDATES -int wolfBoot_get_delta_info(uint8_t part, int inverse, uint32_t *img_offset, uint16_t *img_size) +int wolfBoot_get_delta_info(uint8_t part, int inverse, uint32_t **img_offset, uint16_t **img_size) { uint32_t *version_field = NULL; uint32_t *magic = NULL; @@ -500,17 +500,17 @@ int wolfBoot_get_delta_info(uint8_t part, int inverse, uint32_t *img_offset, uin return -1; if (inverse) { if (wolfBoot_find_header((uint8_t *)(image + IMAGE_HEADER_OFFSET), - HDR_IMG_DELTA_INVERSE, (void *)img_offset) != sizeof(uint32_t)) { + HDR_IMG_DELTA_INVERSE, (uint8_t **) img_offset) != sizeof(uint32_t)) { return -1; } if (wolfBoot_find_header((uint8_t *)(image + IMAGE_HEADER_OFFSET), - HDR_IMG_DELTA_INVERSE_SIZE, (void *)img_size) != sizeof(uint16_t)) { + HDR_IMG_DELTA_INVERSE_SIZE, (uint8_t **) img_size) != sizeof(uint16_t)) { return -1; } } else { *img_offset = 0x0000000; if (wolfBoot_find_header((uint8_t *)(image + IMAGE_HEADER_OFFSET), - HDR_IMG_DELTA_SIZE, (void *)img_size) != sizeof(uint16_t)) { + HDR_IMG_DELTA_SIZE, (uint8_t **)img_size) != sizeof(uint16_t)) { return -1; } } diff --git a/src/uart_flash.c b/src/uart_flash.c index 9ed9d693..3cc031d8 100644 --- a/src/uart_flash.c +++ b/src/uart_flash.c @@ -60,7 +60,7 @@ static int uart_rx_timeout(uint8_t *c) volatile int count = 0; while(++count < (WAIT_CYCLES * READ_TIMEOUT)) { if (uart_rx(c) == 1) /* Success */ - return 0; + return 0; } *c = 0x00; return -1; @@ -155,7 +155,7 @@ void ext_flash_unlock(void) { wait_ack(); } - + void uart_send_current_version(void) { uint32_t version = wolfBoot_current_firmware_version(); diff --git a/src/update_flash.c b/src/update_flash.c index 9a0e63d1..20fddf0f 100644 --- a/src/update_flash.c +++ b/src/update_flash.c @@ -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 1024 + # define DELTA_BLOCK_SIZE 1024 #endif static int wolfBoot_delta_update(struct wolfBoot_image *boot, @@ -167,8 +167,8 @@ static int wolfBoot_delta_update(struct wolfBoot_image *boot, uint8_t delta_blk[DELTA_BLOCK_SIZE]; uint32_t offset = 0; uint16_t ptr_len; - uint32_t img_offset; - uint16_t img_size; + uint32_t *img_offset; + uint16_t *img_size; uint32_t total_size; WB_PATCH_CTX ctx; @@ -177,9 +177,6 @@ static int wolfBoot_delta_update(struct wolfBoot_image *boot, 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 ext_flash_unlock(); @@ -198,16 +195,16 @@ static int wolfBoot_delta_update(struct wolfBoot_image *boot, delta_base_v = wolfBoot_get_diffbase_version(PART_UPDATE); if ((cur_v == upd_v) && (delta_base_v < cur_v)) { ret = wb_patch_init(&ctx, boot->hdr, boot->fw_size + IMAGE_HEADER_SIZE, - update->hdr + img_offset, img_size); + update->hdr + *img_offset, *img_size); } else { ret = -1; } } else { ret = wb_patch_init(&ctx, boot->hdr, boot->fw_size + IMAGE_HEADER_SIZE, - update->hdr + IMAGE_HEADER_SIZE, img_size); + update->hdr + IMAGE_HEADER_SIZE, *img_size); } if (ret < 0) - return ret; + goto out; while((sector * WOLFBOOT_SECTOR_SIZE) < (int)total_size) { if ((wolfBoot_get_update_sector_flag(sector, &flag) != 0) || (flag == SECT_FLAG_NEW)) { @@ -245,13 +242,14 @@ 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; + hal_flash_lock(); update_size = wolfBoot_image_size((uint8_t *)WOLFBOOT_PARTITION_BOOT_ADDRESS) + IMAGE_HEADER_SIZE; + hal_flash_unlock(); if (update_size > total_size) total_size = update_size; if (total_size <= IMAGE_HEADER_SIZE) { @@ -264,19 +262,21 @@ static int wolfBoot_delta_update(struct wolfBoot_image *boot, } } -#endif sector++; } ret = 0; while((sector * WOLFBOOT_SECTOR_SIZE) < WOLFBOOT_PARTITION_SIZE) { - hal_flash_erase(WOLFBOOT_PARTITION_BOOT_ADDRESS + + 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); + /* 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(); #endif @@ -324,11 +324,6 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed) 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)) @@ -346,11 +341,19 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed) #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(); #endif + /* Read encryption key/IV before starting the update */ #ifdef EXT_ENCRYPTED wolfBoot_get_encrypt_key(key, nonce); diff --git a/tools/test-delta.mk b/tools/test-delta.mk index 69437697..66f3556a 100644 --- a/tools/test-delta.mk +++ b/tools/test-delta.mk @@ -1,7 +1,6 @@ test-delta-update:SIGN_ARGS?=--ecc256 test-delta-update:SIGN_DELTA_ARGS?=--ecc256 --encrypt /tmp/enc_key.der 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 @@ -26,23 +25,18 @@ test-delta-update: factory.bin test-app/image.bin tools/uart-flash-server/ufserv @st-flash write test-app/image_v7_signed_diff.bin 0x0802C000 @sleep 2 @st-flash reset - @sleep 20 - @echo Expecting version '7' - @(test `$(EXPVER)` -eq 7) - @sleep 2 - @st-flash reset @echo Expecting version '7' @(test `$(EXPVER)` -eq 7) @sleep 2 @st-flash reset @echo Expecting version '1' @(test `$(EXPVER)` -eq 1) - @st-flash reset @st-flash erase || st-flash erase @st-flash write factory.bin 0x08000000 @echo Expecting version '1' @(test `$(EXPVER)` -eq 1) @sleep 1 + @st-flash reset @st-flash write test-app/image_v2_signed_diff.bin 0x0802C000 @st-flash reset @echo Expecting version '2' @@ -69,13 +63,30 @@ test-delta-update-ext: factory.bin test-app/image.bin tools/uart-flash-server/uf @sync @echo Waiting $(TIMEOUT) seconds... @sleep $(TIMEOUT) - @st-flash reset - @sleep 3 @killall ufserver @st-flash reset + @sleep 3 @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" + @sleep 1 + @echo + @echo + @st-flash reset + @(tools/uart-flash-server/ufserver test-app/image_v7_signed_diff.bin $(USBTTY))& + @echo TEST INVERSE + @sleep $(TIMEOUT) + @st-flash reset + @killall ufserver + @st-flash reset + @st-flash read boot_full.bin 0x0800C000 0x8000 + @SIZE=`wc -c test-app/image_v1_signed.bin | cut -d" " -f 1`; \ + dd if=boot_full.bin of=boot.bin bs=1 count=$$SIZE + @diff boot.bin test-app/image_v1_signed.bin || (echo "TEST INVERSE FAILED" && exit 1) + @rm boot.bin boot_full.bin + @echo "TEST SUCCESSFUL" + + diff --git a/tools/uart-flash-server/ufserver.c b/tools/uart-flash-server/ufserver.c index 97169098..e6b53855 100644 --- a/tools/uart-flash-server/ufserver.c +++ b/tools/uart-flash-server/ufserver.c @@ -55,6 +55,10 @@ #define SWAP_SIZE 0x1000 #define UART_BITRATE 115200 +/* Change the following to 1 to debug flash access */ +#define LOG_FLASH_ADDRESS 0 + + const char msgSha[] = "Verifying SHA digest..."; const char msgReadUpdate[] = "Fetching update blocks "; const char msgReadSwap[] = "Reading SWAP blocks "; @@ -280,7 +284,9 @@ static void uart_flash_erase(uint8_t *base, int ud) } else { printmsg(msgEraseSwap); } +#if LOG_FLASH_ADDRESS printf("Erase @%x\n", address); +#endif for (i = 0; i < len; i++) { base[address + i] = 0xFF; } @@ -307,7 +313,9 @@ static void uart_flash_read(uint8_t *base, int ud) } else { printmsg(msgReadSwap); } +#if LOG_FLASH_ADDRESS printf("Read @%x\n", address); +#endif if (address + len > (FIRMWARE_PARTITION_SIZE + SWAP_SIZE)) return; for (i = 0; i < len; i++) { @@ -330,7 +338,9 @@ static void uart_flash_write(uint8_t *base, int ud) } else { printmsg(msgWriteSwap); } +#if LOG_FLASH_ADDRESS printf("Write @%x\n", address); +#endif if (address + len > (FIRMWARE_PARTITION_SIZE + SWAP_SIZE)) return; for (i = 0; i < len; i++) { @@ -373,7 +383,7 @@ static void serve_update(uint8_t *base, const char *uart_dev) } v = buf[4] + (buf[3] << 8) + (buf[2] << 16) + (buf[1] << 24); - printf("Bootloader version from test app: %u\n", v); + printf("Boot partition version from test app: %u\n", v); continue; } if (buf[0] == CMD_HDR_VER) {