diff options
| author | Victor Rajewski <victor@allumeenergy.com.au> | 2024-12-04 10:48:29 +1100 |
|---|---|---|
| committer | Damien George <damien@micropython.org> | 2025-01-02 12:59:14 +1100 |
| commit | 61e2931f864129524e0707c7487f804cfe59e84e (patch) | |
| tree | 1a1a438b7395e6c8f7bb26e309d349d5569f39ec | |
| parent | 931a768f5529649c43a65e999ab28f2820002c38 (diff) | |
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>
| -rwxr-xr-x | ports/stm32/mboot/Makefile | 20 | ||||
| -rw-r--r-- | ports/stm32/mboot/README.md | 16 | ||||
| -rw-r--r-- | ports/stm32/mboot/fwupdate.py | 22 | ||||
| -rw-r--r-- | ports/stm32/mboot/stm32_sections.ld | 6 | ||||
| -rw-r--r-- | ports/stm32/mboot/version.c | 62 |
5 files changed, 124 insertions, 2 deletions
diff --git a/ports/stm32/mboot/Makefile b/ports/stm32/mboot/Makefile index 07053b329..87bced1ae 100755 --- a/ports/stm32/mboot/Makefile +++ b/ports/stm32/mboot/Makefile @@ -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) diff --git a/ports/stm32/mboot/README.md b/ports/stm32/mboot/README.md index 221e3a7c3..c294041a5 100644 --- a/ports/stm32/mboot/README.md +++ b/ports/stm32/mboot/README.md @@ -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 ------------------------- diff --git a/ports/stm32/mboot/fwupdate.py b/ports/stm32/mboot/fwupdate.py index 8578ff4fc..b28ba2a78 100644 --- a/ports/stm32/mboot/fwupdate.py +++ b/ports/stm32/mboot/fwupdate.py @@ -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 diff --git a/ports/stm32/mboot/stm32_sections.ld b/ports/stm32/mboot/stm32_sections.ld index 3302c5f97..43511f083 100644 --- a/ports/stm32/mboot/stm32_sections.ld +++ b/ports/stm32/mboot/stm32_sections.ld @@ -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 : { diff --git a/ports/stm32/mboot/version.c b/ports/stm32/mboot/version.c new file mode 100644 index 000000000..b9912f61f --- /dev/null +++ b/ports/stm32/mboot/version.c @@ -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 |
