Skip to content

kvm-it 0.3.0: flash the adapter from the app

Choose a tag to compare

@spilloid spilloid released this 05 Oct 00:41
· 68 commits to main since this release
8e314e8

Firmware (0.1.0) and wire protocol (v1) are unchanged. The controller can now flash the adapter itself, on Linux and Windows.
Verification: see the README status table. On a physical board: kvmit flash on Linux (verified write, pairing kept by a
default flash and wiped by --erase-all, refusal while the adapter's USB port is plugged in, recovery from a write killed
halfway). In the Windows 11 VM with the board's COM bridge passed through: the CLI and the GUI wizard, and an MSI built, installed
and uninstalled. Not exercised: the Linux GUI wizard, bare-metal Windows, the signed release pipeline with the new packaging
before this tag. The flasher was adversarially reviewed over rounds 7-13 (docs/dev-process.md; round 13 by Claude Opus 5.5 because the usual reviewer was out of quota, a recorded deviation from STD-001, with a Codex round to follow); the adapter firmware now ships with the app.

Added

  • kvmit flash (in progress for 0.3.0): writes the adapter's firmware through its UART (COM) port with the espflash library.
    It validates the image first, refuses the board's native USB port (which would type into the flashing computer), keeps the
    pairing and settings unless --erase-all is given, and asks for confirmation. Host-tested (image and port rules);
    hardware-verified once on one board over its CH343 UART. Before writing it re-checks that the chosen port is still the same
    device, that no Espressif USB device (which may be an adapter's own USB port: a keyboard and mouse, HID-only so not a serial port,
    or the generic debug unit it shows in download mode) is plugged into the computer, that the chip is an ESP32-S3 with the image's flash size, and that the installed partition table keeps the settings
    where they are; it validates the image (headers, partition table, file paths inside the firmware folder). Hardware
    results: on Linux with a physical board the pairing survives a default flash and is wiped by --erase-all, and the native-USB
    refusal works (also with --any-port); on Windows 11 (VM, the board's COM bridge passed through) the CLI and the GUI wizard
    flash end to end. An interrupted flash (the Windows flasher killed halfway through the app) was recovered by flashing again, no BOOT button. Not exercised: the Linux GUI wizard, bare-metal Windows.
  • Flash adapter… in the GUI's Adapter popup (flashwiz.rs): a window that finds the board's COM port, checks the firmware
    folder, blocks while any Espressif native USB port is plugged into the computer, requires a second tick before erasing the
    pairing, refuses while a script runs or the adapter is connected, flashes on a worker thread with a progress bar (no close button
    and no app exit while writing), and says how to recover if it fails. Its rules are unit-tested; a flash through the window was run end to end in the
    Windows 11 VM. Opening it cancels a pending connection attempt (which would otherwise block it with nothing to press).
  • The adapter firmware ships with the app: firmware/release/ (the exact images, with provenance and checksums) is installed
    beside the program by the MSI, included in the zip and the AppImage, and found by kvmit flash and Flash adapter… with no
    setup (KVMIT_FIRMWARE or --firmware override it). CI checks that the bundled images are not older than the firmware sources;
    verify-release.py checks the zip carries them. Windows executables grew from ~21 MB to ~35 MB with the flasher (espflash).
  • THIRD_PARTY_NOTICES.md (MPL-2.0 notice for serialport) ships in the zip, the MSI and the AppImage; the AppImage builder moved to Rust 1.99.

Changed

  • Build toolchain is Rust 1.99 (was 1.90), needed for the in-app flasher planned for 0.3.0; clippy lints fixed (as_chunks, an
    always-true min in a test, explicit f32 for stroke widths). No behaviour change. The AppImage builder stays on 1.90 for now.

Changed (found cutting the release)

  • The window title now carries the version ("kvm-it 0.3.0"), which also stamps it into kvmit-gui.exe. scripts/verify-release.py checks that stamp, and it had only
    passed for 0.2.1 by coincidence (a dependency's source path in the executable happened to contain "0.2.1"): the GUI never embedded its own version before.

Known limitations

  • Flashing: identical boards behind a USB bridge with no serial number cannot be told apart (the app says so and re-checks chip, flash size and settings layout); a USB device
    the OS will not let the enumerator describe, one plugged in after the check, or an adapter's USB port running other firmware under another vendor id are not detected as
    a reason to refuse. Firmware is not signed; KVMIT_FIRMWARE / --firmware can point at any valid ESP32-S3 image set.
  • BLE lifecycle around the flasher (review round 13, Low): pairing and then immediately connecting elsewhere can leave an idle OS-level link unowned, and a failed first
    connection after a pairing may not close its link; both are dropped when the board is flashed (it resets). Planned for 0.3.1.
  • The Linux GUI wizard, Linux pairing with the new code and bare-metal Windows were not exercised.

Signing and assets

  • Windows: code-signed. SIGNATURES.txt (straight from Get-AuthenticodeSignature) reports Valid for kvmit.exe, kvmit-gui.exe and the MSI, signer
    CN=Joseph Spillers, signed in CI with Azure Artifact Signing (RFC 3161 timestamped). scripts/verify-release.py --require-signed passes on the published assets
    (hashes, zip contents, the bundled firmware byte-identical to firmware/release, its checksums and source hash, PE headers, version stamps).
  • The signed MSI was installed in a Windows 11 VM: it places the firmware next to the app, both executables report a valid signature, and the installed
    kvmit flash wrote the bundled firmware to a real board (verified write, pairing kept).
  • Linux: kvm-it-0.3.0-x86_64.AppImage (+ .sha256), built from the tag, not code-signed; check it against its checksum. Needs BlueZ, OpenGL and the usual
    desktop libraries; glibc 2.35+. It carries the firmware too. Only cli --version and cli flash --list were run from it; the GUI was not started from the AppImage.
  • Nothing here is verified on bare-metal Windows, on the Linux GUI wizard, or on Linux pairing with this release.
  • The first publication attempt of this tag failed its own verifier (the GUI never embedded its version) before anything was attached; the tag was re-cut on the fixed
    commit, which is why the tag is newer than the merge of the flasher work (details in docs/dev-process.md).
  • Review: the flasher went through thirteen adversarial review rounds; round 13 was done by Claude Opus 5.5 instead of the usual reviewer (out of quota), a recorded
    deviation, and a Codex round over the same code is still to be run.