Files
BlackMarkandClaude Opus 5.5 44db419c4b chore: the editor config describes this repository, in ASCII
.clangd said the repository rides as a submodule in its consumers, which none
does, and removed three codegen flags only pureboot's loaders carry; its em
dashes are ASCII now. The settings.json comment built on the same premise goes,
and the oracle README states the variant rather than who chose it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 21:41:55 +02:00
..

Oracle — the hand-written TinySafeBoot assembly

tsb-fixedbaud.asm is the reference implementation this port is measured against: the native-UART, fixed-baud TinySafeBoot bootloader, hand-written in AVR assembly. It is the size-and-feature bar for the port's tsb_asm tier.

  • Source: https://github.com/seedrobotics/tinysafeboot (firmware_ASM/latest_stable_release/20200727-fixedbaud/main.asm), the Seed Robotics fixed-baud fork of Julien Thomas' TinySafeBoot.
  • License: GPLv3 (see the header in the file). It is vendored here only as a reference oracle — it is not compiled, linked, or distributed as part of the MIT-licensed port. Mere aggregation.

Why this variant

The fixed-baud, hardware-UART variant is the one whose feature set the port must match. It fits the complete TSB feature set into the 512-byte ATmega boot section:

Feature Oracle routine
Watchdog-reset bail straight to the app RESET (WDRF check)
One-wire half-duplex (RX/TX shorted): RXEN/TXEN toggled per direction, TX turnaround guard SetRX / SetTX / TransmitByte
Activation timeout read from the config page, with a lockout-proof minimum WRX1To (uses utimeoutH)
3×@ activation knock ActCharRcvd
Password gate; wrong byte hangs (still draining the UART) CheckPassword
Emergency erase on password \0 + double-confirm — wipes flash, EEPROM and the config page EmergencyErase
Device-info block (16 bytes) SendDeviceInfo / DEVICEINFO
App-flash read/write (f/F), EEPROM read/write (e/E), config read/write (c/C) CheckCommands

Assembled size (the bar)

Assembled for the ATmega328P with avra:

avra -I /usr/share/avra tsb-fixedbaud.asm   # after uncommenting .include "m328Pdef.inc"
#   Code : 250 words (500 bytes)  — the whole loader, all features, in the 512 B section

500 bytes with every feature — the proof that ≤512 B and full feature parity are simultaneously reachable. The port's four tiers reach it from the other side, and the gradient between them is the cost of the mechanisms each is allowed:

tier bytes section what it is allowed
oracle 500 512 B hand-written assembly, the reference
tsb_asm 512 512 B C++ on libavr, two routines in asm
tsb_tricks 528 1 KB no asm; global register variables
tsb_policy 630 1 KB pureboot's rules: no asm, no register variables
tsb_pure 776 1 KB idiomatic libavr throughout

The two routines tsb_asm keeps are the ones whose remaining cost is the calling convention itself: the bounded rx and the page-store loop. It fills its section exactly, with the same one-bit-time turn-around guard the oracle spends six bytes on - every tier implements the whole feature set, which is what makes the column a gradient rather than four different loaders.

The oracle targets 20 MHz / 33333 baud; the port targets 16 MHz / 115200 baud (what the simavr protocol test drives). Baud and geometry differ, code size and feature set do not.