From 799f065d081b7fd2adcde438b2a00ecc3e13fb8f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 27 Nov 2025 18:08:01 +0000 Subject: [PATCH 01/11] Initial plan From fea140e068678f4dbc54e72e44910d944f14c7df Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 27 Nov 2025 18:21:18 +0000 Subject: [PATCH 02/11] Backport version reporting from PR #5093 and #5111 Co-authored-by: netmindz <442066+netmindz@users.noreply.github.com> --- wled00/fcn_declare.h | 2 + wled00/json.cpp | 2 + wled00/util.cpp | 99 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 103 insertions(+) diff --git a/wled00/fcn_declare.h b/wled00/fcn_declare.h index 16e4471f31..a467f8f51f 100644 --- a/wled00/fcn_declare.h +++ b/wled00/fcn_declare.h @@ -400,6 +400,8 @@ uint8_t extractModeSlider(uint8_t mode, uint8_t slider, char *dest, uint8_t maxL int16_t extractModeDefaults(uint8_t mode, const char *segVar); void checkSettingsPIN(const char *pin); uint16_t crc16(const unsigned char* data_p, size_t length); +String computeSHA1(const String& input); +String getDeviceId(); uint16_t beatsin88_t(accum88 beats_per_minute_88, uint16_t lowest = 0, uint16_t highest = 65535, uint32_t timebase = 0, uint16_t phase_offset = 0); uint16_t beatsin16_t(accum88 beats_per_minute, uint16_t lowest = 0, uint16_t highest = 65535, uint32_t timebase = 0, uint16_t phase_offset = 0); uint8_t beatsin8_t(accum88 beats_per_minute, uint8_t lowest = 0, uint8_t highest = 255, uint32_t timebase = 0, uint8_t phase_offset = 0); diff --git a/wled00/json.cpp b/wled00/json.cpp index ac9b0432b4..bd2d717638 100644 --- a/wled00/json.cpp +++ b/wled00/json.cpp @@ -631,6 +631,8 @@ void serializeInfo(JsonObject root) root[F("vid")] = VERSION; root[F("cn")] = F(WLED_CODENAME); root[F("release")] = releaseString; + root[F("repo")] = repoString; + root[F("deviceId")] = getDeviceId(); JsonObject leds = root.createNestedObject(F("leds")); leds[F("count")] = strip.getLengthTotal(); diff --git a/wled00/util.cpp b/wled00/util.cpp index 301b037b70..62aa49eb63 100644 --- a/wled00/util.cpp +++ b/wled00/util.cpp @@ -3,6 +3,7 @@ #include "const.h" #ifdef ESP8266 #include "user_interface.h" // for bootloop detection +#include // for SHA1 on ESP8266 #else #include #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 0) @@ -10,6 +11,8 @@ #elif ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(3, 3, 0) #include "soc/rtc.h" #endif +#include "mbedtls/sha1.h" // for SHA1 on ESP32 +#include "esp_adc_cal.h" #endif @@ -745,3 +748,99 @@ void handleBootLoop() { ESP.restart(); // restart cleanly and don't wait for another crash } + +// Platform-agnostic SHA1 computation from String input +String computeSHA1(const String& input) { + #ifdef ESP8266 + return sha1(input); // ESP8266 has built-in sha1() function + #else + // ESP32: Compute SHA1 hash using mbedtls + unsigned char shaResult[20]; // SHA1 produces 20 bytes + mbedtls_sha1_context ctx; + + mbedtls_sha1_init(&ctx); + mbedtls_sha1_starts_ret(&ctx); + mbedtls_sha1_update_ret(&ctx, (const unsigned char*)input.c_str(), input.length()); + mbedtls_sha1_finish_ret(&ctx, shaResult); + mbedtls_sha1_free(&ctx); + + // Convert to hexadecimal string + char hexString[41]; + for (int i = 0; i < 20; i++) { + sprintf(&hexString[i*2], "%02x", shaResult[i]); + } + hexString[40] = '\0'; + + return String(hexString); + #endif +} + +#ifdef ESP32 +String generateDeviceFingerprint() { + uint32_t fp[2] = {0, 0}; // create 64 bit fingerprint + esp_chip_info_t chip_info; + esp_chip_info(&chip_info); + esp_efuse_mac_get_default((uint8_t*)fp); + fp[1] ^= ESP.getFlashChipSize(); + #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) + fp[0] ^= chip_info.full_revision | (chip_info.model << 16); + #else + fp[0] ^= chip_info.revision | (chip_info.model << 16); + #endif + // mix in ADC calibration data: + esp_adc_cal_characteristics_t ch; + #if SOC_ADC_MAX_BITWIDTH == 13 // S2 has 13 bit ADC + #define BIT_WIDTH ADC_WIDTH_BIT_13 + #else + #define BIT_WIDTH ADC_WIDTH_BIT_12 + #endif + esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_11, BIT_WIDTH, 1100, &ch); + fp[0] ^= ch.coeff_a; + fp[1] ^= ch.coeff_b; + if (ch.low_curve) { + for (int i = 0; i < 8; i++) { + fp[0] ^= ch.low_curve[i]; + } + } + if (ch.high_curve) { + for (int i = 0; i < 8; i++) { + fp[1] ^= ch.high_curve[i]; + } + } + char fp_string[17]; // 16 hex chars + null terminator + sprintf(fp_string, "%08X%08X", fp[1], fp[0]); + return String(fp_string); +} +#else // ESP8266 +String generateDeviceFingerprint() { + uint32_t fp[2] = {0, 0}; // create 64 bit fingerprint + WiFi.macAddress((uint8_t*)&fp); // use MAC address as fingerprint base + fp[0] ^= ESP.getFlashChipId(); + fp[1] ^= ESP.getFlashChipSize() | ESP.getFlashChipVendorId() << 16; + char fp_string[17]; // 16 hex chars + null terminator + sprintf(fp_string, "%08X%08X", fp[1], fp[0]); + return String(fp_string); +} +#endif + +// Generate a device ID based on SHA1 hash of MAC address salted with other unique device info +// Returns: original SHA1 + last 2 chars of double-hashed SHA1 (42 chars total) +String getDeviceId() { + static String cachedDeviceId = ""; + if (cachedDeviceId.length() > 0) return cachedDeviceId; + // The device string is deterministic as it needs to be consistent for the same device, even after a full flash erase + // MAC is salted with other consistent device info to avoid rainbow table attacks. + // If the MAC address is known by malicious actors, they could precompute SHA1 hashes to impersonate devices, + // but as WLED developers are just looking at statistics and not authenticating devices, this is acceptable. + // If the usage data was exfiltrated, you could not easily determine the MAC from the device ID without brute forcing SHA1 + + String firstHash = computeSHA1(generateDeviceFingerprint()); + + // Second hash: SHA1 of the first hash + String secondHash = computeSHA1(firstHash); + + // Concatenate first hash + last 2 chars of second hash + cachedDeviceId = firstHash + secondHash.substring(38); + + return cachedDeviceId; +} From 3738bf79f59d7444a7e8b5290e0366fabbb4559b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 27 Nov 2025 18:23:31 +0000 Subject: [PATCH 03/11] Add #undef BIT_WIDTH after use Co-authored-by: netmindz <442066+netmindz@users.noreply.github.com> --- _codeql_detected_source_root | 1 + package-lock.json | 4 ++-- wled00/util.cpp | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) create mode 120000 _codeql_detected_source_root diff --git a/_codeql_detected_source_root b/_codeql_detected_source_root new file mode 120000 index 0000000000..945c9b46d6 --- /dev/null +++ b/_codeql_detected_source_root @@ -0,0 +1 @@ +. \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index b80ed0c214..a8a0d89878 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "wled", - "version": "0.15.1", + "version": "0.15.2-beta2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "wled", - "version": "0.15.1", + "version": "0.15.2-beta2", "license": "ISC", "dependencies": { "clean-css": "^5.3.3", diff --git a/wled00/util.cpp b/wled00/util.cpp index 62aa49eb63..a516676b61 100644 --- a/wled00/util.cpp +++ b/wled00/util.cpp @@ -795,6 +795,7 @@ String generateDeviceFingerprint() { #define BIT_WIDTH ADC_WIDTH_BIT_12 #endif esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_11, BIT_WIDTH, 1100, &ch); + #undef BIT_WIDTH fp[0] ^= ch.coeff_a; fp[1] ^= ch.coeff_b; if (ch.low_curve) { From 17cdca2c2d7bbac0ad4579d3120299b1ee85ced6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 27 Nov 2025 18:23:59 +0000 Subject: [PATCH 04/11] Add codeql artifact to gitignore Co-authored-by: netmindz <442066+netmindz@users.noreply.github.com> --- .gitignore | 1 + _codeql_detected_source_root | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) delete mode 120000 _codeql_detected_source_root diff --git a/.gitignore b/.gitignore index 51d321d922..6c80b8e8e5 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,4 @@ wled-update.sh /wled00/Release /wled00/wled00.ino.cpp /wled00/html_*.h +_codeql_detected_source_root diff --git a/_codeql_detected_source_root b/_codeql_detected_source_root deleted file mode 120000 index 945c9b46d6..0000000000 --- a/_codeql_detected_source_root +++ /dev/null @@ -1 +0,0 @@ -. \ No newline at end of file From bb3ee7c3adaf880dfd90e0394798398a2fa33387 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 27 Nov 2025 23:11:55 +0000 Subject: [PATCH 05/11] Add bootloader SHA256 hash to JSON info (cherry-pick from main) Co-authored-by: netmindz <442066+netmindz@users.noreply.github.com> --- wled00/json.cpp | 4 ++++ wled00/ota_update.cpp | 55 ++++++++++++++++++++++++++++++++++++++++++- wled00/ota_update.h | 20 ++++++++++++++++ 3 files changed, 78 insertions(+), 1 deletion(-) diff --git a/wled00/json.cpp b/wled00/json.cpp index bd2d717638..2126de361d 100644 --- a/wled00/json.cpp +++ b/wled00/json.cpp @@ -1,4 +1,5 @@ #include "wled.h" +#include "ota_update.h" #include "palettes.h" @@ -755,6 +756,9 @@ void serializeInfo(JsonObject root) root[F("resetReason1")] = (int)rtc_get_reset_reason(1); #endif root[F("lwip")] = 0; //deprecated + #ifndef WLED_DISABLE_OTA + root[F("bootloaderSHA256")] = getBootloaderSHA256Hex(); + #endif #else root[F("arch")] = "esp8266"; root[F("core")] = ESP.getCoreVersion(); diff --git a/wled00/ota_update.cpp b/wled00/ota_update.cpp index 2f3d6145e6..4e9c13eea1 100644 --- a/wled00/ota_update.cpp +++ b/wled00/ota_update.cpp @@ -3,12 +3,15 @@ #ifdef ESP32 #include +#include +#include #endif // Platform-specific metadata locations #ifdef ESP32 constexpr size_t METADATA_OFFSET = 256; // ESP32: metadata appears after Espressif metadata #define UPDATE_ERROR errorString +const size_t BOOTLOADER_OFFSET = 0x1000; #elif defined(ESP8266) constexpr size_t METADATA_OFFSET = 0x1000; // ESP8266: metadata appears at 4KB offset #define UPDATE_ERROR getErrorString @@ -253,4 +256,54 @@ void handleOTAData(AsyncWebServerRequest *request, size_t index, uint8_t *data, // Upload complete context->uploadComplete = true; } -} \ No newline at end of file +} + +#if defined(ARDUINO_ARCH_ESP32) && !defined(WLED_DISABLE_OTA) +static String bootloaderSHA256HexCache = ""; + +// Calculate and cache the bootloader SHA256 digest as hex string +void calculateBootloaderSHA256() { + if (!bootloaderSHA256HexCache.isEmpty()) return; + + // Bootloader is at fixed offset 0x1000 (4KB) and is typically 32KB + const uint32_t bootloaderSize = 0x8000; // 32KB, typical bootloader size + + // Calculate SHA256 + uint8_t sha256[32]; + mbedtls_sha256_context ctx; + mbedtls_sha256_init(&ctx); + mbedtls_sha256_starts(&ctx, 0); // 0 = SHA256 (not SHA224) + + const size_t chunkSize = 256; + uint8_t buffer[chunkSize]; + + for (uint32_t offset = 0; offset < bootloaderSize; offset += chunkSize) { + size_t readSize = min((size_t)(bootloaderSize - offset), chunkSize); + if (spi_flash_read(BOOTLOADER_OFFSET + offset, buffer, readSize) == ESP_OK) { + mbedtls_sha256_update(&ctx, buffer, readSize); + } + } + + mbedtls_sha256_finish(&ctx, sha256); + mbedtls_sha256_free(&ctx); + + // Convert to hex string and cache it + char hex[65]; + for (int i = 0; i < 32; i++) { + sprintf(hex + (i * 2), "%02x", sha256[i]); + } + hex[64] = '\0'; + bootloaderSHA256HexCache = hex; +} + +// Get bootloader SHA256 as hex string +String getBootloaderSHA256Hex() { + calculateBootloaderSHA256(); + return bootloaderSHA256HexCache; +} + +// Invalidate cached bootloader SHA256 (call after bootloader update) +void invalidateBootloaderSHA256Cache() { + bootloaderSHA256HexCache = ""; +} +#endif \ No newline at end of file diff --git a/wled00/ota_update.h b/wled00/ota_update.h index c8fd702643..6513e9750c 100644 --- a/wled00/ota_update.h +++ b/wled00/ota_update.h @@ -50,3 +50,23 @@ std::pair getOTAResult(AsyncWebServerRequest *request); * @return bool indicating if a reply is necessary; string with error message if the update failed. */ void handleOTAData(AsyncWebServerRequest *request, size_t index, uint8_t *data, size_t len, bool isFinal); + +#if defined(ARDUINO_ARCH_ESP32) && !defined(WLED_DISABLE_OTA) +/** + * Calculate and cache the bootloader SHA256 digest + * Reads the bootloader from flash at offset 0x1000 and computes SHA256 hash + */ +void calculateBootloaderSHA256(); + +/** + * Get bootloader SHA256 as hex string + * @return String containing 64-character hex representation of SHA256 hash + */ +String getBootloaderSHA256Hex(); + +/** + * Invalidate cached bootloader SHA256 (call after bootloader update) + * Forces recalculation on next call to calculateBootloaderSHA256 or getBootloaderSHA256Hex + */ +void invalidateBootloaderSHA256Cache(); +#endif From c64c94d7922bfb566318c8aa503d18ec3c583317 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sat, 29 Nov 2025 00:47:45 +0100 Subject: [PATCH 06/11] avoid #define in generateDeviceFingerprint() --- wled00/util.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/wled00/util.cpp b/wled00/util.cpp index a516676b61..1d1f3881a9 100644 --- a/wled00/util.cpp +++ b/wled00/util.cpp @@ -790,12 +790,11 @@ String generateDeviceFingerprint() { // mix in ADC calibration data: esp_adc_cal_characteristics_t ch; #if SOC_ADC_MAX_BITWIDTH == 13 // S2 has 13 bit ADC - #define BIT_WIDTH ADC_WIDTH_BIT_13 + constexpr auto myBIT_WIDTH = ADC_WIDTH_BIT_13; #else - #define BIT_WIDTH ADC_WIDTH_BIT_12 + constexpr auto myBIT_WIDTH = ADC_WIDTH_BIT_12; #endif - esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_11, BIT_WIDTH, 1100, &ch); - #undef BIT_WIDTH + esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_11, myBIT_WIDTH, 1100, &ch); fp[0] ^= ch.coeff_a; fp[1] ^= ch.coeff_b; if (ch.low_curve) { From 77e3c4d80cdeb3491342329ab16f423c1d37ef61 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sat, 29 Nov 2025 01:23:31 +0100 Subject: [PATCH 07/11] add bootloader offsets for -C3, S3, and some future MCU's --- wled00/ota_update.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/wled00/ota_update.cpp b/wled00/ota_update.cpp index 4e9c13eea1..fcdd2eb0e2 100644 --- a/wled00/ota_update.cpp +++ b/wled00/ota_update.cpp @@ -11,7 +11,16 @@ #ifdef ESP32 constexpr size_t METADATA_OFFSET = 256; // ESP32: metadata appears after Espressif metadata #define UPDATE_ERROR errorString -const size_t BOOTLOADER_OFFSET = 0x1000; + +// Bootloader offsets for different MCUs => see https://github.com/wled/WLED/issues/5064 +#if defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) +constexpr size_t BOOTLOADER_OFFSET = 0x0000; // esp32-S3, esp32-C3 and (future support) esp32-c6 +#elif defined(CONFIG_IDF_TARGET_ESP32P4) || defined(CONFIG_IDF_TARGET_ESP32C5) +constexpr size_t BOOTLOADER_OFFSET = 0x2000; // (future support) esp32-P4 and esp32-C5 +#else +constexpr size_t BOOTLOADER_OFFSET = 0x1000; // esp32 and esp32-s2 +#endif + #elif defined(ESP8266) constexpr size_t METADATA_OFFSET = 0x1000; // ESP8266: metadata appears at 4KB offset #define UPDATE_ERROR getErrorString From 7a5c6f9c1153aec2288569dfbb3ffdc1e04fcd88 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sat, 29 Nov 2025 01:24:16 +0100 Subject: [PATCH 08/11] use esp_flash_read for S3, S2, C3 --- wled00/ota_update.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/wled00/ota_update.cpp b/wled00/ota_update.cpp index fcdd2eb0e2..369b80694a 100644 --- a/wled00/ota_update.cpp +++ b/wled00/ota_update.cpp @@ -288,7 +288,11 @@ void calculateBootloaderSHA256() { for (uint32_t offset = 0; offset < bootloaderSize; offset += chunkSize) { size_t readSize = min((size_t)(bootloaderSize - offset), chunkSize); - if (spi_flash_read(BOOTLOADER_OFFSET + offset, buffer, readSize) == ESP_OK) { +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 0) + if (esp_flash_read(NULL, buffer, BOOTLOADER_OFFSET + offset, readSize) == ESP_OK) { // use esp_flash_read for V4 framework (-S2, -S3, -C3) +#else + if (spi_flash_read(BOOTLOADER_OFFSET + offset, buffer, readSize) == ESP_OK) { // use spi_flash_read for old V3 framework (legacy esp32) +#endif mbedtls_sha256_update(&ctx, buffer, readSize); } } From f9e72f9a5520d8a369440fb0b3f766d03f5d8feb Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sat, 29 Nov 2025 01:24:45 +0100 Subject: [PATCH 09/11] fix over-protective ESP_IDF_VERSION check --- wled00/util.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/util.cpp b/wled00/util.cpp index 1d1f3881a9..7329479086 100644 --- a/wled00/util.cpp +++ b/wled00/util.cpp @@ -782,7 +782,7 @@ String generateDeviceFingerprint() { esp_chip_info(&chip_info); esp_efuse_mac_get_default((uint8_t*)fp); fp[1] ^= ESP.getFlashChipSize(); - #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) + #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 3) fp[0] ^= chip_info.full_revision | (chip_info.model << 16); #else fp[0] ^= chip_info.revision | (chip_info.model << 16); From 15317760b6256ade7012e4b0fa094db7e739772a Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Sat, 29 Nov 2025 01:58:57 +0100 Subject: [PATCH 10/11] allow different bootloader sizes for each MCU not needed yet, but will make maintenance easier in the future, and avoid confusion. --- wled00/ota_update.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/wled00/ota_update.cpp b/wled00/ota_update.cpp index 369b80694a..e0a3c3c85d 100644 --- a/wled00/ota_update.cpp +++ b/wled00/ota_update.cpp @@ -12,13 +12,17 @@ constexpr size_t METADATA_OFFSET = 256; // ESP32: metadata appears after Espressif metadata #define UPDATE_ERROR errorString +// Bootloader is at fixed offset 0x1000 (4KB), 0x0000 (0KB), or 0x2000 (8KB), and is typically 32KB // Bootloader offsets for different MCUs => see https://github.com/wled/WLED/issues/5064 #if defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) constexpr size_t BOOTLOADER_OFFSET = 0x0000; // esp32-S3, esp32-C3 and (future support) esp32-c6 +constexpr size_t BOOTLOADER_SIZE = 0x8000; // 32KB, typical bootloader size #elif defined(CONFIG_IDF_TARGET_ESP32P4) || defined(CONFIG_IDF_TARGET_ESP32C5) constexpr size_t BOOTLOADER_OFFSET = 0x2000; // (future support) esp32-P4 and esp32-C5 +constexpr size_t BOOTLOADER_SIZE = 0x8000; // 32KB, typical bootloader size #else constexpr size_t BOOTLOADER_OFFSET = 0x1000; // esp32 and esp32-s2 +constexpr size_t BOOTLOADER_SIZE = 0x8000; // 32KB, typical bootloader size #endif #elif defined(ESP8266) @@ -274,9 +278,6 @@ static String bootloaderSHA256HexCache = ""; void calculateBootloaderSHA256() { if (!bootloaderSHA256HexCache.isEmpty()) return; - // Bootloader is at fixed offset 0x1000 (4KB) and is typically 32KB - const uint32_t bootloaderSize = 0x8000; // 32KB, typical bootloader size - // Calculate SHA256 uint8_t sha256[32]; mbedtls_sha256_context ctx; @@ -286,8 +287,8 @@ void calculateBootloaderSHA256() { const size_t chunkSize = 256; uint8_t buffer[chunkSize]; - for (uint32_t offset = 0; offset < bootloaderSize; offset += chunkSize) { - size_t readSize = min((size_t)(bootloaderSize - offset), chunkSize); + for (uint32_t offset = 0; offset < BOOTLOADER_SIZE; offset += chunkSize) { + size_t readSize = min((size_t)(BOOTLOADER_SIZE - offset), chunkSize); #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 0) if (esp_flash_read(NULL, buffer, BOOTLOADER_OFFSET + offset, readSize) == ESP_OK) { // use esp_flash_read for V4 framework (-S2, -S3, -C3) #else From a3741656cddc74fe18019c3b905d31969d96dc86 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Sat, 29 Nov 2025 15:11:41 +0000 Subject: [PATCH 11/11] Fix version checking for chip_info.full_revision # Conflicts: # wled00/util.cpp --- wled00/util.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/util.cpp b/wled00/util.cpp index 7329479086..d96a6efc78 100644 --- a/wled00/util.cpp +++ b/wled00/util.cpp @@ -782,7 +782,7 @@ String generateDeviceFingerprint() { esp_chip_info(&chip_info); esp_efuse_mac_get_default((uint8_t*)fp); fp[1] ^= ESP.getFlashChipSize(); - #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 3) + #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 4) fp[0] ^= chip_info.full_revision | (chip_info.model << 16); #else fp[0] ^= chip_info.revision | (chip_info.model << 16);