6
6
#include < esp_ota_ops.h>
7
7
#endif
8
8
9
- // Same hash function used at compile time (must match wled_custom_desc.cpp)
10
- static uint32_t djb2_hash (const char * str) {
11
- uint32_t hash = 5381 ;
12
- while (*str) {
13
- hash = ((hash << 5 ) + hash) + *str++;
14
- }
15
- return hash;
16
- }
17
-
18
- bool extractReleaseFromCustomDesc (const uint8_t * binaryData, size_t dataSize, char * extractedRelease) {
19
- if (!binaryData || !extractedRelease || dataSize < 64 ) {
9
+ bool extractWledCustomDesc (const uint8_t * binaryData, size_t dataSize, wled_custom_desc_t * extractedDesc) {
10
+ if (!binaryData || !extractedDesc || dataSize < 64 ) {
20
11
return false ;
21
12
}
22
13
23
- // Search in first 8KB only - ESP32 .rodata.wled_desc and ESP8266 .ver_number
24
- // sections appear early in binary. 8KB should be sufficient for metadata discovery
25
- // while minimizing processing time for large firmware files.
14
+ // Search in first 8KB only. This range was chosen because:
15
+ // - ESP32 .rodata.wled_desc sections appear early in the binary (typically within first 2-4KB)
16
+ // - ESP8266 .ver_number sections also appear early (typically within first 1-2KB)
17
+ // - 8KB provides ample coverage for metadata discovery while minimizing processing time
18
+ // - Larger firmware files (>1MB) would take significantly longer to process with full search
19
+ // - Real-world testing shows all valid metadata appears well within this range
26
20
const size_t search_limit = min (dataSize, (size_t )8192 );
27
21
28
22
for (size_t offset = 0 ; offset <= search_limit - sizeof (wled_custom_desc_t ); offset++) {
@@ -37,23 +31,22 @@ bool extractReleaseFromCustomDesc(const uint8_t* binaryData, size_t dataSize, ch
37
31
continue ;
38
32
}
39
33
40
- // Validate hash using same algorithm as compile-time
41
- uint32_t expected_hash = djb2_hash (custom_desc->release_name );
34
+ // Validate hash using runtime function
35
+ uint32_t expected_hash = djb2_hash_runtime (custom_desc->release_name );
42
36
if (custom_desc->crc32 != expected_hash) {
43
37
DEBUG_PRINTF_P (PSTR (" Found WLED structure at offset %u but hash mismatch\n " ), offset);
44
38
continue ;
45
39
}
46
40
47
- // Valid structure found
48
- strncpy (extractedRelease, custom_desc->release_name , WLED_RELEASE_NAME_MAX_LEN - 1 );
49
- extractedRelease[WLED_RELEASE_NAME_MAX_LEN - 1 ] = ' \0 ' ;
41
+ // Valid structure found - copy entire structure
42
+ memcpy (extractedDesc, custom_desc, sizeof (wled_custom_desc_t ));
50
43
51
44
#ifdef ESP32
52
- DEBUG_PRINTF_P (PSTR (" Extracted ESP32 release name from .rodata.wled_desc section at offset %u: '%s'\n " ),
53
- offset, extractedRelease );
45
+ DEBUG_PRINTF_P (PSTR (" Extracted ESP32 WLED structure from .rodata.wled_desc section at offset %u: '%s'\n " ),
46
+ offset, extractedDesc-> release_name );
54
47
#else
55
- DEBUG_PRINTF_P (PSTR (" Extracted ESP8266 release name from .ver_number section at offset %u: '%s'\n " ),
56
- offset, extractedRelease );
48
+ DEBUG_PRINTF_P (PSTR (" Extracted ESP8266 WLED structure from .ver_number section at offset %u: '%s'\n " ),
49
+ offset, extractedDesc-> release_name );
57
50
#endif
58
51
return true ;
59
52
}
@@ -87,33 +80,33 @@ bool shouldAllowOTA(const uint8_t* binaryData, size_t dataSize, bool skipValidat
87
80
const wled_custom_desc_t * local_desc = getWledCustomDesc ();
88
81
(void )local_desc; // Suppress unused variable warning
89
82
90
- // If user chose to ignore release check , allow OTA
83
+ // If user chose to skip validation , allow OTA immediately
91
84
if (skipValidation) {
92
85
DEBUG_PRINTLN (F (" OTA release check bypassed by user" ));
93
86
return true ;
94
87
}
95
88
96
- // Try to extract release name directly from binary data
97
- char extractedRelease[WLED_RELEASE_NAME_MAX_LEN] ;
98
- bool hasCustomDesc = extractReleaseFromCustomDesc (binaryData, dataSize, extractedRelease );
89
+ // Try to extract WLED structure directly from binary data
90
+ wled_custom_desc_t extractedDesc ;
91
+ bool hasCustomDesc = extractWledCustomDesc (binaryData, dataSize, &extractedDesc );
99
92
100
93
if (!hasCustomDesc) {
101
94
// No custom description - this could be a legacy binary
102
95
if (errorMessage) {
103
- strcpy (errorMessage, " Binary has no release compatibility metadata. Check 'Ignore validation' to proceed." );
96
+ strcpy (errorMessage, " This firmware file is missing compatibility metadata. Enable 'Ignore firmware validation' to proceed anyway ." );
104
97
}
105
- DEBUG_PRINTLN (F (" OTA blocked : No custom description found" ));
98
+ DEBUG_PRINTLN (F (" OTA declined : No custom description found" ));
106
99
return false ;
107
100
}
108
101
109
102
// Validate compatibility using extracted release name
110
- if (!validateReleaseCompatibility (extractedRelease )) {
103
+ if (!validateReleaseCompatibility (extractedDesc. release_name )) {
111
104
if (errorMessage) {
112
- snprintf (errorMessage, 127 , " Release mismatch: current='%s', uploaded='%s'. Check 'Ignore validation' to proceed." ,
113
- releaseString, extractedRelease );
105
+ snprintf (errorMessage, 127 , " Firmware compatibility mismatch: current='%s', uploaded='%s'. Enable 'Ignore firmware validation' to proceed anyway ." ,
106
+ releaseString, extractedDesc. release_name );
114
107
}
115
- DEBUG_PRINTF_P (PSTR (" OTA blocked : Release mismatch current='%s', uploaded='%s'\n " ),
116
- releaseString, extractedRelease );
108
+ DEBUG_PRINTF_P (PSTR (" OTA declined : Release mismatch current='%s', uploaded='%s'\n " ),
109
+ releaseString, extractedDesc. release_name );
117
110
return false ;
118
111
}
119
112
0 commit comments