stm32/mboot: Add mboot version string.

Adds a configurable version string to a known location at the end of mboot
flash section.  Also stores the options mboot was built with, eg usb and
which filesystems are supported.

A board can override the defaults, or disable the version string entirely
by setting MBOOT_VERSION_ALLOCATED_BYTES=0.

Signed-off-by: Victor Rajewski <victor@allumeenergy.com.au>
This commit is contained in:
Victor Rajewski
2024-12-04 10:48:29 +11:00
committed by Damien George
parent 931a768f55
commit 61e2931f86
5 changed files with 124 additions and 2 deletions

View File

@@ -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
@@ -78,9 +84,14 @@ 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
LDFLAGS += --defsym mboot_version_len=$(MBOOT_VERSION_ALLOCATED_BYTES)
LIBS += $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
# Remove uncalled code from the final image.
@@ -121,6 +132,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 \
@@ -206,7 +218,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
@@ -231,8 +243,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
@@ -250,6 +263,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)

View File

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

View File

@@ -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 == 0x00 or c == 0xFF: # have hit padding or 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

View File

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

View File

@@ -0,0 +1,62 @@
#include "mboot.h"
#include "genhdr/mpversion.h"
#if defined(MBOOT_VERSION_ALLOCATED_BYTES) && MBOOT_VERSION_ALLOCATED_BYTES > 0
#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