overdub

m-bootloader

jvitkauskas/m-bootloader · ★ 31

Clean-room open bootloader for the FM-1 and SMK-37 Pro/Elite that adds a download mode and a recovery menu on the keys, plus the flash loader M-Flasher uses.

README from GitHub, MIT

m-bootloader

An open-source (MIT) bootloader for the M-VAVE FM-1 and SMK-37 Pro / Elite synthesizers (JieLi AC791N), plus the small flash loader that M-Flasher runs on the chip to read and write its flash.

It replaces the bootloader M-VAVE ships, adding a way back into USB download mode and a recovery menu, so a unit with broken or unwanted firmware can be reflashed without opening it. M-VAVE's stock firmware, Snoop37 and Baud Girl run with it.

Features

  • Download mode from the keys. Hold REC (FM-1) or SEQ REC (SMK-37) while switching on. The unit appears on USB in the chip's download mode, ready for M-Flasher.
  • MIDI mode. Reinstall firmware from a browser installer over USB MIDI, including from a phone, with no computer and no firmware running. It's in the recovery menu, which also opens by itself when there's no valid firmware (specification §11.6). The unit reads the package twice, to check it and then to write it, so an installer's progress bar fills about twice as fast as the unit's. Wait for the unit. Tested with SLOOP's, Felucca's, Melodee's and ChoralRoot's installers, from Linux, macOS, Android and iOS (the MIDIWeb app), and on the SMK-37 Pro with ChoralRoot's and Felucca's SMK-37 installers from Linux. Baud Girl's installer refuses it, and needs M-VAVE's firmware on the unit. Keep the installer's tab in front, as browsers slow background tabs down. If you stop an install with the menu key or a restart, choose MIDI mode again before an installer's resume button can find the unit. On an SMK-37 Elite, which hasn't been tested, an install this way leaves it reporting itself as a Pro.
  • Recovery menu. Hold PLAY (FM-1) or SEQ PLAY (SMK-37) while switching on. The menu also opens by itself when the firmware cannot start. It shows the firmware's state and size, pending updates and the flash chip, and offers:
    • Boot app and Download mode;
    • Boot anyway: start firmware that fails its checksum, once;
    • Wipe user data: erase the settings areas the firmware declares, and nothing else. The menu lists the exact ranges, and you hold the key for 3 s to confirm.
  • SD card (FM-1). With an m-card board and a FAT32 card fitted, the menu gets an SD card item at the top. It loads and runs /MBOOT/MENU.BIN from the card, which can be any program built for it (docs/SPEC.md §11.5). The card is only touched when the menu is open. This is new and not yet tested on real hardware.
  • Checked start. Every firmware file's checksum is verified before the firmware starts.
  • Firmware updates. M-VAVE's own updater and other firmwares' updaters run as they do with the stock bootloader.
  • Calibration guard (SMK-37). Keeps a copy of the factory calibration and puts it back if it is erased.
  • Flash loader for M-Flasher. Fast reads (about 860 KB/s), an on-chip CRC32 check, checked writes, the flash chip's unique ID, and progress on the unit's own screen.

Status

SMK-37 Protested on hardware: start-up (about 1 s), both keys, every menu action, the calibration guard, an official M-VAVE update, Snoop37 and Baud Girl, all loader operations, installation with M-UPGRADE
SMK-37 Elitesame build as the Pro, with the same flash layout; installation with M-UPGRADE tested with the Elite firmware on an SMK-37
FM-1tested on hardware: start-up, both keys, every menu action, an official M-VAVE update, SLOOP, all loader operations, installation with M-UPGRADE

This release, 2.0-c43a32f, on an FM-1 and an SMK-37 Pro: installing over 1.3 with M-Flasher and over 1.2 with M-UPGRADE, an official 016 update, Baud Girl, a browser installer from running firmware, and MIDI mode. On the FM-1 also installing with M-UPGRADE from the stock bootloader, and M-Flasher on macOS and Windows. VDDIO has not been measured.

Official M-VAVE updates and Baud Girl's installer put the stock bootloader back, with its full configuration. Reinstall m-bootloader afterwards, with M-Flasher or M-UPGRADE.

Do not install 1.3 or older over this version. They need the configuration it removes, and stop at their menu with BAD CONFIG on every start; Boot app still starts the firmware. Melodee's installer offers 1.2 as an option, so leave that unticked. Reinstalling this version with M-Flasher fixes it.

FAILED -5 from Felucca-family firmware. Melodee's Return to official V15, and M-UPGRADE on an SMK-37 running such firmware, refuse because the boot area differs from the package's. The boot area and firmware stay as they were. Use M-Flasher instead.

Going from FM-1 016 back to 015 leaves garbage presets and wrong pitch, with any bootloader: 016 overwrites the presets once it runs, and official updates do not restore them. Only a backup with the original area does.

Baud Girl overwrites the SMK-37's stock presets. Stock firmware installed afterwards has none, with any bootloader, until a backup with the original area is restored. Back up before installing it.

Little tested on the FM-1's newer flash chip. FM-1s sold from late 2026 have a UCUN UC25HQ80 flash (JEDEC ID 0xB36014) instead of the Puya P25Q80H (0x856014). One such unit did not start after version 1.1 or 1.2 was installed, and the cause is not known. Another runs 1.3 and this version, on one owner's report, with its firmware, menu and download mode working. A MIDI mode reinstall of the same firmware worked there too, which rewrites only the first 4 KiB sector (M-Flasher #13). Check FLASH CHIP in M-Flasher before installing. With 0xB36014, whether through M-Flasher or M-UPGRADE, install it at your own risk.

Install

Back up your unit with M-Flasher first. Then install the build for your board, smk37-uboot.boot or fm1-uboot.boot from the releases:

m-flasher bootloader --file smk37-uboot.boot

M-Flasher writes only the boot area. It keeps the chip-key record that firmware installers need and drops the rest of the configuration, which the bootloader does not use, for more room (specification §5.3). If the bootloader is ever broken, the USB_KEY dongle still forces the chip into download mode (specification §4.3).

A unit running M-VAVE's firmware enters download mode on a MIDI message, whichever bootloader it has, so a stock unit can be backed up first: the SysEx F0 22 24 35 7D F7 on its first MIDI port (specification §4.2). On Linux, find the port with amidi -l, then amidi -p hw:N,0,0 -S 'F0 22 24 35 7D F7'. M-Flasher sends it with its DOWNLOAD MODE button, from 0.5.0.

With M-VAVE's updater

fm1-uboot.fwsc, smk37-pro-uboot.fwsc and smk37-elite-uboot.fwsc install it with M-VAVE's M-UPGRADE, over USB MIDI, without download mode. The unit has to run firmware that M-UPGRADE can update, such as M-VAVE's, and keeps it.

A package holds no firmware, only our installer (src/installer.c): the unit's firmware stores it and the bootloader starts it. It writes only the bootloader and its boot-area record, shows its progress on the screen, and restarts the unit. M-UPGRADE then waits for an updater that never comes, and times out with an error; the installation is done by then. Tested from M-VAVE's bootloader on an FM-1 (firmware 015) and on an SMK-37 with the Pro and the Elite firmware (016). This version was tested on an FM-1 with firmware 015 and an SMK-37 Pro with firmware 016, and leaves the same boot area as M-Flasher.

The packages are labelled version 099, as M-UPGRADE refuses the version a unit already has. If it refuses a unit running other firmware, its force upgrade skips the model and version checks.

Build

You need Python 3, GNU Make, Rust and a C compiler, and the pi32v2 LLVM toolchain release pi32v2-23.1.5-2. Nothing from JieLi is needed. On Linux x86-64:

curl -fLo toolchain.tar.xz https://github.com/jvitkauskas/pi32v2-llvm/releases/download/pi32v2-23.1.5-2/pi32v2-llvm-23.1.5-2-linux-x64.tar.xz
echo 'cb896562418a2be93edb9bac26af4bc81a106a32974002a78e6b9fc203c93990  toolchain.tar.xz' | sha256sum -c
mkdir toolchain && tar -xJf toolchain.tar.xz -C toolchain --strip-components=1
cargo install --locked --git https://github.com/exoticorn/upkr --rev a9e56d9d50d1f64cab7590f2c584a12b173e7715 upkr
make

Upkr is the packer that stores stage 1. make UPKR=<path> uses one installed elsewhere. The release also has packages for Linux arm64 and macOS, with their checksums in SHA256SUMS. make TOOLCHAIN=<directory> uses a toolchain unpacked elsewhere.

OutputWhat
build/fm1/uboot.bootbootloader for the FM-1
build/smk37/uboot.bootbootloader for the SMK-37 Pro / Elite
build/fm1/uboot.fwsc, build/smk37/uboot-pro.fwsc, uboot-elite.fwscthe same bootloaders as M-UPGRADE packages; the Elite's differs from the Pro's only in the model name M-UPGRADE checks
build/loader/mflr-loader-a.bin, -b.binflash loader, at RAM 0x01C20000 and 0x01C28000

Builds are reproducible: the same commit and toolchain release give the same bytes. The version shown by the menu and by M-Flasher is VERSION plus the git commit, for example 1.1-e9a25e1. The build fails if an image outgrows its slot.

make test runs the tests: the formats, the loader protocol, and the start-up and menu of both boards on a simulated chip and flash. make sanitize runs them under ASan and UBSan, and make reproducible checks that two builds match. Some tests also use flash images of real units and M-VAVE's packages in testdata/. Those contain M-VAVE's firmware, so they are not in the repository, and the tests skip them when absent.

Source

PathWhat
src/startup.S, src/stage0.cstage 0: entry, power and clock, holding the key for download mode (specification §4.4)
src/boot.cstage 1: start-up decisions, menu
src/midi_update.c, src/usb_midi.cMIDI mode: the update protocol, and the USB-MIDI device
src/core.cflash formats, checksums, ciphers, updater decoding, wipe and calibration rules (portable C, also built for the tests)
src/contract.cwhat the firmware and updaters are handed at start
src/platform.c, src/board.c, src/display.cclock, SPI flash, keys, LEDs, screen
src/loader.c, src/loader_target.cthe flash loader
src/sdboot.cfinding a card, and loading and running /MBOOT/MENU.BIN from it
src/installer.c, src/installer_start.Sthe installer in the .fwsc packages
tools/container and M-UPGRADE package packing, build checks
docs/SPEC.mdthe specification it was written from: hardware, formats and protocols

Clean room

m-bootloader was written from scratch, from a specification of the chip, the flash formats and the protocols (docs/SPEC.md). No code from JieLi's SDK or from the earlier open bootloader went into it. The people who studied the original wrote only the specification, and separate sessions that never saw the original wrote the code.

MIT licence: see LICENSE.