mirror of
https://github.com/torlando-tech/pyxis.git
synced 2026-08-06 18:59:52 +00:00
fix: confirm successful OTA boot before restart
This commit is contained in:
@@ -1312,6 +1312,13 @@ void SettingsScreen::set_lxmf_address(const Bytes& hash) {
|
||||
_lxmf_address = hash;
|
||||
}
|
||||
|
||||
void SettingsScreen::set_firmware_version(const String& version) {
|
||||
if (_label_firmware) {
|
||||
String text = "Firmware: " + version;
|
||||
lv_label_set_text(_label_firmware, text.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsScreen::set_gps(TinyGPSPlus* gps) {
|
||||
_gps = gps;
|
||||
}
|
||||
|
||||
@@ -176,6 +176,9 @@ public:
|
||||
*/
|
||||
void set_lxmf_address(const RNS::Bytes& hash);
|
||||
|
||||
/** Set the exact running firmware build for post-reboot verification. */
|
||||
void set_firmware_version(const String& version);
|
||||
|
||||
/**
|
||||
* Set GPS pointer for status display
|
||||
*/
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <esp_system.h>
|
||||
#include <esp_heap_caps.h>
|
||||
#include <esp_task_wdt.h>
|
||||
#include <esp_ota_ops.h>
|
||||
#include <new> // placement new
|
||||
#include <soc/rtc_cntl_reg.h>
|
||||
|
||||
@@ -956,6 +957,30 @@ void setup_hardware() {
|
||||
INFO("Power enabled (early init)");
|
||||
}
|
||||
|
||||
void confirm_running_firmware() {
|
||||
const esp_partition_t* running = esp_ota_get_running_partition();
|
||||
if (!running) {
|
||||
ERROR("Unable to identify running OTA partition");
|
||||
return;
|
||||
}
|
||||
|
||||
esp_ota_img_states_t state = ESP_OTA_IMG_UNDEFINED;
|
||||
esp_err_t state_result = esp_ota_get_state_partition(running, &state);
|
||||
INFOF("Running firmware: version=%s partition=%s subtype=%d address=0x%lx state=%d",
|
||||
FIRMWARE_VERSION, running->label, static_cast<int>(running->subtype),
|
||||
static_cast<unsigned long>(running->address), static_cast<int>(state));
|
||||
|
||||
if (state_result == ESP_OK &&
|
||||
(state == ESP_OTA_IMG_NEW || state == ESP_OTA_IMG_PENDING_VERIFY)) {
|
||||
esp_err_t result = esp_ota_mark_app_valid_cancel_rollback();
|
||||
if (result == ESP_OK) {
|
||||
INFO("Running firmware marked valid; OTA rollback cancelled");
|
||||
} else {
|
||||
ERRORF("Failed to mark running firmware valid: %s", esp_err_to_name(result));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setup_lvgl_and_ui() {
|
||||
INFO("\n=== LVGL & UI Initialization ===");
|
||||
|
||||
@@ -1275,6 +1300,7 @@ void setup_ui_manager() {
|
||||
// Configure settings screen
|
||||
UI::LXMF::SettingsScreen* settings = ui_manager->get_settings_screen();
|
||||
if (settings) {
|
||||
settings->set_firmware_version(FIRMWARE_VERSION);
|
||||
// Pass GPS for status display
|
||||
settings->set_gps(&gps);
|
||||
|
||||
@@ -1789,6 +1815,11 @@ void setup() {
|
||||
Serial.flush();
|
||||
});
|
||||
|
||||
// Columba writes app0 plus fresh OTA-selection data. This framework has
|
||||
// bootloader rollback enabled, so confirm the app only after filesystem,
|
||||
// LXMF, and UI initialization have all completed successfully.
|
||||
confirm_running_firmware();
|
||||
|
||||
// Boot profiling complete
|
||||
BOOT_PROFILE_COMPLETE();
|
||||
#ifdef BOOT_PROFILING_ENABLED
|
||||
|
||||
@@ -7,6 +7,7 @@ REPO_ROOT = Path(__file__).resolve().parents[2]
|
||||
UI_MANAGER = REPO_ROOT / "lib/tdeck_ui/UI/LXMF/UIManager.cpp"
|
||||
CHAT_SCREEN = REPO_ROOT / "lib/tdeck_ui/UI/LXMF/ChatScreen.cpp"
|
||||
COMPOSE_SCREEN = REPO_ROOT / "lib/tdeck_ui/UI/LXMF/ComposeScreen.cpp"
|
||||
MAIN = REPO_ROOT / "src/main.cpp"
|
||||
|
||||
|
||||
def function_body(source: str, signature: str, next_signature: str) -> str:
|
||||
@@ -84,3 +85,17 @@ def test_storage_error_dialogs_are_coalesced():
|
||||
source = UI_MANAGER.read_text()
|
||||
assert "if (storage_error_dialog) return;" in source
|
||||
assert "storage_error_dialog = nullptr;" in source
|
||||
|
||||
|
||||
def test_successful_boot_cancels_ota_rollback_after_subsystems_initialize():
|
||||
source = MAIN.read_text()
|
||||
confirm = function_body(
|
||||
source,
|
||||
"void confirm_running_firmware()",
|
||||
"void setup_lvgl_and_ui()",
|
||||
)
|
||||
assert "ESP_OTA_IMG_PENDING_VERIFY" in confirm
|
||||
assert "esp_ota_mark_app_valid_cancel_rollback()" in confirm
|
||||
setup = function_body(source, "void setup()", "void loop()")
|
||||
assert setup.index("setup_lxmf();") < setup.index("setup_ui_manager();")
|
||||
assert setup.index("setup_ui_manager();") < setup.index("confirm_running_firmware();")
|
||||
|
||||
Reference in New Issue
Block a user