@@ -426,23 +426,42 @@ void initServer()
426
426
}
427
427
if (!correctPIN || otaLock) return ;
428
428
429
- // Static variable to track release check status across chunks
429
+ // Static variables to track release check status and data accumulation across chunks
430
430
static bool releaseCheckPassed = false ;
431
+ static bool releaseCheckPending = true ;
432
+ static size_t totalBytesReceived = 0 ;
433
+ static uint8_t * validationBuffer = nullptr ;
434
+ static const size_t ESP8266_VALIDATION_OFFSET = 0x1000 ; // 4KB offset for ESP8266
435
+ static const size_t VALIDATION_BUFFER_SIZE = 8192 ; // Buffer size for validation
431
436
432
437
if (!index){
433
438
DEBUG_PRINTLN (F (" OTA Update Start" ));
434
439
440
+ // Reset validation state for new update
441
+ releaseCheckPassed = false ;
442
+ releaseCheckPending = true ;
443
+ totalBytesReceived = 0 ;
444
+
445
+ // Free any existing validation buffer
446
+ if (validationBuffer) {
447
+ free (validationBuffer);
448
+ validationBuffer = nullptr ;
449
+ }
450
+
435
451
// Check if user wants to skip validation
436
452
bool skipValidation = request->hasParam (" skipValidation" , true );
437
453
438
454
// If user chose to skip validation, proceed without compatibility check
439
455
if (skipValidation) {
440
456
DEBUG_PRINTLN (F (" OTA validation skipped by user" ));
441
457
releaseCheckPassed = true ;
458
+ releaseCheckPending = false ;
442
459
} else {
443
- // Validate OTA release compatibility using the first chunk data directly
460
+ #ifdef ESP32
461
+ // ESP32: metadata appears at offset 0, validate immediately with first chunk
444
462
char errorMessage[128 ];
445
463
releaseCheckPassed = shouldAllowOTA (data, len, errorMessage, sizeof (errorMessage));
464
+ releaseCheckPending = false ;
446
465
447
466
if (!releaseCheckPassed) {
448
467
DEBUG_PRINTF_P (PSTR (" OTA declined: %s\n " ), errorMessage);
@@ -451,6 +470,16 @@ void initServer()
451
470
} else {
452
471
DEBUG_PRINTLN (F (" OTA allowed: Release compatibility check passed" ));
453
472
}
473
+ #elif defined(ESP8266)
474
+ // ESP8266: metadata appears around offset 0x1000, need to buffer data until then
475
+ validationBuffer = (uint8_t *)malloc (VALIDATION_BUFFER_SIZE);
476
+ if (!validationBuffer) {
477
+ DEBUG_PRINTLN (F (" OTA failed: Could not allocate validation buffer" ));
478
+ request->send (500 , FPSTR (CONTENT_TYPE_PLAIN), F (" Out of memory for validation" ));
479
+ return ;
480
+ }
481
+ DEBUG_PRINTLN (F (" ESP8266: Deferring validation until offset 0x1000" ));
482
+ #endif
454
483
}
455
484
456
485
DEBUG_PRINTLN (F (" Release check passed, starting OTA update" ));
@@ -487,8 +516,46 @@ void initServer()
487
516
}
488
517
}
489
518
490
- // Write chunk data to OTA update (only if release check passed)
491
- if (releaseCheckPassed && !Update.hasError ()) {
519
+ // Handle ESP8266 deferred validation - accumulate data until validation offset is reached
520
+ #ifdef ESP8266
521
+ if (releaseCheckPending && validationBuffer) {
522
+ // Copy data to validation buffer
523
+ size_t bytesToCopy = min ((size_t )len, VALIDATION_BUFFER_SIZE - totalBytesReceived);
524
+ if (bytesToCopy > 0 ) {
525
+ memcpy (validationBuffer + totalBytesReceived, data, bytesToCopy);
526
+ }
527
+ totalBytesReceived += len;
528
+
529
+ // Check if we've reached the validation offset
530
+ if (totalBytesReceived >= ESP8266_VALIDATION_OFFSET + sizeof (wled_custom_desc_t )) {
531
+ DEBUG_PRINTLN (F (" ESP8266: Performing deferred validation" ));
532
+ char errorMessage[128 ];
533
+
534
+ // Validate using buffered data starting from the expected offset
535
+ releaseCheckPassed = shouldAllowOTA (validationBuffer + ESP8266_VALIDATION_OFFSET,
536
+ totalBytesReceived - ESP8266_VALIDATION_OFFSET,
537
+ errorMessage, sizeof (errorMessage));
538
+ releaseCheckPending = false ;
539
+
540
+ if (!releaseCheckPassed) {
541
+ DEBUG_PRINTF_P (PSTR (" OTA declined (deferred): %s\n " ), errorMessage);
542
+ free (validationBuffer);
543
+ validationBuffer = nullptr ;
544
+ request->send (400 , FPSTR (CONTENT_TYPE_PLAIN), errorMessage);
545
+ return ;
546
+ } else {
547
+ DEBUG_PRINTLN (F (" OTA allowed: Deferred release compatibility check passed" ));
548
+ }
549
+
550
+ // Free validation buffer as it's no longer needed
551
+ free (validationBuffer);
552
+ validationBuffer = nullptr ;
553
+ }
554
+ }
555
+ #endif
556
+
557
+ // Write chunk data to OTA update (only if release check passed or still pending)
558
+ if ((releaseCheckPassed || releaseCheckPending) && !Update.hasError ()) {
492
559
if (Update.write (data, len) != len) {
493
560
DEBUG_PRINTF_P (PSTR (" OTA write failed on chunk %zu: %s\n " ), index, Update.getErrorString ().c_str ());
494
561
}
@@ -497,6 +564,21 @@ void initServer()
497
564
if (isFinal){
498
565
DEBUG_PRINTLN (F (" OTA Update End" ));
499
566
567
+ // Clean up validation buffer if still allocated
568
+ #ifdef ESP8266
569
+ if (validationBuffer) {
570
+ free (validationBuffer);
571
+ validationBuffer = nullptr ;
572
+ }
573
+ #endif
574
+
575
+ // Check if validation was still pending (shouldn't happen normally)
576
+ if (releaseCheckPending) {
577
+ DEBUG_PRINTLN (F (" OTA failed: Validation never completed" ));
578
+ request->send (400 , FPSTR (CONTENT_TYPE_PLAIN), F (" Firmware validation incomplete" ));
579
+ return ;
580
+ }
581
+
500
582
if (releaseCheckPassed) {
501
583
if (Update.end (true )){
502
584
DEBUG_PRINTLN (F (" Update Success" ));
0 commit comments