Skip to content

Commit

Permalink
ota: detect Tasmota magic numbers when booting (#2370)
Browse files Browse the repository at this point in the history
- inject dummy data sequence that is expected to hold current version info
- check rtcmem markers and purge settings, since we don't want accidentally reading something as a kv
- sometimes we cannot boot b/c of certain SDK params, purge last 16KiB as well

ref. `SetOption78 1`
https://tasmota.github.io/docs/Commands/#setoptions

The original idea from Esphome:
https://github.com/esphome/esphome/blob/0e59243b83913fc724d0229514a84b6ea14717cc/esphome/core/esphal.cpp#L275-L287
Does not seem to be working atm. Will need to re-check with the esphome builder, c/p did not work and I tried building with gcc-10

Specific things we want to do is to have 'version' byte between 2 'marker' bytes:
https://github.com/arendst/Tasmota/blob/217addc2bb2cf46e7633c93e87954b245cb96556/tasmota/settings.ino#L218-L262       https://github.com/arendst/Tasmota/blob/0dfa38df89c8f2a1e582d53d79243881645be0b8/tasmota/i18n.h#L780-L782
  • Loading branch information
mcspr authored Sep 27, 2020
1 parent 1b66460 commit 0586f5d
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 6 deletions.
8 changes: 2 additions & 6 deletions code/espurna/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,15 +153,11 @@ void setup() {
info(true);

wifiSetup();
#if OTA_ARDUINOOTA_SUPPORT
arduinoOtaSetup();
#endif
otaSetup();

#if TELNET_SUPPORT
telnetSetup();
#endif
#if OTA_CLIENT != OTA_CLIENT_NONE
otaClientSetup();
#endif

// -------------------------------------------------------------------------
// Check if system is stable
Expand Down
46 changes: 46 additions & 0 deletions code/espurna/ota.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,12 @@ OTA MODULE COMMON FUNCTIONS
#include "ota.h"
#include "system.h"
#include "terminal.h"
#include "rtcmem.h"
#include "utils.h"
#include "ws.h"

#include <atomic>

void otaPrintError() {
if (Update.hasError()) {
#if TERMINAL_SUPPORT
Expand Down Expand Up @@ -77,3 +81,45 @@ void otaProgress(size_t bytes, size_t each) {
last = bytes;
}
}

void otaSetup() {
// Some magic to allow seamless Tasmota OTA upgrades
// - inject dummy data sequence that is expected to hold current version info
// - purge settings, since we don't want accidentaly reading something as a kv
// - sometimes we cannot boot b/c of certain SDK params, purge last 16KiB
{
// ref. `SetOption78 1`
// - https://tasmota.github.io/docs/Commands/#setoptions (> SetOption78 Version check on Tasmota upgrade)
// - https://github.com/esphome/esphome/blob/0e59243b83913fc724d0229514a84b6ea14717cc/esphome/core/esphal.cpp#L275-L287 (the original idea from esphome)
// - https://github.com/arendst/Tasmota/blob/217addc2bb2cf46e7633c93e87954b245cb96556/tasmota/settings.ino#L218-L262 (specific checks, which succeed when finding 0xffffffff as version)
// - https://github.com/arendst/Tasmota/blob/0dfa38df89c8f2a1e582d53d79243881645be0b8/tasmota/i18n.h#L780-L782 (constants)
std::atomic_thread_fence(std::memory_order_relaxed);
volatile uint32_t magic[3] [[gnu::unused]] {
0x5AA55AA5,
0xFFFFFFFF,
0xA55AA55A
};

// ref. https://github.com/arendst/Tasmota/blob/217addc2bb2cf46e7633c93e87954b245cb96556/tasmota/settings.ino#L24
// We will certainly find these when rebooting from Tasmota. Purge SDK as well, since we may experience WDT after starting up the softAP
auto* rtcmem = reinterpret_cast<volatile uint32_t*>(RTCMEM_ADDR);
if ((0xA55A == rtcmem[64]) && (0xA55A == rtcmem[68])) {
DEBUG_MSG_P(PSTR("[OTA] Detected TASMOTA OTA, resetting the device...\n"));
rtcmem[64] = rtcmem[68] = 0;
customResetReason(CUSTOM_RESET_TERMINAL);
resetSettings();
eraseSDKConfig();
*((int*) 0) = 0;
// noreturn, we simply reboot after writing into 0
}

// TODO: also check for things throughout the flash sector, somehow?
}

#if OTA_ARDUINOOTA_SUPPORT
arduinoOtaSetup();
#endif
#if OTA_CLIENT != OTA_CLIENT_NONE
otaClientSetup();
#endif
}
1 change: 1 addition & 0 deletions code/espurna/ota.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ void otaClientSetup();
#include <WiFiClientSecure.h>
#endif

void otaSetup();
void otaPrintError();
bool otaFinalize(size_t size, int reason, bool evenIfRemaining = false);

Expand Down

0 comments on commit 0586f5d

Please sign in to comment.