From 7cc3af76417f27d94a960479fdd3ab15ba17ab4c Mon Sep 17 00:00:00 2001 From: David Garske Date: Mon, 30 Sep 2024 14:41:29 -0700 Subject: [PATCH] Fix for the `set_trailer_at` with external flash to use 32-bit write using cached value (Many QSPI hardware peripherals do not support a single byte write). Fix delta build error with DISABLE_BACKUP. Added tests for updating both cores in build_flash.sh. --- config/examples/nrf5340.config | 5 ++ config/examples/nrf5340_net.config | 1 + hal/nrf5340.c | 89 ++++++++++++---------------- hal/spi/spi_drv_nrf5340.h | 4 +- include/spi_drv.h | 3 - src/libwolfboot.c | 12 +++- src/qspi_flash.c | 10 +++- src/update_flash.c | 2 + tools/scripts/nrf5340/build_flash.sh | 12 +++- 9 files changed, 75 insertions(+), 63 deletions(-) diff --git a/config/examples/nrf5340.config b/config/examples/nrf5340.config index d12984ccd..c92b5bc84 100644 --- a/config/examples/nrf5340.config +++ b/config/examples/nrf5340.config @@ -11,6 +11,7 @@ NO_ASM?=0 NO_MPU=1 ALLOW_DOWNGRADE?=0 NVM_FLASH_WRITEONCE?=0 +DELTA_UPDATES?=1 SPMATH?=1 RAM_CODE?=1 @@ -44,4 +45,8 @@ DEBUG?=0 DEBUG_UART?=1 USE_GCC=1 +# Use larger block size for swapping sectors +CFLAGS_EXTRA+=-DFLASHBUFFER_SIZE=0x1000 + CFLAGS_EXTRA+=-DDEBUG_FLASH +CFLAGS_EXTRA+=-DDEBUG_QSPI=1 diff --git a/config/examples/nrf5340_net.config b/config/examples/nrf5340_net.config index 81010a008..f4dd88b41 100644 --- a/config/examples/nrf5340_net.config +++ b/config/examples/nrf5340_net.config @@ -11,6 +11,7 @@ NO_ASM?=1 NO_MPU=1 ALLOW_DOWNGRADE?=0 NVM_FLASH_WRITEONCE?=0 +DELTA_UPDATES?=1 SPMATH?=1 RAM_CODE?=1 diff --git a/hal/nrf5340.c b/hal/nrf5340.c index 9ed31f3ff..32b9215ff 100644 --- a/hal/nrf5340.c +++ b/hal/nrf5340.c @@ -53,11 +53,11 @@ #define SHARED_MEM_ADDR (0x20000000UL + (64 * 1024)) #endif /* Shared memory states (mask, easier to check) */ -#define SHARED_STATUS_UNKNOWN 0 -#define SHARED_STATUS_READY 1 -#define SHARED_STATUS_UPDATE_START 2 -#define SHARED_STATUS_UPDATE_DONE 4 -#define SHARED_STATUS_DO_BOOT 8 +#define SHARED_STATUS_UNKNOWN 0x00 +#define SHARED_STATUS_READY 0x01 +#define SHARED_STATUS_UPDATE_START 0x02 +#define SHARED_STATUS_UPDATE_DONE 0x04 +#define SHARED_STATUS_DO_BOOT 0x08 #define SHAREM_MEM_MAGIC 0x5753484D /* WSHM */ @@ -205,7 +205,7 @@ int RAMFUNCTION hal_flash_erase(uint32_t address, int len) { uint32_t end = address + len - 1; uint32_t p; -#ifdef DEBUG_FLASH +#if defined(DEBUG_FLASH) && DEBUG_FLASH > 1 wolfBoot_printf("Internal Flash Erase: addr 0x%x, len %d\n", address, len); #endif /* mask to page start address */ @@ -354,6 +354,7 @@ static int hal_shm_status_wait(ShmInfo_t* info, uint32_t status, return ret; } +/* Handles network core updates */ static void hal_net_check_version(void) { int ret; @@ -374,51 +375,8 @@ static void hal_net_check_version(void) /* check if network core can continue booting or needs to wait for update */ if (ret != 0 || shm->app.version <= shm->net.version) { wolfBoot_printf("Network Core: Releasing for boot\n"); - hal_shm_status_set(&shm->app, SHARED_STATUS_DO_BOOT); } else { - wolfBoot_printf("Network Core: Holding for update\n"); - } -#else /* TARGET_nrf5340_net */ - hal_net_get_image(&img, &shm->net); - hal_shm_status_set(&shm->net, SHARED_STATUS_READY); - - /* wait for do_boot or update from app core */ - ret = hal_shm_status_wait(&shm->app, - (SHARED_STATUS_UPDATE_START | SHARED_STATUS_DO_BOOT), 1000000); - /* are we updating? */ - if (ret == 0 && shm->app.status == SHARED_STATUS_UPDATE_START) { - wolfBoot_printf("Starting update: Ver %d->%d, Size %d->%d\n", - shm->net.version, shm->app.version, shm->net.size, shm->net.size); - /* Erase network core boot flash */ - hal_flash_erase((uintptr_t)img.hdr, shm->app.size); - /* Write new firmware to internal flash */ - hal_flash_write((uintptr_t)img.hdr, shm->data, shm->app.size); - - /* Reopen image and refresh information */ - hal_net_get_image(&img, &shm->net); - wolfBoot_printf("Network version (after update): 0x%x\n", - shm->net.version); - hal_shm_status_set(&shm->net, SHARED_STATUS_UPDATE_DONE); - - /* continue booting - boot process will validate image hash/signature */ - } -#endif /* TARGET_nrf5340_* */ -exit: - wolfBoot_printf("Status: App %d (ver %d), Net %d (ver %d)\n", - shm->app.status, shm->app.version, shm->net.status, shm->net.version); -} - -#ifdef TARGET_nrf5340_app -void hal_net_check_update(void) -{ - int ret; - uint32_t timeout; - struct wolfBoot_image img; - - /* handle update for network core */ - ret = hal_net_get_image(&img, &shm->app); - if (ret == 0 && shm->app.version > shm->net.version) { wolfBoot_printf("Found Network Core update: Ver %d->%d, Size %d->%d\n", shm->net.version, shm->app.version, shm->net.size, shm->app.size); @@ -452,8 +410,37 @@ void hal_net_check_update(void) } /* inform network core to boot */ hal_shm_status_set(&shm->app, SHARED_STATUS_DO_BOOT); +#else /* TARGET_nrf5340_net */ + hal_net_get_image(&img, &shm->net); + hal_shm_status_set(&shm->net, SHARED_STATUS_READY); + + /* wait for do_boot or update from app core */ + wolfBoot_printf("Waiting for status from app core...\n"); + ret = hal_shm_status_wait(&shm->app, + (SHARED_STATUS_UPDATE_START | SHARED_STATUS_DO_BOOT), 1000000); + + /* are we updating? */ + if (ret == 0 && shm->app.status == SHARED_STATUS_UPDATE_START) { + wolfBoot_printf("Starting update: Ver %d->%d, Size %d->%d\n", + shm->net.version, shm->app.version, shm->net.size, shm->net.size); + /* Erase network core boot flash */ + hal_flash_erase((uintptr_t)img.hdr, shm->app.size); + /* Write new firmware to internal flash */ + hal_flash_write((uintptr_t)img.hdr, shm->data, shm->app.size); + + /* Reopen image and refresh information */ + hal_net_get_image(&img, &shm->net); + wolfBoot_printf("Network version (after update): 0x%x\n", + shm->net.version); + hal_shm_status_set(&shm->net, SHARED_STATUS_UPDATE_DONE); + + /* continue booting - boot process will validate image hash/signature */ + } +#endif /* TARGET_nrf5340_* */ +exit: + wolfBoot_printf("Status: App %d (ver %d), Net %d (ver %d)\n", + shm->app.status, shm->app.version, shm->net.status, shm->net.version); } -#endif void hal_init(void) { @@ -488,8 +475,6 @@ void hal_prepare_boot(void) //BOOTLOADER_PARTITION_SIZE #ifdef TARGET_nrf5340_app - hal_net_check_update(); - /* Restore defaults preventing network core from accessing shared SDRAM */ SPU_EXTDOMAIN_PERM(0) = (SPU_EXTDOMAIN_PERM_SECATTR_NONSECURE | SPU_EXTDOMAIN_PERM_UNLOCK); diff --git a/hal/spi/spi_drv_nrf5340.h b/hal/spi/spi_drv_nrf5340.h index 686ac59e2..961dfe50c 100644 --- a/hal/spi/spi_drv_nrf5340.h +++ b/hal/spi/spi_drv_nrf5340.h @@ -79,8 +79,8 @@ #define QSPI_IO3_PIN 16 #endif -#ifndef QSPI_CLOCK_MHZ /* default 24MHz (up to 96MHz) */ - #define QSPI_CLOCK_MHZ 24000000UL +#ifndef QSPI_CLOCK_MHZ /* default 48MHz (up to 96MHz) */ + #define QSPI_CLOCK_MHZ 48000000UL #endif /* MX25R6435F */ diff --git a/include/spi_drv.h b/include/spi_drv.h index 4eee57679..332f136a7 100644 --- a/include/spi_drv.h +++ b/include/spi_drv.h @@ -112,9 +112,6 @@ int qspi_transfer(uint8_t fmode, const uint8_t cmd, uint8_t* data, uint32_t dataSz, uint32_t dataMode ); -#if !defined(DEBUG_QSPI) && defined(DEBUG_UART) - #define DEBUG_QSPI 1 -#endif #endif /* QSPI_FLASH || OCTOSPI_FLASH */ #ifndef SPI_CS_FLASH diff --git a/src/libwolfboot.c b/src/libwolfboot.c index 22b7dfcbe..e078b39dc 100644 --- a/src/libwolfboot.c +++ b/src/libwolfboot.c @@ -453,8 +453,12 @@ static void RAMFUNCTION set_trailer_at(uint8_t part, uint32_t at, uint8_t val) if (part == PART_BOOT) { #ifdef EXT_FLASH if (FLAGS_BOOT_EXT()) { + /* use ext_cache and 32-bit writes to avoid any underlying hardware + * issues with 1-byte write */ + ext_cache &= ~0xFF; + ext_cache |= val; ext_flash_check_write(PART_BOOT_ENDFLAGS - (sizeof(uint32_t) + at), - (void *)&val, 1); + (void *)&ext_cache, sizeof(uint32_t)); } else #endif @@ -465,8 +469,12 @@ static void RAMFUNCTION set_trailer_at(uint8_t part, uint32_t at, uint8_t val) else if (part == PART_UPDATE) { #ifdef EXT_FLASH if (FLAGS_UPDATE_EXT()) { + /* use ext_cache and 32-bit writes to avoid any underlying hardware + * issues with 1-byte write */ + ext_cache &= ~0xFF; + ext_cache |= val; ext_flash_check_write(PART_UPDATE_ENDFLAGS - (sizeof(uint32_t) + at), - (void *)&val, 1); + (void *)&ext_cache, sizeof(uint32_t)); } else #endif diff --git a/src/qspi_flash.c b/src/qspi_flash.c index 3e271446c..b30419efa 100644 --- a/src/qspi_flash.c +++ b/src/qspi_flash.c @@ -422,6 +422,11 @@ int spi_flash_write(uint32_t address, const void *data, int len) uint32_t xferSz, page, pages, idx = 0; uintptr_t addr; +#ifdef DEBUG_QSPI + wolfBoot_printf("QSPI Flash Write: Len %d, %p -> 0x%x\n", + len, data, address); +#endif + /* write by page */ pages = ((len + (FLASH_PAGE_SIZE-1)) / FLASH_PAGE_SIZE); for (page = 0; page < pages; page++) { @@ -444,8 +449,9 @@ int spi_flash_write(uint32_t address, const void *data, int len) xferSz, QSPI_DATA_MODE /* Data */ ); #ifdef DEBUG_QSPI - wolfBoot_printf("QSPI Flash Write: Ret %d, Cmd 0x%x, Len %d , 0x%x -> %p\n", - ret, FLASH_WRITE_CMD, xferSz, address, ptr); + wolfBoot_printf("QSPI Flash Sector Write: " + "Ret %d, Cmd 0x%x, Len %d, %p -> 0x%x\n", + ret, FLASH_WRITE_CMD, xferSz, ptr, address); #endif if (ret != 0) break; diff --git a/src/update_flash.c b/src/update_flash.c index 427e2a7f3..c04196eea 100644 --- a/src/update_flash.c +++ b/src/update_flash.c @@ -438,9 +438,11 @@ static int wolfBoot_delta_update(struct wolfBoot_image *boot, wb_flash_erase(boot, sector * WOLFBOOT_SECTOR_SIZE, WOLFBOOT_SECTOR_SIZE); sector++; } +#ifndef DISABLE_BACKUP /* start re-entrant final erase, return code is only for resumption in * wolfBoot_start*/ wolfBoot_swap_and_final_erase(0); +#endif out: #ifdef EXT_FLASH ext_flash_lock(); diff --git a/tools/scripts/nrf5340/build_flash.sh b/tools/scripts/nrf5340/build_flash.sh index 0f0327db5..6fe7d8bac 100755 --- a/tools/scripts/nrf5340/build_flash.sh +++ b/tools/scripts/nrf5340/build_flash.sh @@ -28,11 +28,19 @@ cp factory.bin tools/scripts/nrf5340/factory_app.bin tools/keytools/sign --ecc256 test-app/image.bin wolfboot_signing_private_key.der 2 cp test-app/image_v2_signed.bin tools/scripts/nrf5340/image_v2_signed_app.bin +# Create a bin footer with wolfBoot trailer "BOOT" and "p" (ASCII for 0x70 == IMG_STATE_UPDATING): +echo -n "pBOOT" > tools/scripts/nrf5340/trigger_magic.bin +./tools/bin-assemble/bin-assemble \ + tools/scripts/nrf5340/update_app_v2.bin \ + 0x0 tools/scripts/nrf5340/image_v2_signed_app.bin \ + 0xEDFFB tools/scripts/nrf5340/trigger_magic.bin + + # Convert to HEX format for programmer tool arm-none-eabi-objcopy -I binary -O ihex --change-addresses 0x00000000 tools/scripts/nrf5340/factory_app.bin tools/scripts/nrf5340/factory_app.hex arm-none-eabi-objcopy -I binary -O ihex --change-addresses 0x01000000 tools/scripts/nrf5340/factory_net.bin tools/scripts/nrf5340/factory_net.hex -arm-none-eabi-objcopy -I binary -O ihex --change-addresses 0x10000000 tools/scripts/nrf5340/image_v2_signed_app.bin tools/scripts/nrf5340/image_v2_signed_app.hex +arm-none-eabi-objcopy -I binary -O ihex --change-addresses 0x10000000 tools/scripts/nrf5340/update_app_v2.bin tools/scripts/nrf5340/update_app_v2.hex arm-none-eabi-objcopy -I binary -O ihex --change-addresses 0x10100000 tools/scripts/nrf5340/image_v2_signed_net.bin tools/scripts/nrf5340/image_v2_signed_net.hex @@ -42,7 +50,7 @@ if [ "$1" == "erase" ]; then fi # Program external flash -nrfjprog -f nrf53 --program tools/scripts/nrf5340/image_v2_signed_app.hex --verify +nrfjprog -f nrf53 --program tools/scripts/nrf5340/update_app_v2.hex --verify nrfjprog -f nrf53 --program tools/scripts/nrf5340/image_v2_signed_net.hex --verify