-
-
Notifications
You must be signed in to change notification settings - Fork 4.1k
Add option to use SafeBootloader #5426
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| # Name, Type, SubType, Offset, Size, Flags | ||
| nvs, data, nvs, 0x9000, 0x5000, | ||
| otadata, data, ota, 0xe000, 0x2000, | ||
| app0, app, ota_0, 0x10000, 0x240000, | ||
| app1, app, ota_1, 0x250000, 0x240000, | ||
| spiffs, data, spiffs, 0x490000, 0x100000, | ||
| spiffs_backup, data, 0x40, 0x590000, 0x100000, | ||
| crc0, data, 0x41, 0x690000, 0x1000, | ||
| crc1, data, 0x42, 0x691000, 0x1000, | ||
| coredump, data, coredump,,64K |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,86 @@ | ||
| /* | ||
| This functions are used to use WLED together with "Safe Bootbootloader" | ||
| https://github.com/wled-install/SafeBootloader | ||
| */ | ||
| #ifdef WLED_ENABLE_SAFE_BOOT | ||
| #include "safe_boot_functions.h" | ||
| #include "wled.h" | ||
| #include <Arduino.h> | ||
|
|
||
| #define SPIFFS_CRC_MAGIC 0x53504653 | ||
|
|
||
| typedef struct { | ||
| uint32_t magic; | ||
| uint32_t crc_spiffs; // CRC SPIFFS / Backup | ||
| uint32_t size_spiffs; // Größe SPIFFS / Backup | ||
| } crc_group_t; | ||
|
|
||
| uint32_t calc_crc(const esp_partition_t* part) | ||
| { | ||
| const size_t bufsize = 4096; | ||
| uint8_t buf[bufsize]; | ||
|
|
||
| uint32_t crc = 0; | ||
| size_t offset = 0; | ||
|
|
||
| while (offset < part->size) { | ||
| size_t toread = bufsize; | ||
| if (offset + toread > part->size) | ||
| toread = part->size - offset; | ||
|
|
||
| esp_partition_read(part, offset, buf, toread); | ||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| crc = crc32_le(crc, buf, toread); | ||
| offset += toread; | ||
| } | ||
|
|
||
| return crc; | ||
| } | ||
|
|
||
| bool update_spiffs_crc() | ||
| { | ||
| const esp_partition_t* spiffs = | ||
| esp_partition_find_first( | ||
| ESP_PARTITION_TYPE_DATA, | ||
| ESP_PARTITION_SUBTYPE_DATA_SPIFFS, | ||
| "spiffs"); | ||
|
|
||
| const esp_partition_t* crcpart = | ||
| esp_partition_find_first( | ||
| ESP_PARTITION_TYPE_DATA, | ||
| static_cast<esp_partition_subtype_t>(0x41), // crc subtype | ||
| "crc0"); | ||
|
|
||
| if (!spiffs || !crcpart) { | ||
| DEBUG_PRINTLN(F("SPIFFS or CRC partition not found!")); | ||
| return false; | ||
| } | ||
|
|
||
|
|
||
| uint32_t crc = calc_crc(spiffs); | ||
|
|
||
| crc_group_t stored = {}; | ||
| esp_partition_read(crcpart, 0, &stored, sizeof(stored)); | ||
|
|
||
| // prüfen ob identisch | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. minor: please translate german comments into english |
||
| if (stored.magic == SPIFFS_CRC_MAGIC && | ||
| stored.crc_spiffs == crc && | ||
| stored.size_spiffs == spiffs->size) | ||
| { | ||
| // nichts zu tun | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same minor comment here: german -> english please |
||
| DEBUG_PRINTLN(F("SPIFFS CRC matches stored value, no update needed.")); | ||
| return true; | ||
| } | ||
|
|
||
| stored.magic = SPIFFS_CRC_MAGIC; | ||
| stored.crc_spiffs = crc; | ||
| stored.size_spiffs = spiffs->size; | ||
| DEBUG_PRINTLN(F("Updating SPIFFS CRC partition with new values.")); | ||
| esp_partition_erase_range(crcpart, 0, 4096); | ||
| esp_partition_write(crcpart, 0, &stored, sizeof(stored)); | ||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| DEBUG_PRINTLN(F("SPIFFS CRC partition updated.")); | ||
|
|
||
| return true; | ||
| } | ||
|
Comment on lines
+12
to
+84
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Indentation does not follow the repository C++ style rule. Line 12 onward uses 4-space indentation in nested scopes; this repository guideline requires 2 spaces per level. As per coding guidelines 🤖 Prompt for AI Agents |
||
|
|
||
| #endif | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| /* | ||
| This functions are used to use WLED together with "Safe Bootbootloader" | ||
| https://github.com/wled-install/SafeBootloader | ||
| */ | ||
|
|
||
| #pragma once | ||
|
|
||
| #ifdef WLED_ENABLE_SAFE_BOOT | ||
| #include <esp_partition.h> | ||
| #include <esp_spi_flash.h> | ||
| #include <rom/crc.h> | ||
| #include <esp_ota_ops.h> | ||
|
|
||
| bool update_spiffs_crc(); | ||
|
|
||
| #endif |
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Critical performance concern: CRC calculation on every file close.
Calling
update_spiffs_crc()after everycloseFile()will cause significant performance degradation. Based on the implementation inwled00/safe_boot_functions.cpp:19-39,calc_crc()reads the entire SPIFFS partition in 4 KB chunks. For a typical 1-3 MB SPIFFS partition, this means reading megabytes of flash data on every single file close operation.This will cause:
Consider updating the CRC only at strategic points (config save, preset save completion) rather than on every file close, or deferring CRC updates to idle time.
The CRC updates in
cfg.cpp,presets.cpp, andcopyFile()should be sufficient for Safe Boot validation.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Theoretically yes, practially it is fast enogh.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@wled-install, fair enough — thanks for testing this on actual hardware. The CRC read-and-compute still happens on every close even when no update is needed, but if you've verified it doesn't cause noticeable lag or watchdog issues in practice (likely because ESP32 flash reads at ~40 MHz are fast relative to the partition size), that's a reasonable call to make. Acknowledged!🧠 Learnings used
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@wled-install I still think this is a valid concern - especially when users have many leds, frequent flash file reads can lead to leds flickering, or effects slowing down randomly. Also there are boards with 16mb flash (9MB LittleFS) or even 32MB flash (24MB LittleFS) where it might actually cause a slow-down.
Not sure if you found all the file closing locations in the code - ledmaps/gapmaps, webserver up/download, and gif player do file access directly, without relying on file.cpp functions.
The first optimization could be to only update CRCs after file write closing, but not on file read closing.
Or - depending on how mission critical these checksums are - create a global flag
crc_dirtyand delay updating the checksums into the main loop, maybe only every 15 seconds.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.