Skip to content

Commit 5d747d8

Browse files
jedi7radimkarnis
authored andcommitted
feat: enable compress and encryption together
1 parent 81bdb76 commit 5d747d8

24 files changed

+187
-164
lines changed

ci/download_flasher_stubs.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"STUB_SET_VERSION": "1",
1313
"DOWNLOAD_URL": "https://github.com/espressif/esptool-legacy-flasher-stub/releases/download",
1414
"TAG_URL": "https://github.com/espressif/esptool-legacy-flasher-stub/releases/tag",
15-
"VERSION": "v1.9.0",
15+
"VERSION": "v1.10.0",
1616
"FILE_LIST": (
1717
"esp32",
1818
"esp32c2",

esptool/cmds.py

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -619,6 +619,18 @@ def write_flash(
619619
if encrypt or encrypt_files is not None:
620620
do_write = True
621621

622+
if esp.CHIP_NAME == "ESP8266":
623+
raise FatalError("ESP8266 does not support encrypted flashing. ")
624+
625+
# ESP32 ROM bootloader does not support the encryption parameter
626+
# in flash commands. Only the stub flasher supports encrypted writes.
627+
if esp.CHIP_NAME == "ESP32" and not esp.IS_STUB:
628+
raise FatalError(
629+
f"{esp.CHIP_NAME} ROM bootloader does not support encrypted writes. "
630+
"Encrypted writing is only supported by the flasher stub. "
631+
"Do not use --no-stub when writing encrypted data."
632+
)
633+
622634
if not esp.secure_download_mode:
623635
if esp.get_encrypted_download_disabled():
624636
raise FatalError(
@@ -773,16 +785,6 @@ def write_flash(
773785
all_files = sorted(all_files + encrypted_files_flag, key=lambda x: x[0])
774786

775787
for address, data, name, encrypted in all_files:
776-
compress = compress
777-
778-
# Check whether we can compress the current file before flashing
779-
if compress and encrypted:
780-
source = "input bytes" if name is None else f"'{name}'"
781-
log.print("\n")
782-
log.warning("Compress and encrypt options are mutually exclusive.")
783-
log.print(f"Will flash {source} uncompressed.")
784-
compress = False
785-
786788
image = data
787789

788790
if len(image) == 0:
@@ -826,9 +828,11 @@ def write_flash(
826828
# Decompress the compressed binary a block at a time,
827829
# to dynamically calculate the timeout based on the real write size
828830
decompress = zlib.decompressobj()
829-
esp.flash_defl_begin(uncsize, compsize, address)
831+
esp.flash_defl_begin(
832+
uncsize, compsize, address, encrypted_write=encrypted
833+
)
830834
else:
831-
esp.flash_begin(uncsize, address, begin_rom_encrypted=encrypted)
835+
esp.flash_begin(uncsize, address, encrypted_write=encrypted)
832836
seq = 0
833837
bytes_sent = 0 # bytes sent on wire
834838
bytes_written = 0 # bytes written to flash
@@ -861,6 +865,8 @@ def write_flash(
861865
if not esp.IS_STUB:
862866
# ROM code writes block to flash before ACKing
863867
timeout = block_timeout
868+
# For compressed data, encryption is handled
869+
# via encrypted_write flag
864870
esp.flash_defl_block(block, seq, timeout=timeout)
865871
if esp.IS_STUB:
866872
# Stub ACKs when block is received,
@@ -869,10 +875,7 @@ def write_flash(
869875
else:
870876
# Pad the last block
871877
block = block + b"\xff" * (esp.FLASH_WRITE_SIZE - len(block))
872-
if encrypted:
873-
esp.flash_encrypt_block(block, seq)
874-
else:
875-
esp.flash_block(block, seq)
878+
esp.flash_block(block, seq, encrypted=encrypted)
876879
bytes_written += len(block)
877880
bytes_sent += len(block)
878881
image = image[esp.FLASH_WRITE_SIZE :]

esptool/loader.py

Lines changed: 18 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -295,9 +295,6 @@ class ESPLoader:
295295
# Bootloader flashing offset
296296
BOOTLOADER_FLASH_OFFSET = 0x0
297297

298-
# ROM supports an encrypted flashing mode
299-
SUPPORTS_ENCRYPTED_FLASH = False
300-
301298
# Response to SYNC might indicate that flasher stub is running
302299
# instead of the ROM bootloader
303300
sync_stub_detected = False
@@ -988,7 +985,7 @@ def mem_finish(self, entrypoint=0):
988985
raise
989986
pass
990987

991-
def flash_begin(self, size, offset, begin_rom_encrypted=False, logging=True):
988+
def flash_begin(self, size, offset, encrypted_write=False, logging=True):
992989
"""
993990
Start downloading to Flash (performs an erase)
994991
@@ -1008,8 +1005,11 @@ def flash_begin(self, size, offset, begin_rom_encrypted=False, logging=True):
10081005
params = struct.pack(
10091006
"<IIII", erase_size, num_blocks, self.FLASH_WRITE_SIZE, offset
10101007
)
1011-
if self.SUPPORTS_ENCRYPTED_FLASH and not self.IS_STUB:
1012-
params += struct.pack("<I", 1 if begin_rom_encrypted else 0)
1008+
1009+
# ESP32 and ESP8266 ROMs do not support extended parameter format
1010+
if self.IS_STUB or self.CHIP_NAME not in ("ESP32", "ESP8266"):
1011+
params += struct.pack("<I", 1 if encrypted_write else 0)
1012+
10131013
self.check_command(
10141014
"enter flash download mode",
10151015
self.ESP_CMDS["FLASH_BEGIN"],
@@ -1020,39 +1020,15 @@ def flash_begin(self, size, offset, begin_rom_encrypted=False, logging=True):
10201020
log.print(f"Took {time.time() - t:.2f}s to erase flash block.")
10211021
return num_blocks
10221022

1023-
def flash_block(self, data, seq, timeout=DEFAULT_TIMEOUT):
1023+
def flash_block(self, data, seq, timeout=DEFAULT_TIMEOUT, encrypted=False):
10241024
"""Write block to flash, retry if fail"""
1025-
for attempts_left in range(WRITE_BLOCK_ATTEMPTS - 1, -1, -1):
1026-
try:
1027-
self.check_command(
1028-
f"write to target flash after seq {seq}",
1029-
self.ESP_CMDS["FLASH_DATA"],
1030-
struct.pack("<IIII", len(data), seq, 0, 0) + data,
1031-
self.checksum(data),
1032-
timeout=timeout,
1033-
)
1034-
break
1035-
except FatalError:
1036-
if attempts_left:
1037-
self.trace(
1038-
"Block write failed, "
1039-
f"retrying with {attempts_left} attempts left..."
1040-
)
1041-
else:
1042-
raise
1043-
1044-
def flash_encrypt_block(self, data, seq, timeout=DEFAULT_TIMEOUT):
1045-
"""Encrypt, write block to flash, retry if fail"""
1046-
if self.SUPPORTS_ENCRYPTED_FLASH and not self.IS_STUB:
1047-
# ROM support performs the encrypted writes via the normal write command,
1048-
# triggered by flash_begin(begin_rom_encrypted=True)
1049-
return self.flash_block(data, seq, timeout)
10501025

1026+
operation = "encrypted " if encrypted else ""
10511027
for attempts_left in range(WRITE_BLOCK_ATTEMPTS - 1, -1, -1):
10521028
try:
10531029
self.check_command(
1054-
f"Write encrypted to target flash after seq {seq}",
1055-
self.ESP_CMDS["FLASH_ENCRYPT_DATA"],
1030+
f"write {operation}to target flash after seq {seq}",
1031+
self.ESP_CMDS["FLASH_DATA"],
10561032
struct.pack("<IIII", len(data), seq, 0, 0) + data,
10571033
self.checksum(data),
10581034
timeout=timeout,
@@ -1061,8 +1037,8 @@ def flash_encrypt_block(self, data, seq, timeout=DEFAULT_TIMEOUT):
10611037
except FatalError:
10621038
if attempts_left:
10631039
self.trace(
1064-
"Encrypted block write failed, "
1065-
f"retrying with {attempts_left} attempts left"
1040+
f"{operation}block write failed, "
1041+
f"retrying with {attempts_left} attempts left...".capitalize()
10661042
)
10671043
else:
10681044
raise
@@ -1342,7 +1318,7 @@ def run_stub(self, stub: StubFlasher | None = None) -> "ESPLoader":
13421318
return self.STUB_CLASS(self) if self.STUB_CLASS is not None else self
13431319

13441320
@stub_and_esp32_function_only
1345-
def flash_defl_begin(self, size, compsize, offset):
1321+
def flash_defl_begin(self, size, compsize, offset, encrypted_write=False):
13461322
"""
13471323
Start downloading compressed data to Flash (performs an erase)
13481324
@@ -1368,10 +1344,11 @@ def flash_defl_begin(self, size, compsize, offset):
13681344
params = struct.pack(
13691345
"<IIII", write_size, num_blocks, self.FLASH_WRITE_SIZE, offset
13701346
)
1371-
if self.SUPPORTS_ENCRYPTED_FLASH and not self.IS_STUB:
1372-
# extra param is to enter encrypted flash mode via ROM
1373-
# (not supported currently)
1374-
params += struct.pack("<I", 0)
1347+
1348+
# ESP32 and ESP8266 ROMs do not support extended parameter format
1349+
if self.IS_STUB or self.CHIP_NAME not in ("ESP32", "ESP8266"):
1350+
params += struct.pack("<I", 1 if encrypted_write else 0)
1351+
13751352
self.check_command(
13761353
"enter compressed flash mode",
13771354
self.ESP_CMDS["FLASH_DEFL_BEGIN"],

esptool/targets/esp32c3.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,6 @@ class ESP32C3ROM(ESP32ROM):
6969

7070
PURPOSE_VAL_XTS_AES128_KEY = 4
7171

72-
SUPPORTS_ENCRYPTED_FLASH = True
73-
7472
FLASH_ENCRYPTED_WRITE_ALIGN = 16
7573

7674
# Variable in ROM .bss which indicates the port in use

esptool/targets/esp32c6.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,6 @@ class ESP32C6ROM(ESP32C3ROM):
6262

6363
PURPOSE_VAL_XTS_AES128_KEY = 4
6464

65-
SUPPORTS_ENCRYPTED_FLASH = True
66-
6765
FLASH_ENCRYPTED_WRITE_ALIGN = 16
6866

6967
UARTDEV_BUF_NO = 0x4087F580 # Variable in ROM .bss which indicates the port in use

esptool/targets/esp32h4.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,6 @@ class ESP32H4ROM(ESP32C3ROM):
6565

6666
PURPOSE_VAL_XTS_AES128_KEY = 4
6767

68-
SUPPORTS_ENCRYPTED_FLASH = True
69-
7068
FLASH_ENCRYPTED_WRITE_ALIGN = 16
7169

7270
UARTDEV_BUF_NO = 0x4087F580 # Variable in ROM .bss which indicates the port in use

esptool/targets/esp32p4.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,6 @@ class ESP32P4ROM(ESP32ROM):
8080
RTC_CNTL_OPTION1_REG = 0x50110008
8181
RTC_CNTL_FORCE_DOWNLOAD_BOOT_MASK = 0x4 # Is download mode forced over USB?
8282

83-
SUPPORTS_ENCRYPTED_FLASH = True
84-
8583
FLASH_ENCRYPTED_WRITE_ALIGN = 16
8684

8785
@property

esptool/targets/esp32s2.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,6 @@ class ESP32S2ROM(ESP32ROM):
3737

3838
UART_CLKDIV_REG = 0x3F400014
3939

40-
SUPPORTS_ENCRYPTED_FLASH = True
41-
4240
FLASH_ENCRYPTED_WRITE_ALIGN = 16
4341

4442
# todo: use espefuse APIs to get this info

esptool/targets/esp32s3.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,6 @@ class ESP32S3ROM(ESP32ROM):
3838

3939
BOOTLOADER_FLASH_OFFSET = 0x0
4040

41-
SUPPORTS_ENCRYPTED_FLASH = True
42-
4341
FLASH_ENCRYPTED_WRITE_ALIGN = 16
4442

4543
# todo: use espefuse APIs to get this info
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
# Licensing
22

3-
The binaries in JSON format distributed in this directory are released as Free Software under GNU General Public License Version 2 or later. They were released at https://github.com/espressif/esptool-legacy-flasher-stub/releases/tag/v1.9.0 from where the sources can be obtained.
3+
The binaries in JSON format distributed in this directory are released as Free Software under GNU General Public License Version 2 or later. They were released at https://github.com/espressif/esptool-legacy-flasher-stub/releases/tag/v1.10.0 from where the sources can be obtained.

0 commit comments

Comments
 (0)