diff --git a/docs/API.md b/docs/API.md index c110b568..ba8c6bcb 100644 --- a/docs/API.md +++ b/docs/API.md @@ -82,6 +82,11 @@ This feature is disabled by default. To enable it, set of flash sectors (default: 2); - `WOLFBOOT_DIAGNOSTICS_EXT`: setting this causes the region to live in external flash. Only meaningful when `EXT_FLASH` is enabled. +- `WOLFBOOT_DIAGNOSTICS_RECORD_SIZE`: the on-flash slot size for each record and + the sector header, in bytes (default: 16). It must be a multiple of, and no + smaller than, the flash write granularity. Raise it on platforms whose flash + write word is wider than 16 bytes (for example 32 for the 256-bit words on + STM32H7). The region is managed as a circular store over its sectors. With two or more sectors, older records are retained until the log wraps all the way around, so diff --git a/include/wolfboot/wolfboot.h b/include/wolfboot/wolfboot.h index 5ce931f0..8f5c3ea2 100644 --- a/include/wolfboot/wolfboot.h +++ b/include/wolfboot/wolfboot.h @@ -630,8 +630,7 @@ int wolfBoot_get_partition_state(uint8_t part, uint8_t *st); #define WOLFBOOT_FAILURE_CAUSE_NOT_CONFIRMED 4 /* image never confirmed via * wolfBoot_success() */ -/* Persisted failure record. Exactly 16 bytes so it maps to a single 128-bit - * write-once flash word and can be appended without read-modify-write. */ +/* Persisted failure record. */ struct wolfBoot_failure_record { uint32_t seq; /* monotonic sequence number (higher = newer) */ uint8_t phase; /* WOLFBOOT_FAILURE_PHASE_* */ diff --git a/options.mk b/options.mk index 8b9b1457..849fc3c6 100644 --- a/options.mk +++ b/options.mk @@ -78,6 +78,9 @@ ifeq ($(WOLFBOOT_PERSIST_FAILURE_STATUS),1) ifneq ($(WOLFBOOT_DIAGNOSTICS_SECTORS),) CFLAGS+=-D"WOLFBOOT_DIAGNOSTICS_SECTORS=$(WOLFBOOT_DIAGNOSTICS_SECTORS)" endif + ifneq ($(WOLFBOOT_DIAGNOSTICS_RECORD_SIZE),) + CFLAGS+=-D"WOLFBOOT_DIAGNOSTICS_RECORD_SIZE=$(WOLFBOOT_DIAGNOSTICS_RECORD_SIZE)" + endif ifeq ($(WOLFBOOT_DIAGNOSTICS_EXT),1) CFLAGS+=-D"WOLFBOOT_DIAGNOSTICS_EXT" endif diff --git a/src/libwolfboot.c b/src/libwolfboot.c index 61a1de5b..95f91128 100644 --- a/src/libwolfboot.c +++ b/src/libwolfboot.c @@ -939,8 +939,12 @@ void RAMFUNCTION wolfBoot_success(void) #define DIAG_SECTOR_SIZE WOLFBOOT_SECTOR_SIZE #define DIAG_SECTOR_ADDR(i) ((haladdr_t)(WOLFBOOT_DIAGNOSTICS_ADDRESS) + \ (haladdr_t)(i) * DIAG_SECTOR_SIZE) -#define DIAG_HDR_SIZE 16U -#define DIAG_RECORD_SIZE 16U + +#ifndef WOLFBOOT_DIAGNOSTICS_RECORD_SIZE +#define WOLFBOOT_DIAGNOSTICS_RECORD_SIZE 16U +#endif +#define DIAG_HDR_SIZE WOLFBOOT_DIAGNOSTICS_RECORD_SIZE +#define DIAG_RECORD_SIZE WOLFBOOT_DIAGNOSTICS_RECORD_SIZE #define DIAG_SLOTS_PER_SECTOR ((DIAG_SECTOR_SIZE - DIAG_HDR_SIZE) / DIAG_RECORD_SIZE) struct wolfBoot_diag_header { @@ -950,11 +954,11 @@ struct wolfBoot_diag_header { uint32_t crc; /* CRC32 over the preceding 12 bytes */ }; -/* Ensure both structures are exactly 128-bit */ typedef char diag_record_size_check[ - (sizeof(struct wolfBoot_failure_record) == DIAG_RECORD_SIZE) ? 1 : -1]; + (sizeof(struct wolfBoot_failure_record) <= DIAG_RECORD_SIZE) ? 1 : -1]; typedef char diag_header_size_check[ - (sizeof(struct wolfBoot_diag_header) == DIAG_HDR_SIZE) ? 1 : -1]; + (sizeof(struct wolfBoot_diag_header) <= DIAG_HDR_SIZE) ? 1 : -1]; +typedef char diag_record_min_check[(DIAG_RECORD_SIZE >= 16U) ? 1 : -1]; static uint32_t RAMFUNCTION diag_crc32(const void *data, uint32_t len) { @@ -1098,12 +1102,15 @@ static int RAMFUNCTION diag_write(haladdr_t addr, const void *buf, uint32_t len) static int RAMFUNCTION diag_write_header(haladdr_t sector_addr, uint32_t generation) { struct wolfBoot_diag_header hdr; + uint8_t slot[DIAG_HDR_SIZE]; XMEMSET(&hdr, 0, sizeof(hdr)); hdr.magic = DIAG_HDR_MAGIC; hdr.generation = generation; hdr.format_version = DIAG_FORMAT_VERSION; hdr.crc = diag_crc32(&hdr, 12); - return diag_write(sector_addr, &hdr, sizeof(hdr)); + XMEMSET(slot, 0xFF, sizeof(slot)); + XMEMCPY(slot, &hdr, sizeof(hdr)); + return diag_write(sector_addr, slot, DIAG_HDR_SIZE); } /* Highest sequence number present across all sectors (0 if none). */ @@ -1128,6 +1135,7 @@ int RAMFUNCTION wolfBoot_record_failure(uint8_t phase, uint8_t cause, uint32_t gen[DIAG_N_SECTORS]; int count[DIAG_N_SECTORS]; struct wolfBoot_failure_record rec; + uint8_t slot[DIAG_RECORD_SIZE]; uint32_t seq, active_gen; int active, active_count, ret; @@ -1169,8 +1177,10 @@ int RAMFUNCTION wolfBoot_record_failure(uint8_t phase, uint8_t cause, rec.fw_version = fw_version; rec.crc = diag_crc32(&rec, 12); + XMEMSET(slot, 0xFF, sizeof(slot)); + XMEMCPY(slot, &rec, sizeof(rec)); ret = diag_write(DIAG_SECTOR_ADDR(active) + DIAG_HDR_SIZE + - (uint32_t)active_count * DIAG_RECORD_SIZE, &rec, sizeof(rec)); + (uint32_t)active_count * DIAG_RECORD_SIZE, slot, DIAG_RECORD_SIZE); diag_lock(); return ret; diff --git a/tools/unit-tests/Makefile b/tools/unit-tests/Makefile index 5fbd4ed3..e61e232b 100644 --- a/tools/unit-tests/Makefile +++ b/tools/unit-tests/Makefile @@ -65,6 +65,7 @@ TESTS:=unit-parser unit-fdt unit-extflash unit-string unit-spi-flash unit-aes128 TESTS+=unit-tpm-check-rot-auth TESTS+=unit-tpm-api-names TESTS+=unit-diagnostics +TESTS+=unit-diagnostics-256 TESTS+=unit-fit-gzip unit-fit-nogzip TESTS+=unit-fit-fpga TESTS+=unit-mpusize @@ -135,6 +136,7 @@ unit-fdt:CFLAGS+=-DWOLFBOOT_FDT unit-nvm:CFLAGS+=-DNVM_FLASH_WRITEONCE -DMOCK_PARTITIONS unit-nvm-flagshome:CFLAGS+=-DNVM_FLASH_WRITEONCE -DMOCK_PARTITIONS -DFLAGS_HOME unit-diagnostics:CFLAGS+=-DMOCK_PARTITIONS +unit-diagnostics-256:CFLAGS+=-DMOCK_PARTITIONS -DWOLFBOOT_DIAGNOSTICS_RECORD_SIZE=32 unit-enc-nvm:CFLAGS+=-DNVM_FLASH_WRITEONCE -DMOCK_PARTITIONS -DEXT_ENCRYPTED \ -DENCRYPT_WITH_CHACHA -DEXT_FLASH -DHAVE_CHACHA unit-enc-nvm:WOLFCRYPT_SRC+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/chacha.c @@ -456,6 +458,9 @@ unit-nvm-flagshome: ../../include/target.h unit-nvm.c unit-diagnostics: ../../include/target.h unit-diagnostics.c gcc -o $@ unit-diagnostics.c $(CFLAGS) $(LDFLAGS) +unit-diagnostics-256: ../../include/target.h unit-diagnostics.c + gcc -o $@ unit-diagnostics.c $(CFLAGS) $(LDFLAGS) + unit-enc-nvm: ../../include/target.h unit-enc-nvm.c gcc -o $@ $(WOLFCRYPT_SRC) unit-enc-nvm.c $(CFLAGS) $(WOLFCRYPT_CFLAGS) $(LDFLAGS)