diff --git a/ports/stm32/mboot/fwupdate.py b/ports/stm32/mboot/fwupdate.py new file mode 100644 index 0000000000..b2690e8cda --- /dev/null +++ b/ports/stm32/mboot/fwupdate.py @@ -0,0 +1,172 @@ +# Update Mboot or MicroPython from a .dfu.gz file on the board's filesystem +# MIT license; Copyright (c) 2019 Damien P. George + +import struct, time +import uzlib, machine, stm + + +FLASH_KEY1 = 0x45670123 +FLASH_KEY2 = 0xcdef89ab + + +def check_mem_contains(addr, buf): + mem8 = stm.mem8 + r = range(len(buf)) + for off in r: + if mem8[addr + off] != buf[off]: + return False + return True + +def check_mem_erased(addr, size): + mem16 = stm.mem16 + r = range(0, size, 2) + for off in r: + if mem16[addr + off] != 0xffff: + return False + return True + +def dfu_read(filename): + f = open(filename, 'rb') + + hdr = f.read(3) + f.seek(0) + if hdr == b'Dfu': + pass + elif hdr == b'\x1f\x8b\x08': + f = uzlib.DecompIO(f, 16 + 15) + else: + print('Invalid firmware', filename) + return None + + elems = [] + + hdr = f.read(11) + sig, ver, size, num_targ = struct.unpack('<5sBIB', hdr) + + file_offset = 11 + + for i in range(num_targ): + hdr = f.read(274) + sig, alt, has_name, name, t_size, num_elem = struct.unpack('<6sBi255sII', hdr) + + file_offset += 274 + file_offset_t = file_offset + for j in range(num_elem): + hdr = f.read(8) + addr, e_size = struct.unpack(' 16 * 1024 and not check_mem_erased(mboot_addr + 16 * 1024, 16 * 1024): + flash_erase_sector(1) + flash_write(mboot_addr, mboot_fw) + flash_lock() + machine.enable_irq(irq) + + print('New Mboot programmed.') + + if check_mem_contains(mboot_addr, mboot_fw): + print('Verification of new Mboot succeeded.') + else: + print('Verification of new Mboot FAILED! Try rerunning.') + + print('Programming finished, can now reset or turn off.') + +def update_mpy(filename, fs_base, fs_len): + # Check firmware is of .dfu.gz type + try: + with open(filename, 'rb') as f: + hdr = uzlib.DecompIO(f, 16 + 15).read(6) + except Exception: + hdr = None + if hdr != b'DfuSe\x01': + print('Firmware must be a .dfu.gz file.') + return + + ELEM_TYPE_END = 1 + ELEM_TYPE_MOUNT = 2 + ELEM_TYPE_FSLOAD = 3 + ELEM_MOUNT_FAT = 1 + mount_point = 1 + mount = struct.pack('