@@ -457,27 +457,40 @@ def default_output_name(self, input_file):
457
457
"""Derive a default output name from the ELF name."""
458
458
return input_file + "-"
459
459
460
- def save (self , basename ):
461
- """Save a set of V1 images for flashing. Parameter is a base filename."""
462
- # IROM data goes in its own plain binary file
460
+ def save (self , filename : str | None ) -> tuple [bytes | None , bytes ] | None :
461
+ irom_data : bytes | None = None
462
+ other_data : bytes | None = None
463
+
464
+ # Handle IROM data
463
465
irom_segment = self .get_irom_segment ()
464
466
if irom_segment is not None :
465
- with open (
466
- "%s0x%05x.bin"
467
- % (basename , irom_segment .addr - ESP8266ROM .IROM_MAP_START ),
468
- "wb" ,
469
- ) as f :
470
- f .write (irom_segment .data )
471
-
472
- # everything but IROM goes at 0x00000 in an image file
473
- normal_segments = self .get_non_irom_segments ()
474
- with open ("%s0x00000.bin" % basename , "wb" ) as f :
467
+ irom_data = irom_segment .data
468
+
469
+ # Handle other segments (everything but IROM)
470
+ with io .BytesIO () as f : # Use BytesIO to write to memory
471
+ normal_segments = self .get_non_irom_segments ()
475
472
self .write_common_header (f , normal_segments )
476
473
checksum = ESPLoader .ESP_CHECKSUM_MAGIC
477
474
for segment in normal_segments :
478
475
checksum = self .save_segment (f , segment , checksum )
479
476
self .append_checksum (f , checksum )
480
477
478
+ other_data = f .getvalue () # Get the bytes from BytesIO
479
+
480
+ if filename is not None :
481
+ # Write IROM data to a file
482
+ if irom_data is not None :
483
+ offset = irom_segment .addr - ESP8266ROM .IROM_MAP_START
484
+ with open (f"{ filename } { offset :#07x} .bin" , "wb" ) as f :
485
+ f .write (irom_data )
486
+ # Write other data to a file
487
+ if other_data is not None :
488
+ with open (f"{ filename } { 0 :#07x} .bin" , "wb" ) as f :
489
+ f .write (other_data )
490
+ return None
491
+ else :
492
+ return (irom_data , other_data )
493
+
481
494
482
495
ESP8266ROM .BOOTLOADER_IMAGE = ESP8266ROMFirmwareImage
483
496
@@ -561,8 +574,8 @@ def default_output_name(self, input_file):
561
574
irom_offs & ~ (ESPLoader .FLASH_SECTOR_SIZE - 1 ),
562
575
)
563
576
564
- def save (self , filename ) :
565
- with open ( filename , "wb" ) as f :
577
+ def save (self , filename : str | None ) -> bytes | None :
578
+ with io . BytesIO ( ) as f : # Write to memory first
566
579
# Save first header for irom0 segment
567
580
f .write (
568
581
struct .pack (
@@ -592,13 +605,20 @@ def save(self, filename):
592
605
checksum = self .save_segment (f , segment , checksum )
593
606
self .append_checksum (f , checksum )
594
607
595
- # calculate a crc32 of entire file and append
596
- # (algorithm used by recent 8266 SDK bootloaders)
597
- with open (filename , "rb" ) as f :
608
+ # Calculate CRC32 of the entire file and append
609
+ f .seek (0 ) # Move to the start of the BytesIO buffer
598
610
crc = esp8266_crc32 (f .read ())
599
- with open (filename , "ab" ) as f :
600
611
f .write (struct .pack (b"<I" , crc ))
601
612
613
+ if filename is not None :
614
+ # Write the content to a real file
615
+ with open (filename , "wb" ) as real_file :
616
+ real_file .write (f .getvalue ())
617
+ return None
618
+ else :
619
+ # Return the bytes if no filename is provided
620
+ return f .getvalue ()
621
+
602
622
603
623
def esp8266_crc32 (data ):
604
624
"""
@@ -686,7 +706,7 @@ def default_output_name(self, input_file):
686
706
def warn_if_unusual_segment (self , offset , size , is_irom_segment ):
687
707
pass # TODO: add warnings for wrong ESP32 segment offset/size combinations
688
708
689
- def save (self , filename ) :
709
+ def save (self , filename : str | None ) -> bytes | None :
690
710
total_segments = 0
691
711
with io .BytesIO () as f : # write file to memory first
692
712
self .write_common_header (f , self .segments )
@@ -895,8 +915,14 @@ def get_alignment_data_needed(segment):
895
915
pad_by = self .pad_to_size - (image_length % self .pad_to_size )
896
916
f .write (b"\xff " * pad_by )
897
917
898
- with open (filename , "wb" ) as real_file :
899
- real_file .write (f .getvalue ())
918
+ if filename is not None :
919
+ # Write the content to a real file
920
+ with open (filename , "wb" ) as real_file :
921
+ real_file .write (f .getvalue ())
922
+ return None
923
+ else :
924
+ # Return the bytes if no filename is provided
925
+ return f .getvalue ()
900
926
901
927
def load_extended_header (self , load_file ):
902
928
def split_byte (n ):
@@ -965,7 +991,7 @@ class ESP8266V3FirmwareImage(ESP32FirmwareImage):
965
991
def is_flash_addr (self , addr ):
966
992
return addr > ESP8266ROM .IROM_MAP_START
967
993
968
- def save (self , filename ) :
994
+ def save (self , filename : str | None ) -> bytes | None :
969
995
total_segments = 0
970
996
with io .BytesIO () as f : # write file to memory first
971
997
self .write_common_header (f , self .segments )
@@ -1033,8 +1059,14 @@ def save(self, filename):
1033
1059
digest .update (f .read (image_length ))
1034
1060
f .write (digest .digest ())
1035
1061
1036
- with open (filename , "wb" ) as real_file :
1037
- real_file .write (f .getvalue ())
1062
+ if filename is not None :
1063
+ # Write the content to a real file
1064
+ with open (filename , "wb" ) as real_file :
1065
+ real_file .write (f .getvalue ())
1066
+ return None
1067
+ else :
1068
+ # Return the bytes if no filename is provided
1069
+ return f .getvalue ()
1038
1070
1039
1071
def load_extended_header (self , load_file ):
1040
1072
def split_byte (n ):
0 commit comments