Allow configuration of diagnostics record size on flash

pull/815/head
Mattia Moffa 2026-07-02 14:32:37 +02:00 committed by Daniele Lacamera
parent 69e8e044c9
commit ceaed58782
5 changed files with 31 additions and 9 deletions

View File

@ -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

View File

@ -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_* */

View File

@ -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

View File

@ -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;

View File

@ -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)