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 # verify file sizes fit in flash 482 flash_end = flash_size_bytes( 483 detect_flash_size(esp) if args.flash_size == "keep" else args.flash_size 484 ) 485 if flash_end is not None: # Not in secure download mode 486 for address, argfile in args.addr_filename: 487 argfile.seek(0, os.SEEK_END) 488 if address + argfile.tell() > flash_end: 489 raise FatalError( 490 "File %s (length %d) at offset %d " 491 "will not fit in %d bytes of flash. " 492 "Use --flash_size argument, or change flashing address." 493 % (argfile.name, argfile.tell(), address, flash_end) 494 ) 495 argfile.seek(0) 496 497 if args.erase_all: 498 erase_flash(esp, args) 499 else: 500 for address, argfile in args.addr_filename: 501 argfile.seek(0, os.SEEK_END) 502 write_end = address + argfile.tell() 503 argfile.seek(0) 504 bytes_over = address % esp.FLASH_SECTOR_SIZE 505 if bytes_over != 0: 506 print( 507 "WARNING: Flash address {:#010x} is not aligned " 508 "to a {:#x} byte flash sector. " 509 "{:#x} bytes before this address will be erased.".format( 510 address, esp.FLASH_SECTOR_SIZE, bytes_over 511 ) 512 ) 513 # Print the address range of to-be-erased flash memory region 514 print( 515 "Flash will be erased from {:#010x} to {:#010x}...".format( 516 address - bytes_over, 517 div_roundup(write_end, esp.FLASH_SECTOR_SIZE) 518 * esp.FLASH_SECTOR_SIZE 519 - 1, 520 ) 521 ) 522 523 """ Create a list describing all the files we have to flash. 524 Each entry holds an "encrypt" flag marking whether the file needs encryption or not. 525 This list needs to be sorted. 526 527 First, append to each entry of our addr_filename list the flag args.encrypt 528 E.g., if addr_filename is [(0x1000, "partition.bin"), (0x8000, "bootloader")], 529 all_files will be [ 530 (0x1000, "partition.bin", args.encrypt), 531 (0x8000, "bootloader", args.encrypt) 532 ], 533 where, of course, args.encrypt is either True or False 534 """ 535 all_files = [ 536 (offs, filename, args.encrypt) for (offs, filename) in args.addr_filename 537 ] 538 539 """ 540 Now do the same with encrypt_files list, if defined. 541 In this case, the flag is True 542 """ 543 if args.encrypt_files is not None: 544 encrypted_files_flag = [ 545 (offs, filename, True) for (offs, filename) in args.encrypt_files 546 ] 547 548 # Concatenate both lists and sort them. 549 # As both list are already sorted, we could simply do a merge instead, 550 # but for the sake of simplicity and because the lists are very small, 551 # let's use sorted. 552 all_files = sorted(all_files + encrypted_files_flag, key=lambda x: x[0]) 553 554 for address, argfile, encrypted in all_files: 555 compress = args.compress 556 557 # Check whether we can compress the current file before flashing 558 if compress and encrypted: 559 print("\nWARNING: - compress and encrypt options are mutually exclusive ") 560 print("Will flash %s uncompressed" % argfile.name) 561 compress = False 562 563 if args.no_stub: 564 print("Erasing flash...") 565 image = pad_to( 566 argfile.read(), esp.FLASH_ENCRYPTED_WRITE_ALIGN if encrypted else 4 567 ) 568 if len(image) == 0: 569 print("WARNING: File %s is empty" % argfile.name) 570 continue 571 572 if not esp.secure_download_mode and not esp.get_secure_boot_enabled(): 573 image = _update_image_flash_params(esp, address, args, image) 574 else: 575 print( 576 "WARNING: Security features enabled, so not changing any flash settings." 577 ) 578 calcmd5 = hashlib.md5(image).hexdigest() 579 uncsize = len(image) 580 if compress: 581 uncimage = image 582 image = zlib.compress(uncimage, 9) 583 original_image = image # Save the whole image in case retry is needed 584 # Try again if reconnect was successful 585 for attempt in range(1, esp.WRITE_FLASH_ATTEMPTS + 1): 586 try: 587 if compress: 588 # Decompress the compressed binary a block at a time, 589 # to dynamically calculate the timeout based on the real write size 590 decompress = zlib.decompressobj() 591 blocks = esp.flash_defl_begin(uncsize, len(image), address) 592 else: 593 blocks = esp.flash_begin( 594 uncsize, address, begin_rom_encrypted=encrypted 595 ) 596 argfile.seek(0) # in case we need it again 597 seq = 0 598 bytes_sent = 0 # bytes sent on wire 599 bytes_written = 0 # bytes written to flash 600 t = time.time() 601 602 timeout = DEFAULT_TIMEOUT 603 604 while len(image) > 0: 605 print_overwrite( 606 "Writing at 0x%08x... (%d %%)" 607 % (address + bytes_written, 100 * (seq + 1) // blocks) 608 ) 609 sys.stdout.flush() 610 block = image[0 : esp.FLASH_WRITE_SIZE] 611 if compress: 612 # feeding each compressed block into the decompressor lets us 613 # see block-by-block how much will be written 614 block_uncompressed = len(decompress.decompress(block)) 615 bytes_written += block_uncompressed 616 block_timeout = max( 617 DEFAULT_TIMEOUT, 618 timeout_per_mb( 619 ERASE_WRITE_TIMEOUT_PER_MB, block_uncompressed 620 ), 621 ) 622 if not esp.IS_STUB: 623 timeout = block_timeout # ROM code writes block to flash before ACKing 624 esp.flash_defl_block(block, seq, timeout=timeout) 625 if esp.IS_STUB: 626 # Stub ACKs when block is received, 627 # then writes to flash while receiving the block after it 628 timeout = block_timeout 629 else: 630 # Pad the last block 631 block = block + b"\xff" * (esp.FLASH_WRITE_SIZE - len(block)) 632 if encrypted: 633 esp.flash_encrypt_block(block, seq) 634 else: 635 esp.flash_block(block, seq) 636 bytes_written += len(block) 637 bytes_sent += len(block) 638 image = image[esp.FLASH_WRITE_SIZE :] 639 seq += 1 640 break 641 except SerialException: 642 if attempt == esp.WRITE_FLASH_ATTEMPTS or encrypted: 643 # Already retried once or encrypted mode is disabled because of security reasons 644 raise 645 print("\nLost connection, retrying...") 646 esp._port.close() 647 print("Waiting for the chip to reconnect", end="") 648 for _ in range(DEFAULT_CONNECT_ATTEMPTS): 649 try: 650 time.sleep(1) 651 esp._port.open() 652 print() # Print new line which was suppressed by print(".") 653 esp.connect() 654 if esp.IS_STUB: 655 # Hack to bypass the stub overwrite check 656 esp.IS_STUB = False 657 # Reflash stub because chip was reset 658 esp = esp.run_stub() 659 image = original_image 660 break 661 except SerialException: 662 print(".", end="") 663 sys.stdout.flush() 664 else: 665 raise # Reconnect limit reached 666 667 if esp.IS_STUB: 668 # Stub only writes each block to flash after 'ack'ing the receive, 669 # so do a final dummy operation which will not be 'ack'ed 670 # until the last block has actually been written out to flash 671 esp.read_reg(ESPLoader.CHIP_DETECT_MAGIC_REG_ADDR, timeout=timeout) 672 673 t = time.time() - t 674 speed_msg = "" 675 if compress: 676 if t > 0.0: 677 speed_msg = " (effective %.1f kbit/s)" % (uncsize / t * 8 / 1000) 678 print_overwrite( 679 "Wrote %d bytes (%d compressed) at 0x%08x in %.1f seconds%s..." 680 % (uncsize, bytes_sent, address, t, speed_msg), 681 last_line=True, 682 ) 683 else: 684 if t > 0.0: 685 speed_msg = " (%.1f kbit/s)" % (bytes_written / t * 8 / 1000) 686 print_overwrite( 687 "Wrote %d bytes at 0x%08x in %.1f seconds%s..." 688 % (bytes_written, address, t, speed_msg), 689 last_line=True, 690 ) 691 692 if not encrypted and not esp.secure_download_mode: 693 try: 694 res = esp.flash_md5sum(address, uncsize) 695 if res != calcmd5: 696 print("File md5: %s" % calcmd5) 697 print("Flash md5: %s" % res) 698 print( 699 "MD5 of 0xFF is %s" 700 % (hashlib.md5(b"\xff" * uncsize).hexdigest()) 701 ) 702 raise FatalError("MD5 of file does not match data in flash!") 703 else: 704 print("Hash of data verified.") 705 except NotImplementedInROMError: 706 pass 707 708 print("\nLeaving...") 709 710 if esp.IS_STUB: 711 # skip sending flash_finish to ROM loader here, 712 # as it causes the loader to exit and run user code 713 esp.flash_begin(0, 0) 714 715 # Get the "encrypted" flag for the last file flashed 716 # Note: all_files list contains triplets like: 717 # (address: Integer, filename: String, encrypted: Boolean) 718 last_file_encrypted = all_files[-1][2] 719 720 # Check whether the last file flashed was compressed or not 721 if args.compress and not last_file_encrypted: 722 esp.flash_defl_finish(False) 723 else: 724 esp.flash_finish(False) 725 726 if args.verify: 727 print("Verifying just-written flash...") 728 print( 729 "(This option is deprecated, " 730 "flash contents are now always read back after flashing.)" 731 ) 732 # If some encrypted files have been flashed, 733 # print a warning saying that we won't check them 734 if args.encrypt or args.encrypt_files is not None: 735 print("WARNING: - cannot verify encrypted files, they will be ignored") 736 # Call verify_flash function only if there is at least 737 # one non-encrypted file flashed 738 if not args.encrypt: 739 verify_flash(esp, args) 740 741 742def image_info(args): 743 def v2(): 744 def get_key_from_value(dict, val): 745 """Get key from value in dictionary""" 746 for key, value in dict.items(): 747 if value == val: 748 return key 749 return None 750 751 print() 752 title = "{} image header".format(args.chip.upper()) 753 print(title) 754 print("=" * len(title)) 755 print("Image version: {}".format(image.version)) 756 print( 757 "Entry point: {:#8x}".format(image.entrypoint) 758 if image.entrypoint != 0 759 else "Entry point not set" 760 ) 761 762 print("Segments: {}".format(len(image.segments))) 763 764 # Flash size 765 flash_s_bits = image.flash_size_freq & 0xF0 # high four bits 766 flash_s = get_key_from_value(image.ROM_LOADER.FLASH_SIZES, flash_s_bits) 767 print( 768 "Flash size: {}".format(flash_s) 769 if flash_s is not None 770 else "WARNING: Invalid flash size ({:#02x})".format(flash_s_bits) 771 ) 772 773 # Flash frequency 774 flash_fr_bits = image.flash_size_freq & 0x0F # low four bits 775 flash_fr = get_key_from_value(image.ROM_LOADER.FLASH_FREQUENCY, flash_fr_bits) 776 print( 777 "Flash freq: {}".format(flash_fr) 778 if flash_fr is not None 779 else "WARNING: Invalid flash frequency ({:#02x})".format(flash_fr_bits) 780 ) 781 782 # Flash mode 783 flash_mode = get_key_from_value(FLASH_MODES, image.flash_mode) 784 print( 785 "Flash mode: {}".format(flash_mode.upper()) 786 if flash_mode is not None 787 else "WARNING: Invalid flash mode ({})".format(image.flash_mode) 788 ) 789 790 # Extended header (ESP32 and later only) 791 if args.chip != "esp8266": 792 print() 793 title = "{} extended image header".format(args.chip.upper()) 794 print(title) 795 print("=" * len(title)) 796 print( 797 f"WP pin: {image.wp_pin:#02x}", 798 *["(disabled)"] if image.wp_pin == image.WP_PIN_DISABLED else [], 799 ) 800 print( 801 "Flash pins drive settings: " 802 "clk_drv: {:#02x}, q_drv: {:#02x}, d_drv: {:#02x}, " 803 "cs0_drv: {:#02x}, hd_drv: {:#02x}, wp_drv: {:#02x}".format( 804 image.clk_drv, 805 image.q_drv, 806 image.d_drv, 807 image.cs_drv, 808 image.hd_drv, 809 image.wp_drv, 810 ) 811 ) 812 try: 813 chip = next( 814 chip 815 for chip in CHIP_DEFS.values() 816 if getattr(chip, "IMAGE_CHIP_ID", None) == image.chip_id 817 ) 818 print(f"Chip ID: {image.chip_id} ({chip.CHIP_NAME})") 819 except StopIteration: 820 print(f"Chip ID: {image.chip_id} (Unknown ID)") 821 print( 822 "Minimal chip revision: " 823 f"v{image.min_rev_full // 100}.{image.min_rev_full % 100}, " 824 f"(legacy min_rev = {image.min_rev})" 825 ) 826 print( 827 "Maximal chip revision: " 828 f"v{image.max_rev_full // 100}.{image.max_rev_full % 100}" 829 ) 830 print() 831 832 # Segments overview 833 title = "Segments information" 834 print(title) 835 print("=" * len(title)) 836 headers_str = "{:>7} {:>7} {:>10} {:>10} {:10}" 837 print( 838 headers_str.format( 839 "Segment", "Length", "Load addr", "File offs", "Memory types" 840 ) 841 ) 842 print( 843 "{} {} {} {} {}".format("-" * 7, "-" * 7, "-" * 10, "-" * 10, "-" * 12) 844 ) 845 format_str = "{:7} {:#07x} {:#010x} {:#010x} {}" 846 app_desc = None 847 bootloader_desc = None 848 for idx, seg in enumerate(image.segments): 849 segs = seg.get_memory_type(image) 850 seg_name = ", ".join(segs) 851 if "DROM" in segs: # The DROM segment starts with the esp_app_desc_t struct 852 app_desc = seg.data[:256] 853 elif "DRAM" in segs: 854 # The DRAM segment starts with the esp_bootloader_desc_t struct 855 if len(seg.data) >= 80: 856 bootloader_desc = seg.data[:80] 857 print( 858 format_str.format(idx, len(seg.data), seg.addr, seg.file_offs, seg_name) 859 ) 860 print() 861 862 # Footer 863 title = f"{args.chip.upper()} image footer" 864 print(title) 865 print("=" * len(title)) 866 calc_checksum = image.calculate_checksum() 867 print( 868 "Checksum: {:#02x} ({})".format( 869 image.checksum, 870 ( 871 "valid" 872 if image.checksum == calc_checksum 873 else "invalid - calculated {:02x}".format(calc_checksum) 874 ), 875 ) 876 ) 877 try: 878 digest_msg = "Not appended" 879 if image.append_digest: 880 is_valid = image.stored_digest == image.calc_digest 881 digest_msg = "{} ({})".format( 882 hexify(image.calc_digest, uppercase=False), 883 "valid" if is_valid else "invalid", 884 ) 885 print("Validation hash: {}".format(digest_msg)) 886 except AttributeError: 887 pass # ESP8266 image has no append_digest field 888 889 if app_desc: 890 APP_DESC_STRUCT_FMT = "<II" + "8s" + "32s32s16s16s32s32s" + "80s" 891 ( 892 magic_word, 893 secure_version, 894 reserv1, 895 version, 896 project_name, 897 time, 898 date, 899 idf_ver, 900 app_elf_sha256, 901 reserv2, 902 ) = struct.unpack(APP_DESC_STRUCT_FMT, app_desc) 903 904 if magic_word == 0xABCD5432: 905 print() 906 title = "Application information" 907 print(title) 908 print("=" * len(title)) 909 print(f'Project name: {project_name.decode("utf-8")}') 910 print(f'App version: {version.decode("utf-8")}') 911 print(f'Compile time: {date.decode("utf-8")} {time.decode("utf-8")}') 912 print(f"ELF file SHA256: {hexify(app_elf_sha256, uppercase=False)}") 913 print(f'ESP-IDF: {idf_ver.decode("utf-8")}') 914 print(f"Secure version: {secure_version}") 915 916 elif bootloader_desc: 917 BOOTLOADER_DESC_STRUCT_FMT = "<B" + "3s" + "I32s24s" + "16s" 918 ( 919 magic_byte, 920 reserved, 921 version, 922 idf_ver, 923 date_time, 924 reserved2, 925 ) = struct.unpack(BOOTLOADER_DESC_STRUCT_FMT, bootloader_desc) 926 927 if magic_byte == 80: 928 print() 929 title = "Bootloader information" 930 print(title) 931 print("=" * len(title)) 932 print(f"Bootloader version: {version}") 933 print(f'ESP-IDF: {idf_ver.decode("utf-8")}') 934 print(f'Compile time: {date_time.decode("utf-8")}') 935 936 print(f"File size: {get_file_size(args.filename)} (bytes)") 937 with open(args.filename, "rb") as f: 938 # magic number 939 try: 940 common_header = f.read(8) 941 magic = common_header[0] 942 except IndexError: 943 raise FatalError("File is empty") 944 if magic not in [ 945 ESPLoader.ESP_IMAGE_MAGIC, 946 ESP8266V2FirmwareImage.IMAGE_V2_MAGIC, 947 ]: 948 raise FatalError( 949 "This is not a valid image " "(invalid magic number: {:#x})".format( 950 magic 951 ) 952 ) 953 954 if args.chip == "auto": 955 try: 956 extended_header = f.read(16) 957 958 # append_digest, either 0 or 1 959 if extended_header[-1] not in [0, 1]: 960 raise FatalError("Append digest field not 0 or 1") 961 962 chip_id = int.from_bytes(extended_header[4:5], "little") 963 for rom in [n for n in ROM_LIST if n.CHIP_NAME != "ESP8266"]: 964 if chip_id == rom.IMAGE_CHIP_ID: 965 args.chip = rom.CHIP_NAME 966 break 967 else: 968 raise FatalError(f"Unknown image chip ID ({chip_id})") 969 except FatalError: 970 args.chip = "esp8266" 971 972 print(f"Detected image type: {args.chip.upper()}") 973 974 image = LoadFirmwareImage(args.chip, args.filename) 975 976 if args.version == "2": 977 v2() 978 return 979 980 print("Image version: {}".format(image.version)) 981 print( 982 "Entry point: {:8x}".format(image.entrypoint) 983 if image.entrypoint != 0 984 else "Entry point not set" 985 ) 986 print("{} segments".format(len(image.segments))) 987 print() 988 idx = 0 989 for seg in image.segments: 990 idx += 1 991 segs = seg.get_memory_type(image) 992 seg_name = ",".join(segs) 993 print("Segment {}: {} [{}]".format(idx, seg, seg_name)) 994 calc_checksum = image.calculate_checksum() 995 print( 996 "Checksum: {:02x} ({})".format( 997 image.checksum, 998 ( 999 "valid" 1000 if image.checksum == calc_checksum 1001 else "invalid - calculated {:02x}".format(calc_checksum) 1002 ), 1003 ) 1004 ) 1005 try: 1006 digest_msg = "Not appended" 1007 if image.append_digest: 1008 is_valid = image.stored_digest == image.calc_digest 1009 digest_msg = "{} ({})".format( 1010 hexify(image.calc_digest, uppercase=False), 1011 "valid" if is_valid else "invalid", 1012 ) 1013 print("Validation Hash: {}".format(digest_msg)) 1014 except AttributeError: 1015 pass # ESP8266 image has no append_digest field 1016 1017 1018def make_image(args): 1019 print("Creating {} image...".format(args.chip)) 1020 image = ESP8266ROMFirmwareImage() 1021 if len(args.segfile) == 0: 1022 raise FatalError("No segments specified") 1023 if len(args.segfile) != len(args.segaddr): 1024 raise FatalError( 1025 "Number of specified files does not match number of specified addresses" 1026 ) 1027 for seg, addr in zip(args.segfile, args.segaddr): 1028 with open(seg, "rb") as f: 1029 data = f.read() 1030 image.segments.append(ImageSegment(addr, data)) 1031 image.entrypoint = args.entrypoint 1032 image.save(args.output) 1033 print("Successfully created {} image.".format(args.chip)) 1034 1035 1036def elf2image(args): 1037 e = ELFFile(args.input) 1038 if args.chip == "auto": # Default to ESP8266 for backwards compatibility 1039 args.chip = "esp8266" 1040 1041 print("Creating {} image...".format(args.chip)) 1042 1043 if args.chip != "esp8266": 1044 image = CHIP_DEFS[args.chip].BOOTLOADER_IMAGE() 1045 if args.chip == "esp32" and args.secure_pad: 1046 image.secure_pad = "1" 1047 if args.secure_pad_v2: 1048 image.secure_pad = "2" 1049 image.min_rev = args.min_rev 1050 image.min_rev_full = args.min_rev_full 1051 image.max_rev_full = args.max_rev_full 1052 image.ram_only_header = args.ram_only_header 1053 if image.ram_only_header: 1054 image.append_digest = False 1055 else: 1056 image.append_digest = args.append_digest 1057 elif args.version == "1": # ESP8266 1058 image = ESP8266ROMFirmwareImage() 1059 elif args.version == "2": 1060 image = ESP8266V2FirmwareImage() 1061 else: 1062 image = ESP8266V3FirmwareImage() 1063 image.entrypoint = e.entrypoint 1064 image.flash_mode = FLASH_MODES[args.flash_mode] 1065 1066 if args.flash_mmu_page_size: 1067 image.set_mmu_page_size(flash_size_bytes(args.flash_mmu_page_size)) 1068 1069 # ELFSection is a subclass of ImageSegment, so can use interchangeably 1070 image.segments = e.segments if args.use_segments else e.sections 1071 if args.pad_to_size: 1072 image.pad_to_size = flash_size_bytes(args.pad_to_size) 1073 image.flash_size_freq = image.ROM_LOADER.parse_flash_size_arg(args.flash_size) 1074 image.flash_size_freq += image.ROM_LOADER.parse_flash_freq_arg(args.flash_freq) 1075 1076 if args.elf_sha256_offset: 1077 image.elf_sha256 = e.sha256() 1078 image.elf_sha256_offset = args.elf_sha256_offset 1079 1080 if args.ram_only_header: 1081 print( 1082 "Image has only RAM segments visible. " 1083 "ROM segments are hidden and SHA256 digest is not appended." 1084 ) 1085 image.sort_segments() 1086 1087 before = len(image.segments) 1088 image.merge_adjacent_segments() 1089 if len(image.segments) != before: 1090 delta = before - len(image.segments) 1091 print("Merged %d ELF section%s" % (delta, "s" if delta > 1 else "")) 1092 1093 image.verify() 1094 1095 if args.output is None: 1096 args.output = image.default_output_name(args.input) 1097 image.save(args.output) 1098 1099 print("Successfully created {} image.".format(args.chip)) 1100 1101 1102def read_mac(esp, args): 1103 def print_mac(label, mac): 1104 print("%s: %s" % (label, ":".join(map(lambda x: "%02x" % x, mac)))) 1105 1106 eui64 = esp.read_mac("EUI64") 1107 if eui64: 1108 print_mac("MAC", eui64) 1109 print_mac("BASE MAC", esp.read_mac("BASE_MAC")) 1110 print_mac("MAC_EXT", esp.read_mac("MAC_EXT")) 1111 else: 1112 print_mac("MAC", esp.read_mac("BASE_MAC")) 1113 1114 1115def chip_id(esp, args): 1116 try: 1117 chipid = esp.chip_id() 1118 print("Chip ID: 0x%08x" % chipid) 1119 except NotSupportedError: 1120 print("Warning: %s has no Chip ID. Reading MAC instead." % esp.CHIP_NAME) 1121 read_mac(esp, args) 1122 1123 1124def erase_flash(esp, args): 1125 if not args.force and esp.CHIP_NAME != "ESP8266" and not esp.secure_download_mode: 1126 if esp.get_flash_encryption_enabled() or esp.get_secure_boot_enabled(): 1127 raise FatalError( 1128 "Active security features detected, " 1129 "erasing flash is disabled as a safety measure. " 1130 "Use --force to override, " 1131 "please use with caution, otherwise it may brick your device!" 1132 ) 1133 print("Erasing flash (this may take a while)...") 1134 t = time.time() 1135 esp.erase_flash() 1136 print("Chip erase completed successfully in %.1fs" % (time.time() - t)) 1137 1138 1139def erase_region(esp, args): 1140 if not args.force and esp.CHIP_NAME != "ESP8266" and not esp.secure_download_mode: 1141 if esp.get_flash_encryption_enabled() or esp.get_secure_boot_enabled(): 1142 raise FatalError( 1143 "Active security features detected, " 1144 "erasing flash is disabled as a safety measure. " 1145 "Use --force to override, " 1146 "please use with caution, otherwise it may brick your device!" 1147 ) 1148 print("Erasing region (may be slow depending on size)...") 1149 t = time.time() 1150 esp.erase_region(args.address, args.size) 1151 print("Erase completed successfully in %.1f seconds." % (time.time() - t)) 1152 1153 1154def run(esp, args): 1155 esp.run() 1156 1157 1158def flash_id(esp, args): 1159 flash_id = esp.flash_id() 1160 print("Manufacturer: %02x" % (flash_id & 0xFF)) 1161 flid_lowbyte = (flash_id >> 16) & 0xFF 1162 print("Device: %02x%02x" % ((flash_id >> 8) & 0xFF, flid_lowbyte)) 1163 print( 1164 "Detected flash size: %s" % (DETECTED_FLASH_SIZES.get(flid_lowbyte, "Unknown")) 1165 ) 1166 flash_type = esp.flash_type() 1167 flash_type_dict = {0: "quad (4 data lines)", 1: "octal (8 data lines)"} 1168 flash_type_str = flash_type_dict.get(flash_type) 1169 if flash_type_str: 1170 print(f"Flash type set in eFuse: {flash_type_str}") 1171 esp.get_flash_voltage() 1172 1173 1174def read_flash(esp, args): 1175 if args.no_progress: 1176 flash_progress = None 1177 else: 1178 1179 def flash_progress(progress, length): 1180 msg = "%d (%d %%)" % (progress, progress * 100.0 / length) 1181 padding = "\b" * len(msg) 1182 if progress == length: 1183 padding = "\n" 1184 sys.stdout.write(msg + padding) 1185 sys.stdout.flush() 1186 1187 t = time.time() 1188 data = esp.read_flash(args.address, args.size, flash_progress) 1189 t = time.time() - t 1190 speed_msg = " ({:.1f} kbit/s)".format(len(data) / t * 8 / 1000) if t > 0.0 else "" 1191 print_overwrite( 1192 "Read {:d} bytes at {:#010x} in {:.1f} seconds{}...".format( 1193 len(data), args.address, t, speed_msg 1194 ), 1195 last_line=True, 1196 ) 1197 with open(args.filename, "wb") as f: 1198 f.write(data) 1199 1200 1201def verify_flash(esp, args): 1202 differences = False 1203 1204 for address, argfile in args.addr_filename: 1205 image = pad_to(argfile.read(), 4) 1206 argfile.seek(0) # rewind in case we need it again 1207 1208 image = _update_image_flash_params(esp, address, args, image) 1209 1210 image_size = len(image) 1211 print( 1212 "Verifying 0x%x (%d) bytes @ 0x%08x in flash against %s..." 1213 % (image_size, image_size, address, argfile.name) 1214 ) 1215 # Try digest first, only read if there are differences. 1216 digest = esp.flash_md5sum(address, image_size) 1217 expected_digest = hashlib.md5(image).hexdigest() 1218 if digest == expected_digest: 1219 print("-- verify OK (digest matched)") 1220 continue 1221 else: 1222 differences = True 1223 if getattr(args, "diff", "no") != "yes": 1224 print("-- verify FAILED (digest mismatch)") 1225 continue 1226 1227 flash = esp.read_flash(address, image_size) 1228 assert flash != image 1229 diff = [i for i in range(image_size) if flash[i] != image[i]] 1230 print( 1231 "-- verify FAILED: %d differences, first @ 0x%08x" 1232 % (len(diff), address + diff[0]) 1233 ) 1234 for d in diff: 1235 flash_byte = flash[d] 1236 image_byte = image[d] 1237 print(" %08x %02x %02x" % (address + d, flash_byte, image_byte)) 1238 if differences: 1239 raise FatalError("Verify failed.") 1240 1241 1242def read_flash_status(esp, args): 1243 print("Status value: 0x%04x" % esp.read_status(args.bytes)) 1244 1245 1246def write_flash_status(esp, args): 1247 fmt = "0x%%0%dx" % (args.bytes * 2) 1248 args.value = args.value & ((1 << (args.bytes * 8)) - 1) 1249 print(("Initial flash status: " + fmt) % esp.read_status(args.bytes)) 1250 print(("Setting flash status: " + fmt) % args.value) 1251 esp.write_status(args.value, args.bytes, args.non_volatile) 1252 print(("After flash status: " + fmt) % esp.read_status(args.bytes)) 1253 1254 1255# The following mapping was taken from the ROM code 1256# This mapping is same across all targets in the ROM 1257SECURITY_INFO_FLAG_MAP = { 1258 "SECURE_BOOT_EN": (1 << 0), 1259 "SECURE_BOOT_AGGRESSIVE_REVOKE": (1 << 1), 1260 "SECURE_DOWNLOAD_ENABLE": (1 << 2), 1261 "SECURE_BOOT_KEY_REVOKE0": (1 << 3), 1262 "SECURE_BOOT_KEY_REVOKE1": (1 << 4), 1263 "SECURE_BOOT_KEY_REVOKE2": (1 << 5), 1264 "SOFT_DIS_JTAG": (1 << 6), 1265 "HARD_DIS_JTAG": (1 << 7), 1266 "DIS_USB": (1 << 8), 1267 "DIS_DOWNLOAD_DCACHE": (1 << 9), 1268 "DIS_DOWNLOAD_ICACHE": (1 << 10), 1269} 1270 1271 1272# Get the status of respective security flag 1273def get_security_flag_status(flag_name, flags_value): 1274 try: 1275 return (flags_value & SECURITY_INFO_FLAG_MAP[flag_name]) != 0 1276 except KeyError: 1277 raise ValueError(f"Invalid flag name: {flag_name}") 1278 1279 1280def get_security_info(esp, args): 1281 si = esp.get_security_info() 1282 print() 1283 title = "Security Information:" 1284 print(title) 1285 print("=" * len(title)) 1286 print("Flags: {:#010x} ({})".format(si["flags"], bin(si["flags"]))) 1287 print("Key Purposes: {}".format(si["key_purposes"])) 1288 if si["chip_id"] is not None and si["api_version"] is not None: 1289 print("Chip ID: {}".format(si["chip_id"])) 1290 print("API Version: {}".format(si["api_version"])) 1291 1292 flags = si["flags"] 1293 1294 if get_security_flag_status("SECURE_BOOT_EN", flags): 1295 print("Secure Boot: Enabled") 1296 if get_security_flag_status("SECURE_BOOT_AGGRESSIVE_REVOKE", flags): 1297 print("Secure Boot Aggressive key revocation: Enabled") 1298 1299 revoked_keys = [] 1300 for i, key in enumerate( 1301 [ 1302 "SECURE_BOOT_KEY_REVOKE0", 1303 "SECURE_BOOT_KEY_REVOKE1", 1304 "SECURE_BOOT_KEY_REVOKE2", 1305 ] 1306 ): 1307 if get_security_flag_status(key, flags): 1308 revoked_keys.append(i) 1309 1310 if len(revoked_keys) > 0: 1311 print("Secure Boot Key Revocation Status:\n") 1312 for i in revoked_keys: 1313 print(f"\tSecure Boot Key{i} is Revoked\n") 1314 1315 else: 1316 print("Secure Boot: Disabled") 1317 1318 flash_crypt_cnt = bin(si["flash_crypt_cnt"]) 1319 if (flash_crypt_cnt.count("1") % 2) != 0: 1320 print("Flash Encryption: Enabled") 1321 else: 1322 print("Flash Encryption: Disabled") 1323 1324 CRYPT_CNT_STRING = "SPI Boot Crypt Count (SPI_BOOT_CRYPT_CNT)" 1325 if esp.CHIP_NAME == "esp32": 1326 CRYPT_CNT_STRING = "Flash Crypt Count (FLASH_CRYPT_CNT)" 1327 1328 print(f"{CRYPT_CNT_STRING}: {si['flash_crypt_cnt']:#x}") 1329 1330 if get_security_flag_status("DIS_DOWNLOAD_DCACHE", flags): 1331 print("Dcache in UART download mode: Disabled") 1332 1333 if get_security_flag_status("DIS_DOWNLOAD_ICACHE", flags): 1334 print("Icache in UART download mode: Disabled") 1335 1336 hard_dis_jtag = get_security_flag_status("HARD_DIS_JTAG", flags) 1337 soft_dis_jtag = get_security_flag_status("SOFT_DIS_JTAG", flags) 1338 if hard_dis_jtag: 1339 print("JTAG: Permanently Disabled") 1340 elif soft_dis_jtag: 1341 print("JTAG: Software Access Disabled") 1342 if get_security_flag_status("DIS_USB", flags): 1343 print("USB Access: Disabled") 1344 1345 1346def merge_bin(args): 1347 try: 1348 chip_class = CHIP_DEFS[args.chip] 1349 except KeyError: 1350 msg = ( 1351 "Please specify the chip argument" 1352 if args.chip == "auto" 1353 else f"Invalid chip choice: '{args.chip}'" 1354 ) 1355 msg = f"{msg} (choose from {', '.join(CHIP_LIST)})" 1356 raise FatalError(msg) 1357 1358 # sort the files by offset. 1359 # The AddrFilenamePairAction has already checked for overlap 1360 input_files = sorted(args.addr_filename, key=lambda x: x[0]) 1361 if not input_files: 1362 raise FatalError("No input files specified") 1363 first_addr = input_files[0][0] 1364 if first_addr < args.target_offset: 1365 raise FatalError( 1366 f"Output file target offset is {args.target_offset:#x}. " 1367 f"Input file offset {first_addr:#x} is before this." 1368 ) 1369 1370 if args.format == "uf2": 1371 with UF2Writer( 1372 chip_class.UF2_FAMILY_ID, 1373 args.output, 1374 args.chunk_size, 1375 md5_enabled=not args.md5_disable, 1376 ) as writer: 1377 for addr, argfile in input_files: 1378 print(f"Adding {argfile.name} at {addr:#x}") 1379 image = argfile.read() 1380 image = _update_image_flash_params(chip_class, addr, args, image) 1381 writer.add_file(addr, image) 1382 print( 1383 f"Wrote {os.path.getsize(args.output):#x} bytes to file {args.output}, " 1384 f"ready to be flashed with any ESP USB Bridge" 1385 ) 1386 1387 elif args.format == "raw": 1388 with open(args.output, "wb") as of: 1389 1390 def pad_to(flash_offs): 1391 # account for output file offset if there is any 1392 of.write(b"\xff" * (flash_offs - args.target_offset - of.tell())) 1393 1394 for addr, argfile in input_files: 1395 pad_to(addr) 1396 image = argfile.read() 1397 image = _update_image_flash_params(chip_class, addr, args, image) 1398 of.write(image) 1399 if args.fill_flash_size: 1400 pad_to(flash_size_bytes(args.fill_flash_size)) 1401 print( 1402 f"Wrote {of.tell():#x} bytes to file {args.output}, " 1403 f"ready to flash to offset {args.target_offset:#x}" 1404 ) 1405 elif args.format == "hex": 1406 out = IntelHex() 1407 for addr, argfile in input_files: 1408 ihex = IntelHex() 1409 image = argfile.read() 1410 image = _update_image_flash_params(chip_class, addr, args, image) 1411 ihex.frombytes(image, addr) 1412 out.merge(ihex) 1413 out.write_hex_file(args.output) 1414 print( 1415 f"Wrote {os.path.getsize(args.output):#x} bytes to file {args.output}, " 1416 f"ready to flash to offset {args.target_offset:#x}" 1417 ) 1418 1419 1420def version(args): 1421 from . import __version__ 1422 1423 print(__version__) 1424