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