Skip to content

Commit

Permalink
stm32/mboot: Add mboot version string.
Browse files Browse the repository at this point in the history
Adds a configurable version string to a known location at the end of
mboot flash section. Also stores options mboot was built with.

Signed-off-by: Victor Rajewski <victor@allumeenergy.com.au>
  • Loading branch information
victorallume committed Dec 9, 2024
1 parent 406bccc commit 7309e7b
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 3 deletions.
21 changes: 18 additions & 3 deletions ports/stm32/mboot/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ include $(BOARD_DIR)/mpconfigboard.mk
# A board can set MBOOT_TEXT0_ADDR to a custom location where mboot should reside.
MBOOT_TEXT0_ADDR ?= 0x08000000

# The string in MBOOT_VERSION (default defined in version.c if not defined by a
# board) will be stored in the final MBOOT_VERSION_ALLOCATED_BYTES bytes of mboot flash.
# A board can change the size of this region by defining MBOOT_VERSION_ALLOCATED_BYTES.
MBOOT_VERSION_ALLOCATED_BYTES ?= 64
MBOOT_VERSION_INCLUDE_OPTIONS ?= 1 # if set to 1, this will append build options to version string (see version.c)

USBDEV_DIR=usbdev
DFU=$(TOP)/tools/dfu.py
PYDFU ?= $(TOP)/tools/pydfu.py
Expand Down Expand Up @@ -78,6 +84,10 @@ CFLAGS += -DBUILDING_MBOOT=$(BUILDING_MBOOT)
CFLAGS += -DMICROPY_HW_STM32WB_FLASH_SYNCRONISATION=0
CFLAGS += -DUSBD_ENABLE_VENDOR_DEVICE_REQUESTS=1
CFLAGS += -DBOOTLOADER_DFU_USB_VID=$(BOOTLOADER_DFU_USB_VID) -DBOOTLOADER_DFU_USB_PID=$(BOOTLOADER_DFU_USB_PID)
ifdef MBOOT_VERSION
CFLAGS += -DMBOOT_VERSION=\"$(MBOOT_VERSION)\"
endif
CFLAGS += -DMBOOT_VERSION_ALLOCATED_BYTES=$(MBOOT_VERSION_ALLOCATED_BYTES) -DMBOOT_VERSION_INCLUDE_OPTIONS=$(MBOOT_VERSION_INCLUDE_OPTIONS)

MBOOT_LD_FILES ?= stm32_memory.ld stm32_sections.ld
LDFLAGS += -nostdlib -L . $(addprefix -T,$(MBOOT_LD_FILES)) -Map=$(@:.elf=.map) --cref
Expand Down Expand Up @@ -121,6 +131,7 @@ SRC_C += \
vfs_fat.c \
vfs_lfs.c \
vfs_raw.c \
version.c \
drivers/bus/softspi.c \
drivers/bus/softqspi.c \
drivers/memory/spiflash.c \
Expand Down Expand Up @@ -206,7 +217,7 @@ deploy-stlink: $(BUILD)/firmware.dfu

$(BUILD)/firmware.dfu: $(BUILD)/firmware.elf
$(ECHO) "Create $@"
$(Q)$(OBJCOPY) -O binary -j .isr_vector -j .text -j .data $^ $(BUILD)/firmware.bin
$(Q)$(OBJCOPY) -O binary -j .isr_vector -j .text -j .data -j .mboot_version_text $^ $(BUILD)/firmware.bin
$(Q)$(PYTHON) $(DFU) -b $(MBOOT_TEXT0_ADDR):$(BUILD)/firmware.bin $@

$(BUILD)/firmware.hex: $(BUILD)/firmware.elf
Expand All @@ -215,7 +226,7 @@ $(BUILD)/firmware.hex: $(BUILD)/firmware.elf

$(BUILD)/firmware.elf: $(OBJ)
$(ECHO) "LINK $@"
$(Q)$(LD) $(LDFLAGS) -o $@ $^ $(LIBS)
$(Q)$(LD) $(LDFLAGS) --defsym mboot_version_len=$(MBOOT_VERSION_ALLOCATED_BYTES) -o $@ $^ $(LIBS)
$(Q)$(SIZE) $@

#########################################
Expand All @@ -231,8 +242,9 @@ GEN_PINS_SRC = $(BUILD)/pins_$(BOARD).c
GEN_PINS_HDR = $(HEADER_BUILD)/pins.h
GEN_PINS_AF_CONST = $(HEADER_BUILD)/pins_af_const.h
GEN_PINS_AF_DEFS = $(HEADER_BUILD)/pins_af_defs.h
GEN_MPVERSION = $(HEADER_BUILD)/mpversion.h

$(OBJ): $(GEN_QSTRDEFS_GENERATED) $(GEN_ROOT_POINTERS) $(GEN_PINS_AF_DEFS)
$(OBJ): $(GEN_QSTRDEFS_GENERATED) $(GEN_ROOT_POINTERS) $(GEN_PINS_AF_DEFS) $(GEN_MPVERSION)

$(HEADER_BUILD):
$(MKDIR) -p $(BUILD)/genhdr
Expand All @@ -250,6 +262,9 @@ $(GEN_PINS_AF_DEFS): $(BOARD_PINS) $(MAKE_PINS) ../$(AF_FILE) $(PREFIX_FILE) | $
--output-af-const $(GEN_PINS_AF_CONST) --output-af-defs $(GEN_PINS_AF_DEFS) \
--mboot-mode

$(GEN_MPVERSION): | $(HEADER_BUILD)
$(PYTHON) ../../../py/makeversionhdr.py $@

#########################################

vpath %.S . $(TOP)
Expand Down
16 changes: 16 additions & 0 deletions ports/stm32/mboot/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,17 @@ How to use
the beginning of the chunk when the end is reached. Then use a split
raw filesystem to inform mboot of this wrapping.

The version and config options that mboot was built with are stored in a
small, fixed section of bytes at the end of the flash region allocated
for mboot. The length of the fixed section defaults to 64 bytes, but can
be overridden by setting MBOOT_VERSION_ALLOCATED_BYTES. If running
low on flash for the mboot build, this can be reduced or even set to 0.
The version string stored defaults to the micropython git version as
generated by makeversionhdr.py. The default version string can be
overridden by setting MBOOT_VERSION in a board's build files. The version
string is appended with options mboot was built with - see version.c for
details. This can be prevented by setting MBOOT_VERSION_INCLUDE_OPTIONS to 0.

2. Build the board's main application firmware as usual.

3. Build mboot via:
Expand Down Expand Up @@ -209,6 +220,11 @@ and signed firmware, and can be deployed via USB DFU, or by copying it to the de
internal filesystem (if `MBOOT_FSLOAD` is enabled). `firmware.dfu` is still unencrypted
and can be directly flashed with jtag etc.

Retrieving the mboot version in micropython
-------------------------------------------
The function `get_mboot_version` in `fwupdate.py` returns the version mboot was built with,
optionally with build options.

Example: Mboot on PYBv1.x
-------------------------

Expand Down
22 changes: 22 additions & 0 deletions ports/stm32/mboot/fwupdate.py
Original file line number Diff line number Diff line change
Expand Up @@ -281,3 +281,25 @@ def update_mpy(*args, **kwargs):
elems = update_app_elements(*args, **kwargs)
if elems:
machine.bootloader(elems)


def get_mboot_version(
mboot_base=0x0800_0000, # address of start of mboot flash section
mboot_len=0x8000, # length of mboot flash section
mboot_ver_len=64, # length of mboot version section (defined in mboot/Makefile or in board dir)
valid_prefix="mboot-", # prefix that the version string was defined with
include_opts=True, # return the options mboot was built with (set False for just the version)
):
s = ""
for i in range(mboot_ver_len):
c = stm.mem8[mboot_base + mboot_len - mboot_ver_len + i]
if c == 0xFF: # have hit empty flash
break
s += chr(c)
if s.startswith(valid_prefix):
if include_opts:
return s
else:
return s.split("+")[0] # optional mboot config info stored after "+"
else: # version hasn't been set, so on the original mboot (i.e. mboot-v1.0.0)
return None
6 changes: 6 additions & 0 deletions ports/stm32/mboot/stm32_sections.ld
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ SECTIONS
_edata = .;
} >RAM AT> FLASH_BL

/* Final section of mboot flash reserved for mboot version */
.mboot_version_text (ORIGIN(FLASH_BL) + LENGTH(FLASH_BL) - mboot_version_len) :
{
KEEP(*(.mboot_version)) ;
} >FLASH_BL

/* Zeroed-out data section */
.bss :
{
Expand Down
62 changes: 62 additions & 0 deletions ports/stm32/mboot/version.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#include "mboot.h"
#include "genhdr/mpversion.h"

#ifdef MBOOT_VERSION_ALLOCATED_BYTES

#ifndef MBOOT_VERSION
#define MBOOT_VERSION "mboot-" MICROPY_GIT_TAG
#endif

#if MBOOT_VERSION_INCLUDE_OPTIONS // if this is defined, append a list of build options e.g. fat.lfs2
#define MBOOT_VERSION_USB MBOOT_VERSION "+usb" // USB is always included

#if defined(MBOOT_I2C_SCL)
#define MBOOT_VERSION_I2C MBOOT_VERSION_USB ".i2c"
#else
#define MBOOT_VERSION_I2C MBOOT_VERSION_USB
#endif

#if MBOOT_ADDRESS_SPACE_64BIT
#define MBOOT_VERSION_64BIT MBOOT_VERSION_I2C ".64"
#else
#define MBOOT_VERSION_64BIT MBOOT_VERSION_I2C
#endif

#if MBOOT_VFS_FAT
#define MBOOT_VERSION_FAT MBOOT_VERSION_64BIT ".fat"
#else
#define MBOOT_VERSION_FAT MBOOT_VERSION_64BIT
#endif

#if MBOOT_VFS_LFS1
#define MBOOT_VERSION_LFS1 MBOOT_VERSION_FAT ".lfs1"
#else
#define MBOOT_VERSION_LFS1 MBOOT_VERSION_FAT
#endif

#if MBOOT_VFS_LFS2
#define MBOOT_VERSION_LFS2 MBOOT_VERSION_LFS1 ".lfs2"
#else
#define MBOOT_VERSION_LFS2 MBOOT_VERSION_LFS1
#endif

#if MBOOT_VFS_RAW
#define MBOOT_VERSION_RAW MBOOT_VERSION_LFS2 ".raw"
#else
#define MBOOT_VERSION_RAW MBOOT_VERSION_LFS2
#endif

#define MBOOT_VERSION_FINAL MBOOT_VERSION_RAW

#else // MBOOT_VERSION_INCLUDE_OPTIONS

#define MBOOT_VERSION_FINAL MBOOT_VERSION

#endif // MBOOT_VERSION_INCLUDE_OPTIONS

// Ensure we don't overrun the allocated space
_Static_assert(sizeof(MBOOT_VERSION_FINAL) <= MBOOT_VERSION_ALLOCATED_BYTES + 1, "mboot version string is too long");
// Cuts off the null terminator
const char mboot_version[sizeof(MBOOT_VERSION_FINAL) - 1] __attribute__((section(".mboot_version"))) __attribute__ ((__used__)) = MBOOT_VERSION_FINAL;

#endif // MBOOT_VERSION

0 comments on commit 7309e7b

Please sign in to comment.