Browse Source

ota: detect Tasmota magic numbers when booting (#2370)

- 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:
0e59243b83/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:
217addc2bb/tasmota/settings.ino (L218-L262)       0dfa38df89/tasmota/i18n.h (L780-L782)
mcspr-patch-1
Max Prokhorov 3 years ago
committed by GitHub
parent
commit
0586f5d4cc
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 49 additions and 6 deletions
  1. +2
    -6
      code/espurna/main.cpp
  2. +46
    -0
      code/espurna/ota.cpp
  3. +1
    -0
      code/espurna/ota.h

+ 2
- 6
code/espurna/main.cpp View File

@ -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


+ 46
- 0
code/espurna/ota.cpp View File

@ -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
@ -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
- 0
code/espurna/ota.h View File

@ -38,6 +38,7 @@ void otaClientSetup();
#include <WiFiClientSecure.h>
#endif
void otaSetup();
void otaPrintError();
bool otaFinalize(size_t size, int reason, bool evenIfRemaining = false);


Loading…
Cancel
Save