diff --git a/src/bootloader.hpp b/src/bootloader.hpp index 04a0c1b..5e7af25 100644 --- a/src/bootloader.hpp +++ b/src/bootloader.hpp @@ -4,24 +4,12 @@ #include "board.hpp" -// Reaching the resident bootloader from the console. -// -// The legacy firmware did this with a watchdog reset: `bootloader` armed the -// watchdog and hung, and the next boot noticed WDRF and jumped to the boot -// section. That works for TinySafeBoot and **does not work for pureboot**, which -// deliberately hands straight back to the application on WDRF - an unattended -// board that watchdog-resets in a loop must not sit in a loader instead of -// running. So a reset-based route into pureboot opens no window at all, and on a -// board whose only way in is the firmware that is a lockout. -// -// This route therefore never resets. It jumps, with the reset flags already -// clear, so the loader starts as if from a clean power-on and opens its window. -// -// The address is this board's, and it is not the legacy one: the loader lives in -// the top 512 bytes at 0x7e00 (`hfuse d4` puts the boot section at 0x7c00 with -// pureboot's staging slot below its own slot). The legacy firmware probed 0x7800 -// - a 2 KB boot section's base - which on this board reads erased, so its check -// was always false and its `bootloader` command never actually arrived anywhere. +// Reaching the resident bootloader from the console. pureboot hands straight +// back to the application on WDRF - an unattended board that watchdog-resets in +// a loop must not sit in a loader instead of running - so a reset-based route +// opens no window at all, and on a board whose only way in is the firmware that +// is a lockout. This route jumps instead, with the reset flags already clear, +// so the loader starts as if from a clean power-on and opens its window. namespace app { class bootloader { @@ -29,17 +17,10 @@ class bootloader { using guard = dev::watchdog<{.timeout = 16_ms}>; - // The top 512 bytes. An erased slot reads 0xffff, which is not an - // instruction any loader begins with - so this asks "is a loader installed" - // rather than "is it the one I expect", which is the check the legacy - // firmware got wrong in the other direction by testing one specific byte. + // The top 512 bytes: `hfuse d4` puts the boot section at 0x7c00, with + // pureboot's staging slot below its own slot. static constexpr std::uint16_t base = 0x7e00; - static bool present() - { - return avr::flash_load(reinterpret_cast(base)) != 0xffff; - } - // A function pointer holds a word address on AVR, so the byte address // halves. [[gnu::noipa]] keeps the call indirect: a constant target folds // into a relative call that cannot reach across flash. @@ -73,20 +54,12 @@ class bootloader { // Release the USART. While TXEN0 is set the peripheral owns PD1, not the // port register, so a loader that bit-bangs the same pin receives - // perfectly and answers into nothing - mute, not deaf, and unverifiable - // from the host. pureboot clears this itself; TinySafeBoot, which is what - // this board still carries, does not. Four bytes make the hand-over work - // for either one, which is the only reason this route can be tested - // before the loader is replaced. + // perfectly and answers into nothing. pureboot releases it itself; this + // keeps the hand-over correct for a loader that does not. avr::hw::ucsr0b::write(0); call(reinterpret_cast(base / 2)); } - - static bool available() - { - return present(); - } }; } // namespace app