1# SPDX-FileCopyrightText: 2014-2022 Fredrik Ahlberg, Angus Gratton, 2# Espressif Systems (Shanghai) CO LTD, other contributors as noted. 3# 4# SPDX-License-Identifier: GPL-2.0-or-later 5 6import hashlib 7import io 8import os 9import struct 10import sys 11import time 12import zlib 13 14from .bin_image import ELFFile, ImageSegment, LoadFirmwareImage 15from .bin_image import ( 16 ESP8266ROMFirmwareImage, 17 ESP8266V2FirmwareImage, 18 ESP8266V3FirmwareImage, 19) 20from .loader import ( 21 DEFAULT_CONNECT_ATTEMPTS, 22 DEFAULT_TIMEOUT, 23 ERASE_WRITE_TIMEOUT_PER_MB, 24 ESPLoader, 25 timeout_per_mb, 26) 27from .targets import CHIP_DEFS, CHIP_LIST, ROM_LIST 28from .util import ( 29 FatalError, 30 NotImplementedInROMError, 31 NotSupportedError, 32 UnsupportedCommandError, 33) 34from .util import ( 35 div_roundup, 36 flash_size_bytes, 37 hexify, 38 pad_to, 39 print_overwrite, 40) 41 42DETECTED_FLASH_SIZES = { 43 0x12: "256KB", 44 0x13: "512KB", 45 0x14: "1MB", 46 0x15: "2MB", 47 0x16: "4MB", 48 0x17: "8MB", 49 0x18: "16MB", 50 0x19: "32MB", 51 0x1A: "64MB", 52 0x1B: "128MB", 53 0x1C: "256MB", 54 0x20: "64MB", 55 0x21: "128MB", 56 0x22: "256MB", 57 0x32: "256KB", 58 0x33: "512KB", 59 0x34: "1MB", 60 0x35: "2MB", 61 0x36: "4MB", 62 0x37: "8MB", 63 0x38: "16MB", 64 0x39: "32MB", 65 0x3A: "64MB", 66} 67 68FLASH_MODES = {"qio": 0, "qout": 1, "dio": 2, "dout": 3} 69 70 71def detect_chip( 72 port=ESPLoader.DEFAULT_PORT, 73 baud=ESPLoader.ESP_ROM_BAUD, 74 connect_mode="default_reset", 75 trace_enabled=False, 76 connect_attempts=DEFAULT_CONNECT_ATTEMPTS, 77): 78 """Use serial access to detect the chip type. 79 80 First, get_security_info command is sent to detect the ID of the chip 81 (supported only by ESP32-C3 and later, works even in the Secure Download Mode). 82 If this fails, we reconnect and fall-back to reading the magic number. 83 It's mapped at a specific ROM address and has a different value on each chip model. 84 This way we use one memory read and compare it to the magic number for each chip. 85 86 This routine automatically performs ESPLoader.connect() (passing 87 connect_mode parameter) as part of querying the chip. 88 """ 89 inst = None 90 detect_port = ESPLoader(port, baud, trace_enabled=trace_enabled) 91 if detect_port.serial_port.startswith("rfc2217:"): 92 detect_port.USES_RFC2217 = True 93 detect_port.connect(connect_mode, connect_attempts, detecting=True) 94 try: 95 print("Detecting chip type...", end="") 96 chip_id = detect_port.get_chip_id() 97 for cls in [ 98 n for n in ROM_LIST if n.CHIP_NAME not in ("ESP8266", "ESP32", "ESP32S2") 99 ]: 100 # cmd not supported on ESP8266 and ESP32 + ESP32-S2 doesn't return chip_id 101 if chip_id == cls.IMAGE_CHIP_ID: 102 inst = cls(detect_port._port, baud, trace_enabled=trace_enabled) 103 try: 104 inst.read_reg( 105 ESPLoader.CHIP_DETECT_MAGIC_REG_ADDR 106 ) # Dummy read to check Secure Download mode 107 except UnsupportedCommandError: 108 inst.secure_download_mode = True 109 inst._post_connect() 110 except (UnsupportedCommandError, struct.error, FatalError) as e: 111 # UnsupportedCommmanddError: ESP8266/ESP32 ROM 112 # struct.error: ESP32-S2 113 # FatalError: ESP8266/ESP32 STUB 114 print(" Unsupported detection protocol, switching and trying again...") 115 try: 116 # ESP32/ESP8266 are reset after an unsupported command, need to reconnect 117 # (not needed on ESP32-S2) 118 if not isinstance(e, struct.error): 119 detect_port.connect( 120 connect_mode, connect_attempts, detecting=True, warnings=False 121 ) 122 print("Detecting chip type...", end="") 123 sys.stdout.flush() 124 chip_magic_value = detect_port.read_reg( 125 ESPLoader.CHIP_DETECT_MAGIC_REG_ADDR 126 ) 127 128 for cls in ROM_LIST: 129 if chip_magic_value in cls.CHIP_DETECT_MAGIC_VALUE: 130 inst = cls(detect_port._port, baud, trace_enabled=trace_enabled) 131 inst._post_connect() 132 inst.check_chip_id() 133 except UnsupportedCommandError: 134 raise FatalError( 135 "Unsupported Command Error received. " 136 "Probably this means Secure Download Mode is enabled, " 137 "autodetection will not work. Need to manually specify the chip." 138 ) 139 finally: 140 if inst is not None: 141 print(" %s" % inst.CHIP_NAME, end="") 142 if detect_port.sync_stub_detected: 143 inst = inst.STUB_CLASS(inst) 144 inst.sync_stub_detected = True 145 print("") # end line 146 return inst 147 raise FatalError( 148 "Unexpected CHIP magic value 0x%08x. Failed to autodetect chip type." 149 % (chip_magic_value) 150 ) 151 152 153# "Operation" commands, executable at command line. One function each 154# 155# Each function takes either two args (<ESPLoader instance>, <args>) or a single <args> 156# argument. 157 158 159def load_ram(esp, args): 160 image = LoadFirmwareImage(esp.CHIP_NAME, args.filename) 161 162 print("RAM boot...") 163 for seg in image.segments: 164 size = len(seg.data) 165 print("Downloading %d bytes at %08x..." % (size, seg.addr), end=" ") 166 sys.stdout.flush() 167 esp.mem_begin( 168 size, div_roundup(size, esp.ESP_RAM_BLOCK), esp.ESP_RAM_BLOCK, seg.addr 169 ) 170 171 seq = 0 172 while len(seg.data) > 0: 173 esp.mem_block(seg.data[0 : esp.ESP_RAM_BLOCK], seq) 174 seg.data = seg.data[esp.ESP_RAM_BLOCK :] 175 seq += 1 176 print("done!") 177 178 print("All segments done, executing at %08x" % image.entrypoint) 179 esp.mem_finish(image.entrypoint) 180 181 182def read_mem(esp, args): 183 print("0x%08x = 0x%08x" % (args.address, esp.read_reg(args.address))) 184 185 186def write_mem(esp, args): 187 esp.write_reg(args.address, args.value, args.mask, 0) 188 print("Wrote %08x, mask %08x to %08x" % (args.value, args.mask, args.address)) 189 190 191def dump_mem(esp, args): 192 with open(args.filename, "wb") as f: 193 for i in range(args.size // 4): 194 d = esp.read_reg(args.address + (i * 4)) 195 f.write(struct.pack(b"<I", d)) 196 if f.tell() % 1024 == 0: 197 print_overwrite( 198 "%d bytes read... (%d %%)" % (f.tell(), f.tell() * 100 // args.size) 199 ) 200 sys.stdout.flush() 201 print_overwrite("Read %d bytes" % f.tell(), last_line=True) 202 print("Done!") 203 204 205def detect_flash_size(esp, args): 206 if args.flash_size == "detect": 207 if esp.secure_download_mode: 208 raise FatalError( 209 "Detecting flash size is not supported in secure download mode. " 210 "Need to manually specify flash size." 211 ) 212 flash_id = esp.flash_id() 213 size_id = flash_id >> 16 214 args.flash_size = DETECTED_FLASH_SIZES.get(size_id) 215 if args.flash_size is None: 216 print( 217 "Warning: Could not auto-detect Flash size (FlashID=0x%x, SizeID=0x%x)," 218 " defaulting to 4MB" % (flash_id, size_id) 219 ) 220 args.flash_size = "4MB" 221 else: 222 print("Auto-detected Flash size:", args.flash_size) 223 224 225def _update_image_flash_params(esp, address, args, image): 226 """ 227 Modify the flash mode & size bytes if this looks like an executable bootloader image 228 """ 229 if len(image) < 8: 230 return image # not long enough to be a bootloader image 231 232 # unpack the (potential) image header 233 magic, _, flash_mode, flash_size_freq = struct.unpack("BBBB", image[:4]) 234 if address != esp.BOOTLOADER_FLASH_OFFSET: 235 return image # not flashing bootloader offset, so don't modify this 236 237 if (args.flash_mode, args.flash_freq, args.flash_size) == ("keep",) * 3: 238 return image # all settings are 'keep', not modifying anything 239 240 # easy check if this is an image: does it start with a magic byte? 241 if magic != esp.ESP_IMAGE_MAGIC: 242 print( 243 "Warning: Image file at 0x%x doesn't look like an image file, " 244 "so not changing any flash settings." % address 245 ) 246 return image 247 248 # make sure this really is an image, and not just data that 249 # starts with esp.ESP_IMAGE_MAGIC (mostly a problem for encrypted 250 # images that happen to start with a magic byte 251 try: 252 test_image = esp.BOOTLOADER_IMAGE(io.BytesIO(image)) 253 test_image.verify() 254 except Exception: 255 print( 256 "Warning: Image file at 0x%x is not a valid %s image, " 257 "so not changing any flash settings." % (address, esp.CHIP_NAME) 258 ) 259 return image 260 261 # After the 8-byte header comes the extended header for chips others than ESP8266. 262 # The 15th byte of the extended header indicates if the image is protected by 263 # a SHA256 checksum. In that case we should not modify the header because 264 # the checksum check would fail. 265 sha_implies_keep = args.chip != "esp8266" and image[8 + 15] == 1 266 267 def print_keep_warning(arg_to_keep, arg_used): 268 print( 269 "Warning: Image file at {addr} is protected with a hash checksum, " 270 "so not changing the flash {arg} setting. " 271 "Use the --flash_{arg}=keep option instead of --flash_{arg}={arg_orig} " 272 "in order to remove this warning, or use the --dont-append-digest option " 273 "for the elf2image command in order to generate an image file " 274 "without a hash checksum".format( 275 addr=hex(address), arg=arg_to_keep, arg_orig=arg_used 276 ) 277 ) 278 279 if args.flash_mode != "keep": 280 new_flash_mode = FLASH_MODES[args.flash_mode] 281 if flash_mode != new_flash_mode and sha_implies_keep: 282 print_keep_warning("mode", args.flash_mode) 283 else: 284 flash_mode = new_flash_mode 285 286 flash_freq = flash_size_freq & 0x0F 287 if args.flash_freq != "keep": 288 new_flash_freq = esp.parse_flash_freq_arg(args.flash_freq) 289 if flash_freq != new_flash_freq and sha_implies_keep: 290 print_keep_warning("frequency", args.flash_freq) 291 else: 292 flash_freq = new_flash_freq 293 294 flash_size = flash_size_freq & 0xF0 295 if args.flash_size != "keep": 296 new_flash_size = esp.parse_flash_size_arg(args.flash_size) 297 if flash_size != new_flash_size and sha_implies_keep: 298 print_keep_warning("size", args.flash_size) 299 else: 300 flash_size = new_flash_size 301 302 flash_params = struct.pack(b"BB", flash_mode, flash_size + flash_freq) 303 if flash_params != image[2:4]: 304 print("Flash params set to 0x%04x" % struct.unpack(">H", flash_params)) 305 image = image[0:2] + flash_params + image[4:] 306 return image 307 308 309def write_flash(esp, args): 310 # set args.compress based on default behaviour: 311 # -> if either --compress or --no-compress is set, honour that 312 # -> otherwise, set --compress unless --no-stub is set 313 if args.compress is None and not args.no_compress: 314 args.compress = not args.no_stub 315 316 if not args.force and esp.CHIP_NAME != "ESP8266" and not esp.secure_download_mode: 317 # Check if secure boot is active 318 if esp.get_secure_boot_enabled(): 319 for address, _ in args.addr_filename: 320 if address < 0x8000: 321 raise FatalError( 322 "Secure Boot detected, writing to flash regions < 0x8000 " 323 "is disabled to protect the bootloader. " 324 "Use --force to override, " 325 "please use with caution, otherwise it may brick your device!" 326 ) 327 # Check if chip_id and min_rev in image are valid for the target in use 328 for _, argfile in args.addr_filename: 329 try: 330 image = LoadFirmwareImage(esp.CHIP_NAME, argfile) 331 except (FatalError, struct.error, RuntimeError): 332 continue 333 finally: 334 argfile.seek(0) # LoadFirmwareImage changes the file handle position 335 if image.chip_id != esp.IMAGE_CHIP_ID: 336 raise FatalError( 337 f"{argfile.name} is not an {esp.CHIP_NAME} image. " 338 "Use --force to flash anyway." 339 ) 340 341 # this logic below decides which min_rev to use, min_rev or min/max_rev_full 342 if image.max_rev_full == 0: # image does not have max/min_rev_full fields 343 use_rev_full_fields = False 344 elif image.max_rev_full == 65535: # image has default value of max_rev_full 345 use_rev_full_fields = True 346 if ( 347 image.min_rev_full == 0 and image.min_rev != 0 348 ): # min_rev_full is not set, min_rev is used 349 use_rev_full_fields = False 350 else: # max_rev_full set to a version 351 use_rev_full_fields = True 352 353 if use_rev_full_fields: 354 rev = esp.get_chip_revision() 355 if rev < image.min_rev_full or rev > image.max_rev_full: 356 error_str = f"{argfile.name} requires chip revision in range " 357 error_str += ( 358 f"[v{image.min_rev_full // 100}.{image.min_rev_full % 100} - " 359 ) 360 if image.max_rev_full == 65535: 361 error_str += "max rev not set] " 362 else: 363 error_str += ( 364 f"v{image.max_rev_full // 100}.{image.max_rev_full % 100}] " 365 ) 366 error_str += f"(this chip is revision v{rev // 100}.{rev % 100})" 367 raise FatalError(f"{error_str}. Use --force to flash anyway.") 368 else: 369 # In IDF, image.min_rev is set based on Kconfig option. 370 # For C3 chip, image.min_rev is the Minor revision 371 # while for the rest chips it is the Major revision. 372 if esp.CHIP_NAME == "ESP32-C3": 373 rev = esp.get_minor_chip_version() 374 else: 375 rev = esp.get_major_chip_version() 376 if rev < image.min_rev: 377 raise FatalError( 378 f"{argfile.name} requires chip revision " 379 f"{image.min_rev} or higher (this chip is revision {rev}). " 380 "Use --force to flash anyway." 381 ) 382 383 # In case we have encrypted files to write, 384 # we first do few sanity checks before actual flash 385 if args.encrypt or args.encrypt_files is not None: 386 do_write = True 387 388 if not esp.secure_download_mode: 389 if esp.get_encrypted_download_disabled(): 390 raise FatalError( 391 "This chip has encrypt functionality " 392 "in UART download mode disabled. " 393 "This is the Flash Encryption configuration for Production mode " 394 "instead of Development mode." 395 ) 396 397 crypt_cfg_efuse = esp.get_flash_crypt_config() 398 399 if crypt_cfg_efuse is not None and crypt_cfg_efuse != 0xF: 400 print("Unexpected FLASH_CRYPT_CONFIG value: 0x%x" % (crypt_cfg_efuse)) 401 do_write = False 402 403 enc_key_valid = esp.is_flash_encryption_key_valid() 404 405 if not enc_key_valid: 406 print("Flash encryption key is not programmed") 407 do_write = False 408 409 # Determine which files list contain the ones to encrypt 410 files_to_encrypt = args.addr_filename if args.encrypt else args.encrypt_files 411 412 for address, argfile in files_to_encrypt: 413 if address % esp.FLASH_ENCRYPTED_WRITE_ALIGN: 414 print( 415 "File %s address 0x%x is not %d byte aligned, can't flash encrypted" 416 % (argfile.name, address, esp.FLASH_ENCRYPTED_WRITE_ALIGN) 417 ) 418 do_write = False 419 420 if not do_write and not args.ignore_flash_encryption_efuse_setting: 421 raise FatalError( 422 "Can't perform encrypted flash write, " 423 "consult Flash Encryption documentation for more information" 424 ) 425 else: 426 if not args.force and esp.CHIP_NAME != "ESP8266": 427 # ESP32 does not support `get_security_info()` and `secure_download_mode` 428 if ( 429 esp.CHIP_NAME != "ESP32" 430 and esp.secure_download_mode 431 and bin(esp.get_security_info()["flash_crypt_cnt"]).count("1") & 1 != 0 432 ): 433 raise FatalError( 434 "WARNING: Detected flash encryption and " 435 "secure download mode enabled.\n" 436 "Flashing plaintext binary may brick your device! " 437 "Use --force to override the warning." 438 ) 439 440 if ( 441 not esp.secure_download_mode 442 and esp.get_encrypted_download_disabled() 443 and esp.get_flash_encryption_enabled() 444 ): 445 raise FatalError( 446 "WARNING: Detected flash encryption enabled and " 447 "download manual encrypt disabled.\n" 448 "Flashing plaintext binary may brick your device! " 449 "Use --force to override the warning." 450 ) 451 452 # verify file sizes fit in flash 453 if args.flash_size != "keep": # TODO: check this even with 'keep' 454 flash_end = flash_size_bytes(args.flash_size) 455 for address, argfile in args.addr_filename: 456 argfile.seek(0, os.SEEK_END) 457 if address + argfile.tell() > flash_end: 458 raise FatalError( 459 "File %s (length %d) at offset %d " 460 "will not fit in %d bytes of flash. " 461 "Use --flash_size argument, or change flashing address." 462 % (argfile.name, argfile.tell(), address, flash_end) 463 ) 464 argfile.seek(0) 465 466 if args.erase_all: 467 erase_flash(esp, args) 468 else: 469 for address, argfile in args.addr_filename: 470 argfile.seek(0, os.SEEK_END) 471 write_end = address + argfile.tell() 472 argfile.seek(0) 473 bytes_over = address % esp.FLASH_SECTOR_SIZE 474 if bytes_over != 0: 475 print( 476 "WARNING: Flash address {:#010x} is not aligned " 477 "to a {:#x} byte flash sector. " 478 "{:#x} bytes before this address will be erased.".format( 479 address, esp.FLASH_SECTOR_SIZE, bytes_over 480 ) 481 ) 482 # Print the address range of to-be-erased flash memory region 483 print( 484 "Flash will be erased from {:#010x} to {:#010x}...".format( 485 address - bytes_over, 486 div_roundup(write_end, esp.FLASH_SECTOR_SIZE) 487 * esp.FLASH_SECTOR_SIZE 488 - 1, 489 ) 490 ) 491 492 """ Create a list describing all the files we have to flash. 493 Each entry holds an "encrypt" flag marking whether the file needs encryption or not. 494 This list needs to be sorted. 495 496 First, append to each entry of our addr_filename list the flag args.encrypt 497 E.g., if addr_filename is [(0x1000, "partition.bin"), (0x8000, "bootloader")], 498 all_files will be [ 499 (0x1000, "partition.bin", args.encrypt), 500 (0x8000, "bootloader", args.encrypt) 501 ], 502 where, of course, args.encrypt is either True or False 503 """ 504 all_files = [ 505 (offs, filename, args.encrypt) for (offs, filename) in args.addr_filename 506 ] 507 508 """ 509 Now do the same with encrypt_files list, if defined. 510 In this case, the flag is True 511 """ 512 if args.encrypt_files is not None: 513 encrypted_files_flag = [ 514 (offs, filename, True) for (offs, filename) in args.encrypt_files 515 ] 516 517 # Concatenate both lists and sort them. 518 # As both list are already sorted, we could simply do a merge instead, 519 # but for the sake of simplicity and because the lists are very small, 520 # let's use sorted. 521 all_files = sorted(all_files + encrypted_files_flag, key=lambda x: x[0]) 522 523 for address, argfile, encrypted in all_files: 524 compress = args.compress 525 526 # Check whether we can compress the current file before flashing 527 if compress and encrypted: 528 print("\nWARNING: - compress and encrypt options are mutually exclusive ") 529 print("Will flash %s uncompressed" % argfile.name) 530 compress = False 531 532 if args.no_stub: 533 print("Erasing flash...") 534 image = pad_to( 535 argfile.read(), esp.FLASH_ENCRYPTED_WRITE_ALIGN if encrypted else 4 536 ) 537 if len(image) == 0: 538 print("WARNING: File %s is empty" % argfile.name) 539 continue 540 image = _update_image_flash_params(esp, address, args, image) 541 calcmd5 = hashlib.md5(image).hexdigest() 542 uncsize = len(image) 543 if compress: 544 uncimage = image 545 image = zlib.compress(uncimage, 9) 546 # Decompress the compressed binary a block at a time, 547 # to dynamically calculate the timeout based on the real write size 548 decompress = zlib.decompressobj() 549 blocks = esp.flash_defl_begin(uncsize, len(image), address) 550 else: 551 blocks = esp.flash_begin(uncsize, address, begin_rom_encrypted=encrypted) 552 argfile.seek(0) # in case we need it again 553 seq = 0 554 bytes_sent = 0 # bytes sent on wire 555 bytes_written = 0 # bytes written to flash 556 t = time.time() 557 558 timeout = DEFAULT_TIMEOUT 559 560 while len(image) > 0: 561 print_overwrite( 562 "Writing at 0x%08x... (%d %%)" 563 % (address + bytes_written, 100 * (seq + 1) // blocks) 564 ) 565 sys.stdout.flush() 566 block = image[0 : esp.FLASH_WRITE_SIZE] 567 if compress: 568 # feeding each compressed block into the decompressor lets us 569 # see block-by-block how much will be written 570 block_uncompressed = len(decompress.decompress(block)) 571 bytes_written += block_uncompressed 572 block_timeout = max( 573 DEFAULT_TIMEOUT, 574 timeout_per_mb(ERASE_WRITE_TIMEOUT_PER_MB, block_uncompressed), 575 ) 576 if not esp.IS_STUB: 577 timeout = ( 578 block_timeout # ROM code writes block to flash before ACKing 579 ) 580 esp.flash_defl_block(block, seq, timeout=timeout) 581 if esp.IS_STUB: 582 # Stub ACKs when block is received, 583 # then writes to flash while receiving the block after it 584 timeout = block_timeout 585 else: 586 # Pad the last block 587 block = block + b"\xff" * (esp.FLASH_WRITE_SIZE - len(block)) 588 if encrypted: 589 esp.flash_encrypt_block(block, seq) 590 else: 591 esp.flash_block(block, seq) 592 bytes_written += len(block) 593 bytes_sent += len(block) 594 image = image[esp.FLASH_WRITE_SIZE :] 595 seq += 1 596 597 if esp.IS_STUB: 598 # Stub only writes each block to flash after 'ack'ing the receive, 599 # so do a final dummy operation which will not be 'ack'ed 600 # until the last block has actually been written out to flash 601 esp.read_reg(ESPLoader.CHIP_DETECT_MAGIC_REG_ADDR, timeout=timeout) 602 603 t = time.time() - t 604 speed_msg = "" 605 if compress: 606 if t > 0.0: 607 speed_msg = " (effective %.1f kbit/s)" % (uncsize / t * 8 / 1000) 608 print_overwrite( 609 "Wrote %d bytes (%d compressed) at 0x%08x in %.1f seconds%s..." 610 % (uncsize, bytes_sent, address, t, speed_msg), 611 last_line=True, 612 ) 613 else: 614 if t > 0.0: 615 speed_msg = " (%.1f kbit/s)" % (bytes_written / t * 8 / 1000) 616 print_overwrite( 617 "Wrote %d bytes at 0x%08x in %.1f seconds%s..." 618 % (bytes_written, address, t, speed_msg), 619 last_line=True, 620 ) 621 622 if not encrypted and not esp.secure_download_mode: 623 try: 624 res = esp.flash_md5sum(address, uncsize) 625 if res != calcmd5: 626 print("File md5: %s" % calcmd5) 627 print("Flash md5: %s" % res) 628 print( 629 "MD5 of 0xFF is %s" 630 % (hashlib.md5(b"\xFF" * uncsize).hexdigest()) 631 ) 632 raise FatalError("MD5 of file does not match data in flash!") 633 else: 634 print("Hash of data verified.") 635 except NotImplementedInROMError: 636 pass 637 638 print("\nLeaving...") 639 640 if esp.IS_STUB: 641 # skip sending flash_finish to ROM loader here, 642 # as it causes the loader to exit and run user code 643 esp.flash_begin(0, 0) 644 645 # Get the "encrypted" flag for the last file flashed 646 # Note: all_files list contains triplets like: 647 # (address: Integer, filename: String, encrypted: Boolean) 648 last_file_encrypted = all_files[-1][2] 649 650 # Check whether the last file flashed was compressed or not 651 if args.compress and not last_file_encrypted: 652 esp.flash_defl_finish(False) 653 else: 654 esp.flash_finish(False) 655 656 if args.verify: 657 print("Verifying just-written flash...") 658 print( 659 "(This option is deprecated, " 660 "flash contents are now always read back after flashing.)" 661 ) 662 # If some encrypted files have been flashed, 663 # print a warning saying that we won't check them 664 if args.encrypt or args.encrypt_files is not None: 665 print("WARNING: - cannot verify encrypted files, they will be ignored") 666 # Call verify_flash function only if there is at least 667 # one non-encrypted file flashed 668 if not args.encrypt: 669 verify_flash(esp, args) 670 671 672def image_info(args): 673 def v2(): 674 def get_key_from_value(dict, val): 675 """Get key from value in dictionary""" 676 for key, value in dict.items(): 677 if value == val: 678 return key 679 return None 680 681 print() 682 title = "{} image header".format(args.chip.upper()) 683 print(title) 684 print("=" * len(title)) 685 print("Image version: {}".format(image.version)) 686 print( 687 "Entry point: {:#8x}".format(image.entrypoint) 688 if image.entrypoint != 0 689 else "Entry point not set" 690 ) 691 692 print("Segments: {}".format(len(image.segments))) 693 694 # Flash size 695 flash_s_bits = image.flash_size_freq & 0xF0 # high four bits 696 flash_s = get_key_from_value(image.ROM_LOADER.FLASH_SIZES, flash_s_bits) 697 print( 698 "Flash size: {}".format(flash_s) 699 if flash_s is not None 700 else "WARNING: Invalid flash size ({:#02x})".format(flash_s_bits) 701 ) 702 703 # Flash frequency 704 flash_fr_bits = image.flash_size_freq & 0x0F # low four bits 705 flash_fr = get_key_from_value(image.ROM_LOADER.FLASH_FREQUENCY, flash_fr_bits) 706 print( 707 "Flash freq: {}".format(flash_fr) 708 if flash_fr is not None 709 else "WARNING: Invalid flash frequency ({:#02x})".format(flash_fr_bits) 710 ) 711 712 # Flash mode 713 flash_mode = get_key_from_value(FLASH_MODES, image.flash_mode) 714 print( 715 "Flash mode: {}".format(flash_mode.upper()) 716 if flash_mode is not None 717 else "WARNING: Invalid flash mode ({})".format(image.flash_mode) 718 ) 719 720 # Extended header (ESP32 and later only) 721 if args.chip != "esp8266": 722 print() 723 title = "{} extended image header".format(args.chip.upper()) 724 print(title) 725 print("=" * len(title)) 726 print("WP pin: {:#02x}".format(image.wp_pin)) 727 print( 728 "Flash pins drive settings: " 729 "clk_drv: {:#02x}, q_drv: {:#02x}, d_drv: {:#02x}, " 730 "cs0_drv: {:#02x}, hd_drv: {:#02x}, wp_drv: {:#02x}".format( 731 image.clk_drv, 732 image.q_drv, 733 image.d_drv, 734 image.cs_drv, 735 image.hd_drv, 736 image.wp_drv, 737 ) 738 ) 739 print("Chip ID: {}".format(image.chip_id)) 740 print( 741 "Minimal chip revision: " 742 f"v{image.min_rev_full // 100}.{image.min_rev_full % 100}, " 743 f"(legacy min_rev = {image.min_rev})" 744 ) 745 print( 746 "Maximal chip revision: " 747 f"v{image.max_rev_full // 100}.{image.max_rev_full % 100}" 748 ) 749 print() 750 751 # Segments overview 752 title = "Segments information" 753 print(title) 754 print("=" * len(title)) 755 headers_str = "{:>7} {:>7} {:>10} {:>10} {:10}" 756 print( 757 headers_str.format( 758 "Segment", "Length", "Load addr", "File offs", "Memory types" 759 ) 760 ) 761 print( 762 "{} {} {} {} {}".format("-" * 7, "-" * 7, "-" * 10, "-" * 10, "-" * 12) 763 ) 764 format_str = "{:7} {:#07x} {:#010x} {:#010x} {}" 765 app_desc = None 766 for idx, seg in enumerate(image.segments, start=1): 767 segs = seg.get_memory_type(image) 768 seg_name = ", ".join(segs) 769 if "DROM" in segs: # The DROM segment starts with the esp_app_desc_t struct 770 app_desc = seg.data[:256] 771 print( 772 format_str.format(idx, len(seg.data), seg.addr, seg.file_offs, seg_name) 773 ) 774 print() 775 776 # Footer 777 title = f"{args.chip.upper()} image footer" 778 print(title) 779 print("=" * len(title)) 780 calc_checksum = image.calculate_checksum() 781 print( 782 "Checksum: {:#02x} ({})".format( 783 image.checksum, 784 "valid" 785 if image.checksum == calc_checksum 786 else "invalid - calculated {:02x}".format(calc_checksum), 787 ) 788 ) 789 try: 790 digest_msg = "Not appended" 791 if image.append_digest: 792 is_valid = image.stored_digest == image.calc_digest 793 digest_msg = "{} ({})".format( 794 hexify(image.calc_digest, uppercase=False), 795 "valid" if is_valid else "invalid", 796 ) 797 print("Validation hash: {}".format(digest_msg)) 798 except AttributeError: 799 pass # ESP8266 image has no append_digest field 800 801 if app_desc: 802 APP_DESC_STRUCT_FMT = "<II" + "8s" + "32s32s16s16s32s32s" + "80s" 803 ( 804 magic_word, 805 secure_version, 806 reserv1, 807 version, 808 project_name, 809 time, 810 date, 811 idf_ver, 812 app_elf_sha256, 813 reserv2, 814 ) = struct.unpack(APP_DESC_STRUCT_FMT, app_desc) 815 816 if magic_word == 0xABCD5432: 817 print() 818 title = "Application information" 819 print(title) 820 print("=" * len(title)) 821 print(f'Project name: {project_name.decode("utf-8")}') 822 print(f'App version: {version.decode("utf-8")}') 823 print(f'Compile time: {date.decode("utf-8")} {time.decode("utf-8")}') 824 print(f"ELF file SHA256: {hexify(app_elf_sha256, uppercase=False)}") 825 print(f'ESP-IDF: {idf_ver.decode("utf-8")}') 826 print(f"Secure version: {secure_version}") 827 828 with open(args.filename, "rb") as f: 829 # magic number 830 try: 831 common_header = f.read(8) 832 magic = common_header[0] 833 except IndexError: 834 raise FatalError("File is empty") 835 if magic not in [ 836 ESPLoader.ESP_IMAGE_MAGIC, 837 ESP8266V2FirmwareImage.IMAGE_V2_MAGIC, 838 ]: 839 raise FatalError( 840 "This is not a valid image " 841 "(invalid magic number: {:#x})".format(magic) 842 ) 843 844 if args.chip == "auto": 845 try: 846 extended_header = f.read(16) 847 # reserved fields, should all be zero 848 if int.from_bytes(extended_header[7:-1], "little") != 0: 849 raise FatalError("Reserved fields not all zero") 850 851 # append_digest, either 0 or 1 852 if extended_header[-1] not in [0, 1]: 853 raise FatalError("Append digest field not 0 or 1") 854 855 chip_id = int.from_bytes(extended_header[4:5], "little") 856 for rom in [n for n in ROM_LIST if n.CHIP_NAME != "ESP8266"]: 857 if chip_id == rom.IMAGE_CHIP_ID: 858 args.chip = rom.CHIP_NAME 859 break 860 else: 861 raise FatalError(f"Unknown image chip ID ({chip_id})") 862 except FatalError: 863 args.chip = "esp8266" 864 865 print(f"Detected image type: {args.chip.upper()}") 866 867 image = LoadFirmwareImage(args.chip, args.filename) 868 869 if args.version == "2": 870 v2() 871 return 872 873 print("Image version: {}".format(image.version)) 874 print( 875 "Entry point: {:8x}".format(image.entrypoint) 876 if image.entrypoint != 0 877 else "Entry point not set" 878 ) 879 print("{} segments".format(len(image.segments))) 880 print() 881 idx = 0 882 for seg in image.segments: 883 idx += 1 884 segs = seg.get_memory_type(image) 885 seg_name = ",".join(segs) 886 print("Segment {}: {} [{}]".format(idx, seg, seg_name)) 887 calc_checksum = image.calculate_checksum() 888 print( 889 "Checksum: {:02x} ({})".format( 890 image.checksum, 891 "valid" 892 if image.checksum == calc_checksum 893 else "invalid - calculated {:02x}".format(calc_checksum), 894 ) 895 ) 896 try: 897 digest_msg = "Not appended" 898 if image.append_digest: 899 is_valid = image.stored_digest == image.calc_digest 900 digest_msg = "{} ({})".format( 901 hexify(image.calc_digest, uppercase=False), 902 "valid" if is_valid else "invalid", 903 ) 904 print("Validation Hash: {}".format(digest_msg)) 905 except AttributeError: 906 pass # ESP8266 image has no append_digest field 907 908 909def make_image(args): 910 print("Creating {} image...".format(args.chip)) 911 image = ESP8266ROMFirmwareImage() 912 if len(args.segfile) == 0: 913 raise FatalError("No segments specified") 914 if len(args.segfile) != len(args.segaddr): 915 raise FatalError( 916 "Number of specified files does not match number of specified addresses" 917 ) 918 for seg, addr in zip(args.segfile, args.segaddr): 919 with open(seg, "rb") as f: 920 data = f.read() 921 image.segments.append(ImageSegment(addr, data)) 922 image.entrypoint = args.entrypoint 923 image.save(args.output) 924 print("Successfully created {} image.".format(args.chip)) 925 926 927def elf2image(args): 928 e = ELFFile(args.input) 929 if args.chip == "auto": # Default to ESP8266 for backwards compatibility 930 args.chip = "esp8266" 931 932 print("Creating {} image...".format(args.chip)) 933 934 if args.chip != "esp8266": 935 image = CHIP_DEFS[args.chip].BOOTLOADER_IMAGE() 936 if args.chip == "esp32" and args.secure_pad: 937 image.secure_pad = "1" 938 if args.secure_pad_v2: 939 image.secure_pad = "2" 940 image.min_rev = args.min_rev 941 image.min_rev_full = args.min_rev_full 942 image.max_rev_full = args.max_rev_full 943 image.append_digest = args.append_digest 944 elif args.version == "1": # ESP8266 945 image = ESP8266ROMFirmwareImage() 946 elif args.version == "2": 947 image = ESP8266V2FirmwareImage() 948 else: 949 image = ESP8266V3FirmwareImage() 950 image.entrypoint = e.entrypoint 951 image.flash_mode = FLASH_MODES[args.flash_mode] 952 953 if args.flash_mmu_page_size: 954 image.set_mmu_page_size(flash_size_bytes(args.flash_mmu_page_size)) 955 956 # ELFSection is a subclass of ImageSegment, so can use interchangeably 957 image.segments = e.segments if args.use_segments else e.sections 958 if args.pad_to_size: 959 image.pad_to_size = flash_size_bytes(args.pad_to_size) 960 image.flash_size_freq = image.ROM_LOADER.parse_flash_size_arg(args.flash_size) 961 image.flash_size_freq += image.ROM_LOADER.parse_flash_freq_arg(args.flash_freq) 962 963 if args.elf_sha256_offset: 964 image.elf_sha256 = e.sha256() 965 image.elf_sha256_offset = args.elf_sha256_offset 966 967 before = len(image.segments) 968 image.merge_adjacent_segments() 969 if len(image.segments) != before: 970 delta = before - len(image.segments) 971 print("Merged %d ELF section%s" % (delta, "s" if delta > 1 else "")) 972 973 image.verify() 974 975 if args.output is None: 976 args.output = image.default_output_name(args.input) 977 image.save(args.output) 978 979 print("Successfully created {} image.".format(args.chip)) 980 981 982def read_mac(esp, args): 983 mac = esp.read_mac() 984 985 def print_mac(label, mac): 986 print("%s: %s" % (label, ":".join(map(lambda x: "%02x" % x, mac)))) 987 988 print_mac("MAC", mac) 989 990 991def chip_id(esp, args): 992 try: 993 chipid = esp.chip_id() 994 print("Chip ID: 0x%08x" % chipid) 995 except NotSupportedError: 996 print("Warning: %s has no Chip ID. Reading MAC instead." % esp.CHIP_NAME) 997 read_mac(esp, args) 998 999 1000def erase_flash(esp, args): 1001 if not args.force and esp.CHIP_NAME != "ESP8266" and not esp.secure_download_mode: 1002 if esp.get_flash_encryption_enabled() or esp.get_secure_boot_enabled(): 1003 raise FatalError( 1004 "Active security features detected, " 1005 "erasing flash is disabled as a safety measure. " 1006 "Use --force to override, " 1007 "please use with caution, otherwise it may brick your device!" 1008 ) 1009 print("Erasing flash (this may take a while)...") 1010 t = time.time() 1011 esp.erase_flash() 1012 print("Chip erase completed successfully in %.1fs" % (time.time() - t)) 1013 1014 1015def erase_region(esp, args): 1016 if not args.force and esp.CHIP_NAME != "ESP8266" and not esp.secure_download_mode: 1017 if esp.get_flash_encryption_enabled() or esp.get_secure_boot_enabled(): 1018 raise FatalError( 1019 "Active security features detected, " 1020 "erasing flash is disabled as a safety measure. " 1021 "Use --force to override, " 1022 "please use with caution, otherwise it may brick your device!" 1023 ) 1024 print("Erasing region (may be slow depending on size)...") 1025 t = time.time() 1026 esp.erase_region(args.address, args.size) 1027 print("Erase completed successfully in %.1f seconds." % (time.time() - t)) 1028 1029 1030def run(esp, args): 1031 esp.run() 1032 1033 1034def flash_id(esp, args): 1035 flash_id = esp.flash_id() 1036 print("Manufacturer: %02x" % (flash_id & 0xFF)) 1037 flid_lowbyte = (flash_id >> 16) & 0xFF 1038 print("Device: %02x%02x" % ((flash_id >> 8) & 0xFF, flid_lowbyte)) 1039 print( 1040 "Detected flash size: %s" % (DETECTED_FLASH_SIZES.get(flid_lowbyte, "Unknown")) 1041 ) 1042 flash_type = esp.flash_type() 1043 flash_type_dict = {0: "quad (4 data lines)", 1: "octal (8 data lines)"} 1044 flash_type_str = flash_type_dict.get(flash_type) 1045 if flash_type_str: 1046 print(f"Flash type set in eFuse: {flash_type_str}") 1047 1048 1049def read_flash(esp, args): 1050 if args.no_progress: 1051 flash_progress = None 1052 else: 1053 1054 def flash_progress(progress, length): 1055 msg = "%d (%d %%)" % (progress, progress * 100.0 / length) 1056 padding = "\b" * len(msg) 1057 if progress == length: 1058 padding = "\n" 1059 sys.stdout.write(msg + padding) 1060 sys.stdout.flush() 1061 1062 t = time.time() 1063 data = esp.read_flash(args.address, args.size, flash_progress) 1064 t = time.time() - t 1065 speed_msg = " ({:.1f} kbit/s)".format(len(data) / t * 8 / 1000) if t > 0.0 else "" 1066 print_overwrite( 1067 "Read {:d} bytes at {:#010x} in {:.1f} seconds{}...".format( 1068 len(data), args.address, t, speed_msg 1069 ), 1070 last_line=True, 1071 ) 1072 with open(args.filename, "wb") as f: 1073 f.write(data) 1074 1075 1076def verify_flash(esp, args): 1077 differences = False 1078 1079 for address, argfile in args.addr_filename: 1080 image = pad_to(argfile.read(), 4) 1081 argfile.seek(0) # rewind in case we need it again 1082 1083 image = _update_image_flash_params(esp, address, args, image) 1084 1085 image_size = len(image) 1086 print( 1087 "Verifying 0x%x (%d) bytes @ 0x%08x in flash against %s..." 1088 % (image_size, image_size, address, argfile.name) 1089 ) 1090 # Try digest first, only read if there are differences. 1091 digest = esp.flash_md5sum(address, image_size) 1092 expected_digest = hashlib.md5(image).hexdigest() 1093 if digest == expected_digest: 1094 print("-- verify OK (digest matched)") 1095 continue 1096 else: 1097 differences = True 1098 if getattr(args, "diff", "no") != "yes": 1099 print("-- verify FAILED (digest mismatch)") 1100 continue 1101 1102 flash = esp.read_flash(address, image_size) 1103 assert flash != image 1104 diff = [i for i in range(image_size) if flash[i] != image[i]] 1105 print( 1106 "-- verify FAILED: %d differences, first @ 0x%08x" 1107 % (len(diff), address + diff[0]) 1108 ) 1109 for d in diff: 1110 flash_byte = flash[d] 1111 image_byte = image[d] 1112 print(" %08x %02x %02x" % (address + d, flash_byte, image_byte)) 1113 if differences: 1114 raise FatalError("Verify failed.") 1115 1116 1117def read_flash_status(esp, args): 1118 print("Status value: 0x%04x" % esp.read_status(args.bytes)) 1119 1120 1121def write_flash_status(esp, args): 1122 fmt = "0x%%0%dx" % (args.bytes * 2) 1123 args.value = args.value & ((1 << (args.bytes * 8)) - 1) 1124 print(("Initial flash status: " + fmt) % esp.read_status(args.bytes)) 1125 print(("Setting flash status: " + fmt) % args.value) 1126 esp.write_status(args.value, args.bytes, args.non_volatile) 1127 print(("After flash status: " + fmt) % esp.read_status(args.bytes)) 1128 1129 1130def get_security_info(esp, args): 1131 si = esp.get_security_info() 1132 # TODO: better display 1133 print("Flags: {:#010x} ({})".format(si["flags"], bin(si["flags"]))) 1134 print("Flash_Crypt_Cnt: {:#x}".format(si["flash_crypt_cnt"])) 1135 print("Key_Purposes: {}".format(si["key_purposes"])) 1136 if si["chip_id"] is not None and si["api_version"] is not None: 1137 print("Chip_ID: {}".format(si["chip_id"])) 1138 print("Api_Version: {}".format(si["api_version"])) 1139 1140 1141def merge_bin(args): 1142 try: 1143 chip_class = CHIP_DEFS[args.chip] 1144 except KeyError: 1145 msg = ( 1146 "Please specify the chip argument" 1147 if args.chip == "auto" 1148 else "Invalid chip choice: '{}'".format(args.chip) 1149 ) 1150 msg = msg + " (choose from {})".format(", ".join(CHIP_LIST)) 1151 raise FatalError(msg) 1152 1153 # sort the files by offset. 1154 # The AddrFilenamePairAction has already checked for overlap 1155 input_files = sorted(args.addr_filename, key=lambda x: x[0]) 1156 if not input_files: 1157 raise FatalError("No input files specified") 1158 first_addr = input_files[0][0] 1159 if first_addr < args.target_offset: 1160 raise FatalError( 1161 "Output file target offset is 0x%x. Input file offset 0x%x is before this." 1162 % (args.target_offset, first_addr) 1163 ) 1164 1165 if args.format != "raw": 1166 raise FatalError( 1167 "This version of esptool only supports the 'raw' output format" 1168 ) 1169 1170 with open(args.output, "wb") as of: 1171 1172 def pad_to(flash_offs): 1173 # account for output file offset if there is any 1174 of.write(b"\xFF" * (flash_offs - args.target_offset - of.tell())) 1175 1176 for addr, argfile in input_files: 1177 pad_to(addr) 1178 image = argfile.read() 1179 image = _update_image_flash_params(chip_class, addr, args, image) 1180 of.write(image) 1181 if args.fill_flash_size: 1182 pad_to(flash_size_bytes(args.fill_flash_size)) 1183 print( 1184 "Wrote 0x%x bytes to file %s, ready to flash to offset 0x%x" 1185 % (of.tell(), args.output, args.target_offset) 1186 ) 1187 1188 1189def version(args): 1190 from . import __version__ 1191 1192 print(__version__) 1193