11#include " ota_release_check.h"
22#include " wled.h"
33
4- bool extractMetadataHeader (uint8_t * binaryData, size_t dataSize, char * extractedRelease, size_t * actualBinarySize) {
5- if (!binaryData || !extractedRelease || !actualBinarySize || dataSize < WLED_META_HEADER_SIZE) {
6- *actualBinarySize = dataSize;
7- return false ;
8- }
4+ #ifdef ESP32
5+ #include < esp_app_format.h>
6+ #include < esp_ota_ops.h>
7+ #endif
98
10- // Check if the binary starts with our metadata header
11- if (memcmp (binaryData, WLED_META_PREFIX, strlen (WLED_META_PREFIX)) != 0 ) {
12- // No metadata header found, this is a legacy binary
13- *actualBinarySize = dataSize;
14- DEBUG_PRINTLN (F (" No WLED metadata header found - legacy binary" ));
15- return false ;
16- }
9+ bool extractReleaseFromCustomDesc (const uint8_t * binaryData, size_t dataSize, char * extractedRelease) {
10+ if (!binaryData || !extractedRelease || dataSize < sizeof (esp_image_header_t )) {
11+ return false ;
12+ }
1713
18- DEBUG_PRINTLN (F (" Found WLED metadata header" ));
14+ #ifdef ESP32
15+ // Look for ESP32 image header to find the custom description section
16+ const esp_image_header_t * header = (const esp_image_header_t *)binaryData;
17+
18+ // Validate ESP32 image header
19+ if (header->magic != ESP_IMAGE_HEADER_MAGIC) {
20+ DEBUG_PRINTLN (F (" Not a valid ESP32 image - missing magic header" ));
21+ return false ;
22+ }
1923
20- // Extract release name from header
21- const char * releaseStart = (const char *)(binaryData + strlen (WLED_META_PREFIX));
22- size_t maxReleaseLen = WLED_META_HEADER_SIZE - strlen (WLED_META_PREFIX) - 1 ;
23-
24- // Copy release name (it should be null-terminated within the header)
25- strncpy (extractedRelease, releaseStart, maxReleaseLen);
26- extractedRelease[maxReleaseLen] = ' \0 ' ; // Ensure null termination
24+ // The custom description section is located at a fixed offset after the image header
25+ // ESP-IDF places custom description at offset 0x20 in the binary for ESP32
26+ const size_t custom_desc_offset = 0x20 ;
27+
28+ if (dataSize < custom_desc_offset + sizeof (wled_custom_desc_t )) {
29+ DEBUG_PRINTLN (F (" Binary too small to contain custom description" ));
30+ return false ;
31+ }
2732
28- // Remove metadata header by shifting binary data
29- size_t firmwareSize = dataSize - WLED_META_HEADER_SIZE;
30- memmove (binaryData, binaryData + WLED_META_HEADER_SIZE, firmwareSize);
31- *actualBinarySize = firmwareSize;
33+ const wled_custom_desc_t * custom_desc = (const wled_custom_desc_t *)(binaryData + custom_desc_offset);
34+
35+ // Validate magic number and version
36+ if (custom_desc->magic != WLED_CUSTOM_DESC_MAGIC) {
37+ DEBUG_PRINTLN (F (" No WLED custom description found - no magic number" ));
38+ return false ;
39+ }
3240
33- DEBUG_PRINTF_P (PSTR (" Extracted release name from metadata: '%s', firmware size: %zu bytes\n " ),
34- extractedRelease, firmwareSize);
41+ if (custom_desc->version != WLED_CUSTOM_DESC_VERSION) {
42+ DEBUG_PRINTF_P (PSTR (" Unsupported custom description version: %u\n " ), custom_desc->version );
43+ return false ;
44+ }
3545
36- return true ;
46+ // Validate simple hash checksum (using the same simple hash as in wled_custom_desc.cpp)
47+ auto simple_hash = [](const char * str) -> uint32_t {
48+ uint32_t hash = 5381 ;
49+ for (int i = 0 ; str[i]; ++i) {
50+ hash = ((hash << 5 ) + hash) + str[i];
51+ }
52+ return hash;
53+ };
54+
55+ uint32_t expected_hash = simple_hash (custom_desc->release_name );
56+ if (custom_desc->crc32 != expected_hash) {
57+ DEBUG_PRINTF_P (PSTR (" Custom description hash mismatch: expected 0x%08x, got 0x%08x\n " ),
58+ expected_hash, custom_desc->crc32 );
59+ return false ;
60+ }
61+
62+ // Extract release name (ensure null termination)
63+ strncpy (extractedRelease, custom_desc->release_name , WLED_RELEASE_NAME_MAX_LEN - 1 );
64+ extractedRelease[WLED_RELEASE_NAME_MAX_LEN - 1 ] = ' \0 ' ;
65+
66+ DEBUG_PRINTF_P (PSTR (" Extracted release name from custom description: '%s'\n " ), extractedRelease);
67+ return true ;
68+ #else
69+ // ESP8266 doesn't use ESP-IDF format, so we can't extract custom description
70+ DEBUG_PRINTLN (F (" ESP8266 binaries do not support custom description extraction" ));
71+ return false ;
72+ #endif
3773}
3874
3975bool validateReleaseCompatibility (const char * extractedRelease) {
@@ -50,37 +86,32 @@ bool validateReleaseCompatibility(const char* extractedRelease) {
5086 return match;
5187}
5288
53- bool shouldAllowOTA (uint8_t * binaryData, size_t dataSize, bool ignoreReleaseCheck, char * errorMessage, size_t * actualBinarySize ) {
89+ bool shouldAllowOTA (const uint8_t * binaryData, size_t dataSize, bool ignoreReleaseCheck, char * errorMessage) {
5490 // Clear error message
5591 if (errorMessage) {
5692 errorMessage[0 ] = ' \0 ' ;
5793 }
58-
59- // Initialize actual binary size to full size by default
60- if (actualBinarySize) {
61- *actualBinarySize = dataSize;
62- }
6394
6495 // If user chose to ignore release check, allow OTA
6596 if (ignoreReleaseCheck) {
6697 DEBUG_PRINTLN (F (" OTA release check bypassed by user" ));
67- // Still need to extract metadata header if present to get clean binary
68- char dummyRelease[64 ];
69- extractMetadataHeader (binaryData, dataSize, dummyRelease, actualBinarySize);
7098 return true ;
7199 }
72100
73- // Try to extract metadata header
74- char extractedRelease[64 ];
75- bool hasMetadata = extractMetadataHeader (binaryData, dataSize, extractedRelease, actualBinarySize );
101+ // Try to extract release name from custom description section
102+ char extractedRelease[WLED_RELEASE_NAME_MAX_LEN ];
103+ bool hasCustomDesc = extractReleaseFromCustomDesc (binaryData, dataSize, extractedRelease);
76104
77- if (!hasMetadata) {
78- // No metadata header - this could be a legacy binary or a binary without our metadata
79- // We cannot determine compatibility for such binaries
105+ if (!hasCustomDesc) {
106+ // No custom description - this could be a legacy binary or ESP8266 binary
80107 if (errorMessage) {
108+ #ifdef ESP32
81109 strcpy (errorMessage, " Binary has no release compatibility metadata. Check 'Ignore release name check' to proceed." );
110+ #else
111+ strcpy (errorMessage, " ESP8266 binaries do not support release checking. Check 'Ignore release name check' to proceed." );
112+ #endif
82113 }
83- DEBUG_PRINTLN (F (" OTA blocked: No metadata header found" ));
114+ DEBUG_PRINTLN (F (" OTA blocked: No custom description found" ));
84115 return false ;
85116 }
86117
0 commit comments