Skip to content

Commit 5a0db2b

Browse files
committed
Support for MQTT Broker persist on STM32H5 demo
1 parent 57a879b commit 5a0db2b

7 files changed

Lines changed: 925 additions & 4 deletions

File tree

.github/workflows/stm32h563-m33mu.yml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,47 @@ jobs:
319319
sudo kill "$(cat /tmp/m33mu.pid)" 2>/dev/null || true
320320
fi
321321
322+
# Broker persistence (encrypted-at-rest flash KV) lives in wolfMQTT
323+
# PR 538 (broker_features) and is not yet in wolfMQTT master, so the
324+
# stm32h563_m33mu_full job above builds the broker WITHOUT persistence
325+
# (default). This job builds the broker WITH ENABLE_MQTT_BROKER_PERSIST=1
326+
# against the PR 538 head so the feature stays covered until it merges.
327+
# TODO: once wolfMQTT PR 538 merges, add ENABLE_MQTT_BROKER_PERSIST=1 to
328+
# stm32h563_m33mu_full (which clones wolfMQTT master) and drop this job.
329+
stm32h563_m33mu_broker_persist:
330+
runs-on: ubuntu-latest
331+
timeout-minutes: 20
332+
container:
333+
image: ghcr.io/wolfssl/wolfboot-ci-m33mu:v1.2
334+
options: --privileged
335+
336+
steps:
337+
- uses: actions/checkout@v4
338+
339+
- name: Clone wolfSSL + wolfMQTT (PR 538 broker_features)
340+
run: |
341+
set -euo pipefail
342+
cd ..
343+
git clone --depth 1 https://github.com/wolfSSL/wolfssl.git
344+
git clone https://github.com/wolfSSL/wolfmqtt.git
345+
cd wolfmqtt
346+
git fetch --depth 1 origin pull/538/head
347+
git checkout FETCH_HEAD
348+
349+
- name: Build STM32H563 broker with flash persistence
350+
run: |
351+
set -euo pipefail
352+
make -C src/port/stm32h563 \
353+
ENABLE_TLS=1 ENABLE_MQTT_BROKER=1 ENABLE_MQTT_BROKER_PERSIST=1 \
354+
WOLFSSL_SP_NO_ASM=1 \
355+
CC=arm-none-eabi-gcc OBJCOPY=arm-none-eabi-objcopy
356+
# Confirm the persistence backend is compiled in. Write strings to a
357+
# file first: piping into 'grep -q' makes grep close the pipe early,
358+
# so 'strings' takes SIGPIPE (141) which 'set -o pipefail' would turn
359+
# into a spurious job failure.
360+
strings src/port/stm32h563/app.bin > /tmp/app.strings
361+
grep -q "flash persistence enabled" /tmp/app.strings
362+
322363
stm32h563_m33mu_https_tls13:
323364
runs-on: ubuntu-latest
324365
timeout-minutes: 25

src/port/stm32h563/Makefile

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,14 @@ ENABLE_MQTT ?= 0
3030
# MQTT Broker: set ENABLE_MQTT_BROKER=1 to include wolfMQTT broker (requires TLS)
3131
ENABLE_MQTT_BROKER ?= 0
3232

33+
# MQTT Broker persistence: set ENABLE_MQTT_BROKER_PERSIST=1 to persist broker
34+
# state (sessions/subs/retained/offline-queue) to STM32H5 internal flash,
35+
# AES-256-GCM encrypted at rest. OFF by default because it requires the
36+
# wolfMQTT broker persistence layer (mqtt_broker_persist.c +
37+
# MqttBroker_SetPersistHooks) from wolfMQTT PR 538 (broker_features), which is
38+
# not yet in wolfMQTT master. Requires ENABLE_MQTT_BROKER=1.
39+
ENABLE_MQTT_BROKER_PERSIST ?= 0
40+
3341
# TFTP client demo: set ENABLE_TFTP=1 to include the wolfIP TFTP client
3442
# that downloads a firmware image at boot and stages it into the
3543
# wolfBoot update partition. TZEN=0 only.
@@ -310,7 +318,7 @@ SRCS += $(WOLFMQTT_SRCS)
310318

311319
# wolfMQTT objects use relaxed warnings + MQTT/SSL include paths + user_settings.h
312320
$(WOLFMQTT_ROOT)/%.o: $(WOLFMQTT_ROOT)/%.c
313-
$(CC) $(CFLAGS_WOLFSSL) -DENABLE_MQTT -DWOLFSSL_USER_SETTINGS -DWOLFMQTT_USER_SETTINGS $(if $(filter 1,$(ENABLE_MQTT_BROKER)),-DENABLE_MQTT_BROKER) -I$(WOLFMQTT_ROOT) -I$(WOLFSSL_ROOT) -I$(ROOT)/src -c $< -o $@
321+
$(CC) $(CFLAGS_WOLFSSL) -DENABLE_MQTT -DWOLFSSL_USER_SETTINGS -DWOLFMQTT_USER_SETTINGS $(if $(filter 1,$(ENABLE_MQTT_BROKER)),-DENABLE_MQTT_BROKER) $(MQTT_PERSIST_DEFS) -I$(WOLFMQTT_ROOT) -I$(WOLFSSL_ROOT) -I$(ROOT)/src -c $< -o $@
314322

315323
endif # ENABLE_MQTT
316324

@@ -333,13 +341,49 @@ CFLAGS += -DENABLE_MQTT_BROKER
333341
CFLAGS += -DWOLFMQTT_USER_SETTINGS
334342
CFLAGS += -I$(WOLFMQTT_ROOT)
335343

336-
# MQTT broker wrapper
344+
# Opt-in broker persistence. Gated by ENABLE_MQTT_BROKER_PERSIST so the
345+
# default broker build stays compatible with released wolfMQTT (the
346+
# persistence layer is only in wolfMQTT PR 538 / broker_features for now).
347+
# The persistence macros are defined on the command line (not in
348+
# user_settings.h) so they are set before any wolfMQTT/wolfSSL header is
349+
# parsed - the port includes wolfmqtt/mqtt_broker.h before wolfssl/ssl.h
350+
# pulls in user_settings.h, and these also need to precede mqtt_broker.h's
351+
# #ifndef size defaults. MQTT_PERSIST_DEFS is reused by the wolfMQTT object
352+
# pattern rules below.
353+
ifeq ($(ENABLE_MQTT_BROKER_PERSIST),1)
354+
# The flash KV backend writes via the non-secure FLASH register view and a
355+
# fixed flash layout, so it is TZEN=0 only.
356+
ifeq ($(TZEN),1)
357+
$(error ENABLE_MQTT_BROKER_PERSIST=1 requires TZEN=0 (the flash KV backend uses the non-secure FLASH register view))
358+
endif
359+
# NOTE: WOLFMQTT_BROKER_PERSIST_ENCRYPT enables AES-256-GCM at rest, but the
360+
# backend's derive_key hook returns a FIXED DEVELOPMENT KEY (see
361+
# mqtt_broker_persist_flash.c). This is for testing only - replace derive_key
362+
# with a real key source (SE/HSM/device secret) before relying on
363+
# confidentiality.
364+
MQTT_PERSIST_DEFS := -DWOLFMQTT_BROKER_PERSIST -DWOLFMQTT_BROKER_PERSIST_ENCRYPT \
365+
-DBROKER_MAX_PERSIST_SESSIONS=8 -DBROKER_MAX_OFFLINE_MSGS_PER_SUB=8
366+
CFLAGS += $(MQTT_PERSIST_DEFS)
367+
endif
368+
369+
# MQTT broker wrapper (+ STM32H5 internal-flash persistence backend when
370+
# ENABLE_MQTT_BROKER_PERSIST=1).
337371
SRCS += mqtt_broker.c
372+
ifeq ($(ENABLE_MQTT_BROKER_PERSIST),1)
373+
SRCS += mqtt_broker_persist_flash.c
374+
endif
338375

339376
# wolfMQTT broker source files
340377
# Note: mqtt_client.c is needed by broker internals (MqttClient_Init, etc.)
378+
# mqtt_broker_persist.c is the generic persistence codec (encode/decode +
379+
# AES-GCM wrap), built only when persistence is enabled. The POSIX backend
380+
# (mqtt_broker_persist_posix.c) is never built here - it pulls in
381+
# <dirent.h>/<fcntl.h>; we supply a flash backend instead.
341382
WOLFMQTT_BROKER_SRCS := \
342383
$(WOLFMQTT_ROOT)/src/mqtt_broker.c
384+
ifeq ($(ENABLE_MQTT_BROKER_PERSIST),1)
385+
WOLFMQTT_BROKER_SRCS += $(WOLFMQTT_ROOT)/src/mqtt_broker_persist.c
386+
endif
343387

344388
# Only add shared wolfMQTT sources if MQTT client is not already enabled
345389
ifneq ($(ENABLE_MQTT),1)
@@ -355,7 +399,7 @@ SRCS += $(WOLFMQTT_BROKER_SRCS)
355399
# Only define this pattern rule if MQTT client didn't already define it
356400
ifneq ($(ENABLE_MQTT),1)
357401
$(WOLFMQTT_ROOT)/%.o: $(WOLFMQTT_ROOT)/%.c
358-
$(CC) $(CFLAGS_WOLFSSL) -DENABLE_MQTT_BROKER -DWOLFSSL_USER_SETTINGS -DWOLFMQTT_USER_SETTINGS -I$(WOLFMQTT_ROOT) -I$(WOLFSSL_ROOT) -I$(ROOT)/src -c $< -o $@
402+
$(CC) $(CFLAGS_WOLFSSL) -DENABLE_MQTT_BROKER $(MQTT_PERSIST_DEFS) -DWOLFSSL_USER_SETTINGS -DWOLFMQTT_USER_SETTINGS -I$(WOLFMQTT_ROOT) -I$(WOLFSSL_ROOT) -I$(ROOT)/src -c $< -o $@
359403
endif
360404

361405
endif # ENABLE_MQTT_BROKER

src/port/stm32h563/mqtt_broker.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@
2626
#include <string.h>
2727

2828
#include "certs.h"
29+
#ifdef WOLFMQTT_BROKER_PERSIST
30+
#include "mqtt_broker_persist_flash.h"
31+
#endif
2932

3033
/* Configuration defaults */
3134
#define DEFAULT_BROKER_PORT_TLS 8883
@@ -49,6 +52,9 @@ static struct {
4952
MqttBroker broker;
5053
MqttBrokerNet net;
5154
WOLFSSL_CTX *ssl_ctx;
55+
#ifdef WOLFMQTT_BROKER_PERSIST
56+
MqttBrokerPersistHooks persist_hooks;
57+
#endif
5258
broker_state_t state;
5359
mqtt_broker_debug_cb debug_cb;
5460
uint16_t port;
@@ -164,6 +170,19 @@ static int handle_init(void)
164170
/* Configure broker */
165171
ctx.broker.port = ctx.port;
166172

173+
#ifdef WOLFMQTT_BROKER_PERSIST
174+
/* Install the STM32H5 internal-flash persistence backend before
175+
* MqttBroker_Start (restore runs inside Start). On failure the broker
176+
* still runs, just without durable state. */
177+
if (MqttBrokerNet_PersistFlash_Init(&ctx.persist_hooks) == 0) {
178+
(void)MqttBroker_SetPersistHooks(&ctx.broker, &ctx.persist_hooks);
179+
debug_print("MQTT Broker: flash persistence enabled\n");
180+
}
181+
else {
182+
debug_print("MQTT Broker: persist init failed (in-memory only)\n");
183+
}
184+
#endif
185+
167186
/* Set up TLS if enabled */
168187
if (ctx.use_tls) {
169188
ctx.broker.use_tls = 1;

0 commit comments

Comments
 (0)