|
16 | 16 | #endif |
17 | 17 |
|
18 | 18 | constexpr uint32_t WLED_CUSTOM_DESC_MAGIC = 0x57535453; // "WSTS" (WLED System Tag Structure) |
19 | | -constexpr uint32_t WLED_CUSTOM_DESC_VERSION = 1; |
| 19 | +constexpr uint32_t WLED_CUSTOM_DESC_VERSION = 2; // v1 - original PR; v2 - "safe to update from" version |
20 | 20 |
|
21 | 21 | // Compile-time validation that release name doesn't exceed maximum length |
22 | 22 | static_assert(sizeof(WLED_RELEASE_NAME) <= WLED_RELEASE_NAME_MAX_LEN, |
@@ -59,6 +59,11 @@ const wled_metadata_t __attribute__((section(BUILD_METADATA_SECTION))) WLED_BUIL |
59 | 59 | TOSTRING(WLED_VERSION), |
60 | 60 | WLED_RELEASE_NAME, // release_name |
61 | 61 | std::integral_constant<uint32_t, djb2_hash_constexpr(WLED_RELEASE_NAME)>::value, // hash - computed at compile time; integral_constant enforces this |
| 62 | +#if defined(ESP32) && defined(CONFIG_IDF_TARGET_ESP32) |
| 63 | + { 0, 15, 3 }, // Some older ESP32 might have bootloader issues; assume we'll have it sorted by 0.15.3 |
| 64 | +#else |
| 65 | + { 0, 15, 2 }, // All other platforms can update safely |
| 66 | +#endif |
62 | 67 | }; |
63 | 68 |
|
64 | 69 | static const char repoString_s[] PROGMEM = WLED_REPO; |
@@ -96,7 +101,7 @@ bool findWledMetadata(const uint8_t* binaryData, size_t dataSize, wled_metadata_ |
96 | 101 | memcpy(&candidate, binaryData + offset, sizeof(candidate)); |
97 | 102 |
|
98 | 103 | // Found potential match, validate version |
99 | | - if (candidate.desc_version != WLED_CUSTOM_DESC_VERSION) { |
| 104 | + if (candidate.desc_version > WLED_CUSTOM_DESC_VERSION) { |
100 | 105 | DEBUG_PRINTF_P(PSTR("Found WLED structure at offset %u but version mismatch: %u\n"), |
101 | 106 | offset, candidate.desc_version); |
102 | 107 | continue; |
@@ -151,13 +156,30 @@ bool shouldAllowOTA(const wled_metadata_t& firmwareDescription, char* errorMessa |
151 | 156 |
|
152 | 157 | if (strncmp_P(safeFirmwareRelease, releaseString, WLED_RELEASE_NAME_MAX_LEN) != 0) { |
153 | 158 | if (errorMessage && errorMessageLen > 0) { |
154 | | - snprintf_P(errorMessage, errorMessageLen, PSTR("Firmware compatibility mismatch: current='%s', uploaded='%s'."), |
| 159 | + snprintf_P(errorMessage, errorMessageLen, PSTR("Firmware release name mismatch: current='%s', uploaded='%s'."), |
155 | 160 | releaseString, safeFirmwareRelease); |
156 | 161 | errorMessage[errorMessageLen - 1] = '\0'; // Ensure null termination |
157 | 162 | } |
158 | 163 | return false; |
159 | 164 | } |
160 | 165 |
|
| 166 | + if (firmwareDescription.desc_version > 1) { |
| 167 | + // Add safe version check |
| 168 | + // Parse our version (x.y.z) and compare it to the "safe version" array |
| 169 | + char* our_version = const_cast<char*>(versionString); // rip off const for legacy strtol compatibility |
| 170 | + for(unsigned v_index = 0; v_index < 3; ++v_index) { |
| 171 | + long our_v_parsed = strtol(our_version, &our_version, 10); |
| 172 | + ++our_version; // skip the decimal point |
| 173 | + if (firmwareDescription.safe_update_version[v_index] < our_v_parsed) { |
| 174 | + snprintf_P(errorMessage, errorMessageLen, PSTR("Cannot update from this version: requires at least %d.%d.%d, current='%s'."), |
| 175 | + firmwareDescription.safe_update_version[0], firmwareDescription.safe_update_version[1], firmwareDescription.safe_update_version[2], |
| 176 | + versionString); |
| 177 | + errorMessage[errorMessageLen - 1] = '\0'; // Ensure null termination |
| 178 | + return false; |
| 179 | + } |
| 180 | + } |
| 181 | + } |
| 182 | + |
161 | 183 | // TODO: additional checks go here |
162 | 184 |
|
163 | 185 | return true; |
|
0 commit comments