diff --git a/tools/python/esptool/__init__.py b/tools/python/esptool/__init__.py index 2d195155..f95744cc 100644 --- a/tools/python/esptool/__init__.py +++ b/tools/python/esptool/__init__.py @@ -28,7 +28,7 @@ __all__ = [ "write_mem", ] -__version__ = "4.6.2" +__version__ = "4.7.0" import argparse import inspect @@ -38,6 +38,7 @@ import sys import time import traceback +from bin_image import intel_hex_to_bin from cmds import ( DETECTED_FLASH_SIZES, chip_id, @@ -176,16 +177,18 @@ def main(argv=None, esp=None): parent.add_argument( "--spi-connection", "-sc", - help="ESP32-only argument. Override default SPI Flash connection. " + help="Override default SPI Flash connection. " "Value can be SPI, HSPI or a comma-separated list of 5 I/O numbers " - "to use for SPI flash (CLK,Q,D,HD,CS).", + "to use for SPI flash (CLK,Q,D,HD,CS). Not supported with ESP8266.", action=SpiConnectionAction, ) parser_load_ram = subparsers.add_parser( "load_ram", help="Download an image to RAM and execute" ) - parser_load_ram.add_argument("filename", help="Firmware image") + parser_load_ram.add_argument( + "filename", help="Firmware image", action=AutoHex2BinAction + ) parser_dump_mem = subparsers.add_parser( "dump_mem", help="Dump arbitrary memory to disk" @@ -357,7 +360,9 @@ def main(argv=None, esp=None): parser_image_info = subparsers.add_parser( "image_info", help="Dump headers from a binary file (bootloader or application)" ) - parser_image_info.add_argument("filename", help="Image file to parse") + parser_image_info.add_argument( + "filename", help="Image file to parse", action=AutoHex2BinAction + ) parser_image_info.add_argument( "--version", "-v", @@ -477,6 +482,17 @@ def main(argv=None, esp=None): "must be aligned to. Value 0xFF is used for padding, similar to erase_flash", default=None, ) + parser_elf2image.add_argument( + "--ram-only-header", + help="Order segments of the output so IRAM and DRAM are placed at the " + "beginning and force the main header segment number to RAM segments " + "quantity. This will make the other segments invisible to the ROM " + "loader. Use this argument with care because the ROM loader will load " + "only the RAM segments although the other segments being present in " + "the output.", + action="store_true", + default=None, + ) add_spi_flash_subparsers(parser_elf2image, allow_keep=False, auto_detect=False) @@ -587,18 +603,36 @@ def main(argv=None, esp=None): "--output", "-o", help="Output filename", type=str, required=True ) parser_merge_bin.add_argument( - "--format", "-f", help="Format of the output file", choices="raw", default="raw" - ) # for future expansion + "--format", + "-f", + help="Format of the output file", + choices=["raw", "uf2", "hex"], + default="raw", + ) + uf2_group = parser_merge_bin.add_argument_group("UF2 format") + uf2_group.add_argument( + "--chunk-size", + help="Specify the used data part of the 512 byte UF2 block. " + "A common value is 256. By default the largest possible value will be used.", + default=None, + type=arg_auto_chunk_size, + ) + uf2_group.add_argument( + "--md5-disable", + help="Disable MD5 checksum in UF2 output", + action="store_true", + ) add_spi_flash_subparsers(parser_merge_bin, allow_keep=True, auto_detect=False) - parser_merge_bin.add_argument( + raw_group = parser_merge_bin.add_argument_group("RAW format") + raw_group.add_argument( "--target-offset", "-t", help="Target offset where the output file will be flashed", type=arg_auto_int, default=0, ) - parser_merge_bin.add_argument( + raw_group.add_argument( "--fill-flash-size", help="If set, the final binary file will be padded with FF " "bytes up to this flash size.", @@ -736,14 +770,22 @@ def main(argv=None, esp=None): "Keeping initial baud rate %d" % initial_baud ) - # override common SPI flash parameter stuff if configured to do so + # Override the common SPI flash parameter stuff if configured to do so if hasattr(args, "spi_connection") and args.spi_connection is not None: - if esp.CHIP_NAME != "ESP32": - raise FatalError( - "Chip %s does not support --spi-connection option." % esp.CHIP_NAME - ) - print("Configuring SPI flash mode...") - esp.flash_spi_attach(args.spi_connection) + spi_config = args.spi_connection + if args.spi_connection == "SPI": + value = 0 + elif args.spi_connection == "HSPI": + value = 1 + else: + esp.check_spi_connection(args.spi_connection) + # Encode the pin numbers as a 32-bit integer with packed 6-bit values, + # the same way the ESP ROM takes them + clk, q, d, hd, cs = args.spi_connection + spi_config = f"CLK:{clk}, Q:{q}, D:{d}, HD:{hd}, CS:{cs}" + value = (hd << 24) | (cs << 18) | (d << 12) | (q << 6) | clk + print(f"Configuring SPI flash mode ({spi_config})...") + esp.flash_spi_attach(value) elif args.no_stub: print("Enabling default SPI flash mode...") # ROM loader doesn't enable flash unless we explicitly do it @@ -812,6 +854,15 @@ def main(argv=None, esp=None): "Try checking the chip connections or removing " "any other hardware connected to IOs." ) + if ( + hasattr(args, "spi_connection") + and args.spi_connection is not None + ): + print( + "Some GPIO pins might be used by other peripherals, " + "try using another --spi-connection combination." + ) + except FatalError as e: raise FatalError(f"Unable to verify flash chip connection ({e}).") @@ -834,7 +885,11 @@ def main(argv=None, esp=None): if flash_size is not None: # Secure download mode esp.flash_set_parameters(flash_size_bytes(flash_size)) # Check if stub supports chosen flash size - if esp.IS_STUB and flash_size in ("32MB", "64MB", "128MB"): + if ( + esp.IS_STUB + and esp.CHIP_NAME != "ESP32-S3" + and flash_size_bytes(flash_size) > 16 * 1024 * 1024 + ): print( "WARNING: Flasher stub doesn't fully support flash size larger " "than 16MB, in case of failure use --no-stub." @@ -858,7 +913,7 @@ def main(argv=None, esp=None): args.size = flash_size_bytes(size_str) if esp.IS_STUB and hasattr(args, "address") and hasattr(args, "size"): - if args.address + args.size > 0x1000000: + if esp.CHIP_NAME != "ESP32-S3" and args.address + args.size > 0x1000000: print( "WARNING: Flasher stub doesn't fully support flash size larger " "than 16MB, in case of failure use --no-stub." @@ -906,6 +961,13 @@ def arg_auto_size(x): return x if x == "all" else arg_auto_int(x) +def arg_auto_chunk_size(string: str) -> int: + num = int(string, 0) + if num & 3 != 0: + raise argparse.ArgumentTypeError("Chunk size should be a 4-byte aligned number") + return num + + def get_port_list(): if list_ports is None: raise FatalError( @@ -934,7 +996,7 @@ def expand_file_arguments(argv): else: new_args.append(arg) if expanded: - print("esptool %s" % (" ".join(new_args[1:]))) + print(f"esptool.py {' '.join(new_args)}") return new_args return argv @@ -978,42 +1040,44 @@ class SpiConnectionAction(argparse.Action): """ def __call__(self, parser, namespace, value, option_string=None): - if value.upper() == "SPI": - value = 0 - elif value.upper() == "HSPI": - value = 1 + if value.upper() in ["SPI", "HSPI"]: + values = value.upper() elif "," in value: values = value.split(",") if len(values) != 5: raise argparse.ArgumentError( self, - "%s is not a valid list of comma-separate pin numbers. " - "Must be 5 numbers - CLK,Q,D,HD,CS." % value, + f"{value} is not a valid list of comma-separate pin numbers. " + "Must be 5 numbers - CLK,Q,D,HD,CS.", ) try: values = tuple(int(v, 0) for v in values) except ValueError: raise argparse.ArgumentError( self, - "%s is not a valid argument. All pins must be numeric values" - % values, + f"{values} is not a valid argument. " + "All pins must be numeric values", ) - if any([v for v in values if v > 33 or v < 0]): - raise argparse.ArgumentError( - self, "Pin numbers must be in the range 0-33." - ) - # encode the pin numbers as a 32-bit integer with packed 6-bit values, - # the same way ESP32 ROM takes them - # TODO: make this less ESP32 ROM specific somehow... - clk, q, d, hd, cs = values - value = (hd << 24) | (cs << 18) | (d << 12) | (q << 6) | clk else: raise argparse.ArgumentError( self, - "%s is not a valid spi-connection value. " - "Values are SPI, HSPI, or a sequence of 5 pin numbers CLK,Q,D,HD,CS)." - % value, + f"{value} is not a valid spi-connection value. " + "Values are SPI, HSPI, or a sequence of 5 pin numbers - CLK,Q,D,HD,CS.", ) + setattr(namespace, self.dest, values) + + +class AutoHex2BinAction(argparse.Action): + """Custom parser class for auto conversion of input files from hex to bin""" + + def __call__(self, parser, namespace, value, option_string=None): + try: + with open(value, "rb") as f: + # if hex file was detected replace hex file with converted temp bin + # otherwise keep the original file + value = intel_hex_to_bin(f).name + except IOError as e: + raise argparse.ArgumentError(self, e) setattr(namespace, self.dest, value) @@ -1045,6 +1109,8 @@ class AddrFilenamePairAction(argparse.Action): "Must be pairs of an address " "and the binary filename to write there", ) + # check for intel hex files and convert them to bin + argfile = intel_hex_to_bin(argfile, address) pairs.append((address, argfile)) # Sort the addresses and check for overlapping diff --git a/tools/python/esptool/bin_image.py b/tools/python/esptool/bin_image.py index 5edfb5a7..50809d9b 100644 --- a/tools/python/esptool/bin_image.py +++ b/tools/python/esptool/bin_image.py @@ -10,6 +10,10 @@ import io import os import re import struct +import tempfile +from typing import BinaryIO, Optional + +from intelhex import IntelHex from loader import ESPLoader from targets import ( @@ -20,6 +24,7 @@ from targets import ( ESP32H2BETA1ROM, ESP32H2BETA2ROM, ESP32H2ROM, + ESP32P4ROM, ESP32ROM, ESP32S2ROM, ESP32S3BETA2ROM, @@ -35,6 +40,23 @@ def align_file_position(f, size): f.seek(align, 1) +def intel_hex_to_bin(file: BinaryIO, start_addr: Optional[int] = None) -> BinaryIO: + """Convert IntelHex file to temp binary file with padding from start_addr + If hex file was detected return temp bin file object; input file otherwise""" + INTEL_HEX_MAGIC = b":" + magic = file.read(1) + file.seek(0) + if magic == INTEL_HEX_MAGIC: + ih = IntelHex() + ih.loadhex(file.name) + file.close() + bin = tempfile.NamedTemporaryFile(suffix=".bin", delete=False) + ih.tobinfile(bin, start=start_addr) + return bin + else: + return file + + def LoadFirmwareImage(chip, image_file): """ Load a firmware image. Can be for any supported SoC. @@ -61,6 +83,7 @@ def LoadFirmwareImage(chip, image_file): "esp32c2": ESP32C2FirmwareImage, "esp32c6": ESP32C6FirmwareImage, "esp32h2": ESP32H2FirmwareImage, + "esp32p4": ESP32P4FirmwareImage, }[chip](f) else: # Otherwise, ESP8266 so look at magic to determine the image type magic = ord(f.read(1)) @@ -248,6 +271,20 @@ class BaseFirmwareImage(object): if checksum is not None: return ESPLoader.checksum(segment_data, checksum) + def save_flash_segment(self, f, segment, checksum=None): + """ + Save the next segment to the image file, return next checksum value if provided + """ + if self.ROM_LOADER.CHIP_NAME == "ESP32": + # Work around a bug in ESP-IDF 2nd stage bootloader, that it didn't map the + # last MMU page, if an IROM/DROM segment was < 0x24 bytes + # over the page boundary. + segment_end_pos = f.tell() + len(segment.data) + self.SEG_HEADER_LEN + segment_len_remainder = segment_end_pos % self.IROM_ALIGN + if segment_len_remainder < 0x24: + segment.data += b"\x00" * (0x24 - segment_len_remainder) + return self.save_segment(f, segment, checksum) + def read_checksum(self, f): """Return ESPLoader checksum from end of just-read image""" # Skip the padding. The checksum is stored in the last byte so that the @@ -555,7 +592,7 @@ class ESP32FirmwareImage(BaseFirmwareImage): IROM_ALIGN = 65536 - def __init__(self, load_file=None, append_digest=True): + def __init__(self, load_file=None, append_digest=True, ram_only_header=False): super(ESP32FirmwareImage, self).__init__() self.secure_pad = None self.flash_mode = 0 @@ -573,6 +610,7 @@ class ESP32FirmwareImage(BaseFirmwareImage): self.min_rev = 0 self.min_rev_full = 0 self.max_rev_full = 0 + self.ram_only_header = ram_only_header self.append_digest = append_digest @@ -632,10 +670,10 @@ class ESP32FirmwareImage(BaseFirmwareImage): if not self.is_flash_addr(s.addr) ] - # Patch to support 761 union bus memmap // TODO: ESPTOOL-512 + # Patch to support ESP32-C6 union bus memmap # move ".flash.appdesc" segment to the top of the flash segment for segment in flash_segments: - if segment.name == ".flash.appdesc": + if isinstance(segment, ELFSection) and segment.name == ".flash.appdesc": flash_segments.remove(segment) flash_segments.insert(0, segment) break @@ -685,33 +723,61 @@ class ESP32FirmwareImage(BaseFirmwareImage): pad_len += self.IROM_ALIGN return pad_len - # try to fit each flash segment on a 64kB aligned boundary - # by padding with parts of the non-flash segments... - while len(flash_segments) > 0: - segment = flash_segments[0] - pad_len = get_alignment_data_needed(segment) - if pad_len > 0: # need to pad - if len(ram_segments) > 0 and pad_len > self.SEG_HEADER_LEN: - pad_segment = ram_segments[0].split_image(pad_len) - if len(ram_segments[0].data) == 0: - ram_segments.pop(0) - else: - pad_segment = ImageSegment(0, b"\x00" * pad_len, f.tell()) - checksum = self.save_segment(f, pad_segment, checksum) + if self.ram_only_header: + # write RAM segments first in order to get only RAM segments quantity + # and checksum (ROM bootloader will only care for RAM segments and its + # correct checksums) + for segment in ram_segments: + checksum = self.save_segment(f, segment, checksum) total_segments += 1 - else: + self.append_checksum(f, checksum) + + # reversing to match the same section order from linker script + flash_segments.reverse() + for segment in flash_segments: + pad_len = get_alignment_data_needed(segment) + while pad_len > 0: + pad_segment = ImageSegment(0, b"\x00" * pad_len, f.tell()) + self.save_segment(f, pad_segment) + total_segments += 1 + pad_len = get_alignment_data_needed(segment) # write the flash segment assert ( f.tell() + 8 ) % self.IROM_ALIGN == segment.addr % self.IROM_ALIGN - checksum = self.save_flash_segment(f, segment, checksum) - flash_segments.pop(0) + # save the flash segment but not saving its checksum neither + # saving the number of flash segments, since ROM bootloader + # should "not see" them + self.save_flash_segment(f, segment) total_segments += 1 + else: # not self.ram_only_header + # try to fit each flash segment on a 64kB aligned boundary + # by padding with parts of the non-flash segments... + while len(flash_segments) > 0: + segment = flash_segments[0] + pad_len = get_alignment_data_needed(segment) + if pad_len > 0: # need to pad + if len(ram_segments) > 0 and pad_len > self.SEG_HEADER_LEN: + pad_segment = ram_segments[0].split_image(pad_len) + if len(ram_segments[0].data) == 0: + ram_segments.pop(0) + else: + pad_segment = ImageSegment(0, b"\x00" * pad_len, f.tell()) + checksum = self.save_segment(f, pad_segment, checksum) + total_segments += 1 + else: + # write the flash segment + assert ( + f.tell() + 8 + ) % self.IROM_ALIGN == segment.addr % self.IROM_ALIGN + checksum = self.save_flash_segment(f, segment, checksum) + flash_segments.pop(0) + total_segments += 1 - # flash segments all written, so write any remaining RAM segments - for segment in ram_segments: - checksum = self.save_segment(f, segment, checksum) - total_segments += 1 + # flash segments all written, so write any remaining RAM segments + for segment in ram_segments: + checksum = self.save_segment(f, segment, checksum) + total_segments += 1 if self.secure_pad: # pad the image so that after signing it will end on a a 64KB boundary. @@ -743,8 +809,9 @@ class ESP32FirmwareImage(BaseFirmwareImage): checksum = self.save_segment(f, pad_segment, checksum) total_segments += 1 - # done writing segments - self.append_checksum(f, checksum) + if not self.ram_only_header: + # done writing segments + self.append_checksum(f, checksum) image_length = f.tell() if self.secure_pad: @@ -753,7 +820,12 @@ class ESP32FirmwareImage(BaseFirmwareImage): # kinda hacky: go back to the initial header and write the new segment count # that includes padding segments. This header is not checksummed f.seek(1) - f.write(bytes([total_segments])) + if self.ram_only_header: + # Update the header with the RAM segments quantity as it should be + # visible by the ROM bootloader + f.write(bytes([len(ram_segments)])) + else: + f.write(bytes([total_segments])) if self.append_digest: # calculate the SHA256 of the whole file and append it @@ -771,19 +843,6 @@ class ESP32FirmwareImage(BaseFirmwareImage): with open(filename, "wb") as real_file: real_file.write(f.getvalue()) - def save_flash_segment(self, f, segment, checksum=None): - """ - Save the next segment to the image file, return next checksum value if provided - """ - segment_end_pos = f.tell() + len(segment.data) + self.SEG_HEADER_LEN - segment_len_remainder = segment_end_pos % self.IROM_ALIGN - if segment_len_remainder < 0x24: - # Work around a bug in ESP-IDF 2nd stage bootloader, that it didn't map the - # last MMU page, if an IROM/DROM segment was < 0x24 bytes - # over the page boundary. - segment.data += b"\x00" * (0x24 - segment_len_remainder) - return self.save_segment(f, segment, checksum) - def load_extended_header(self, load_file): def split_byte(n): return (n & 0x0F, (n >> 4) & 0x0F) @@ -1055,6 +1114,15 @@ class ESP32C6FirmwareImage(ESP32FirmwareImage): ESP32C6ROM.BOOTLOADER_IMAGE = ESP32C6FirmwareImage +class ESP32P4FirmwareImage(ESP32FirmwareImage): + """ESP32P4 Firmware Image almost exactly the same as ESP32FirmwareImage""" + + ROM_LOADER = ESP32P4ROM + + +ESP32P4ROM.BOOTLOADER_IMAGE = ESP32P4FirmwareImage + + class ESP32H2FirmwareImage(ESP32C6FirmwareImage): """ESP32H2 Firmware Image almost exactly the same as ESP32FirmwareImage""" @@ -1067,6 +1135,7 @@ ESP32H2ROM.BOOTLOADER_IMAGE = ESP32H2FirmwareImage class ELFFile(object): SEC_TYPE_PROGBITS = 0x01 SEC_TYPE_STRTAB = 0x03 + SEC_TYPE_NOBITS = 0x08 # e.g. .bss section SEC_TYPE_INITARRAY = 0x0E SEC_TYPE_FINIARRAY = 0x0F @@ -1157,6 +1226,7 @@ class ELFFile(object): all_sections = [read_section_header(offs) for offs in section_header_offsets] prog_sections = [s for s in all_sections if s[1] in ELFFile.PROG_SEC_TYPES] + nobits_secitons = [s for s in all_sections if s[1] == ELFFile.SEC_TYPE_NOBITS] # search for the string table section if not (shstrndx * self.LEN_SEC_HEADER) in section_header_offsets: @@ -1188,6 +1258,11 @@ class ELFFile(object): if lma != 0 and size > 0 ] self.sections = prog_sections + self.nobits_sections = [ + ELFSection(lookup_string(n_offs), lma, b"") + for (n_offs, _type, lma, size, offs) in nobits_secitons + if lma != 0 and size > 0 + ] def _read_segments(self, f, segment_header_offs, segment_header_count, shstrndx): f.seek(segment_header_offs) diff --git a/tools/python/esptool/cmds.py b/tools/python/esptool/cmds.py index 71ac3585..f5e61ea8 100644 --- a/tools/python/esptool/cmds.py +++ b/tools/python/esptool/cmds.py @@ -11,6 +11,8 @@ import sys import time import zlib +from intelhex import IntelHex + from bin_image import ELFFile, ImageSegment, LoadFirmwareImage from bin_image import ( ESP8266ROMFirmwareImage, @@ -25,6 +27,7 @@ from loader import ( timeout_per_mb, ) from targets import CHIP_DEFS, CHIP_LIST, ROM_LIST +from uf2_writer import UF2Writer from util import ( FatalError, NotImplementedInROMError, @@ -96,7 +99,7 @@ def detect_chip( print("Detecting chip type...", end="") chip_id = detect_port.get_chip_id() for cls in [ - n for n in ROM_LIST if n.CHIP_NAME not in ("ESP8266", "ESP32", "ESP32S2") + n for n in ROM_LIST if n.CHIP_NAME not in ("ESP8266", "ESP32", "ESP32-S2") ]: # cmd not supported on ESP8266 and ESP32 + ESP32-S2 doesn't return chip_id if chip_id == cls.IMAGE_CHIP_ID: @@ -466,7 +469,7 @@ def write_flash(esp, args): flash_end = flash_size_bytes( detect_flash_size(esp) if args.flash_size == "keep" else args.flash_size ) - if flash_end is not None: # Secure download mode + if flash_end is not None: # Not in secure download mode for address, argfile in args.addr_filename: argfile.seek(0, os.SEEK_END) if address + argfile.tell() > flash_end: @@ -979,6 +982,8 @@ def elf2image(args): args.chip = "esp8266" print("Creating {} image...".format(args.chip)) + if args.ram_only_header: + print("ROM segments hidden - only RAM segments are visible to the ROM loader!") if args.chip != "esp8266": image = CHIP_DEFS[args.chip].BOOTLOADER_IMAGE() @@ -989,6 +994,7 @@ def elf2image(args): image.min_rev = args.min_rev image.min_rev_full = args.min_rev_full image.max_rev_full = args.max_rev_full + image.ram_only_header = args.ram_only_header image.append_digest = args.append_digest elif args.version == "1": # ESP8266 image = ESP8266ROMFirmwareImage() @@ -1106,9 +1112,9 @@ def read_flash(esp, args): def flash_progress(progress, length): msg = "%d (%d %%)" % (progress, progress * 100.0 / length) - # padding = "\b" * len(msg) - # if progress == length: - padding = "\n" + padding = "\b" * len(msg) + if progress == length: + padding = "\n" sys.stdout.write(msg + padding) sys.stdout.flush() @@ -1180,15 +1186,95 @@ def write_flash_status(esp, args): print(("After flash status: " + fmt) % esp.read_status(args.bytes)) +# The following mapping was taken from the ROM code +# This mapping is same across all targets in the ROM +SECURITY_INFO_FLAG_MAP = { + "SECURE_BOOT_EN": (1 << 0), + "SECURE_BOOT_AGGRESSIVE_REVOKE": (1 << 1), + "SECURE_DOWNLOAD_ENABLE": (1 << 2), + "SECURE_BOOT_KEY_REVOKE0": (1 << 3), + "SECURE_BOOT_KEY_REVOKE1": (1 << 4), + "SECURE_BOOT_KEY_REVOKE2": (1 << 5), + "SOFT_DIS_JTAG": (1 << 6), + "HARD_DIS_JTAG": (1 << 7), + "DIS_USB": (1 << 8), + "DIS_DOWNLOAD_DCACHE": (1 << 9), + "DIS_DOWNLOAD_ICACHE": (1 << 10), +} + + +# Get the status of respective security flag +def get_security_flag_status(flag_name, flags_value): + try: + return (flags_value & SECURITY_INFO_FLAG_MAP[flag_name]) != 0 + except KeyError: + raise ValueError(f"Invalid flag name: {flag_name}") + + def get_security_info(esp, args): si = esp.get_security_info() - # TODO: better display + print() + title = "Security Information:" + print(title) + print("=" * len(title)) print("Flags: {:#010x} ({})".format(si["flags"], bin(si["flags"]))) - print("Flash_Crypt_Cnt: {:#x}".format(si["flash_crypt_cnt"])) - print("Key_Purposes: {}".format(si["key_purposes"])) + print("Key Purposes: {}".format(si["key_purposes"])) if si["chip_id"] is not None and si["api_version"] is not None: - print("Chip_ID: {}".format(si["chip_id"])) - print("Api_Version: {}".format(si["api_version"])) + print("Chip ID: {}".format(si["chip_id"])) + print("API Version: {}".format(si["api_version"])) + + flags = si["flags"] + + if get_security_flag_status("SECURE_BOOT_EN", flags): + print("Secure Boot: Enabled") + if get_security_flag_status("SECURE_BOOT_AGGRESSIVE_REVOKE", flags): + print("Secure Boot Aggressive key revocation: Enabled") + + revoked_keys = [] + for i, key in enumerate( + [ + "SECURE_BOOT_KEY_REVOKE0", + "SECURE_BOOT_KEY_REVOKE1", + "SECURE_BOOT_KEY_REVOKE2", + ] + ): + if get_security_flag_status(key, flags): + revoked_keys.append(i) + + if len(revoked_keys) > 0: + print("Secure Boot Key Revocation Status:\n") + for i in revoked_keys: + print(f"\tSecure Boot Key{i} is Revoked\n") + + else: + print("Secure Boot: Disabled") + + flash_crypt_cnt = bin(si["flash_crypt_cnt"]) + if (flash_crypt_cnt.count("1") % 2) != 0: + print("Flash Encryption: Enabled") + else: + print("Flash Encryption: Disabled") + + CRYPT_CNT_STRING = "SPI Boot Crypt Count (SPI_BOOT_CRYPT_CNT)" + if esp.CHIP_NAME == "esp32": + CRYPT_CNT_STRING = "Flash Crypt Count (FLASH_CRYPT_CNT)" + + print(f"{CRYPT_CNT_STRING}: {si['flash_crypt_cnt']:#x}") + + if get_security_flag_status("DIS_DOWNLOAD_DCACHE", flags): + print("Dcache in UART download mode: Disabled") + + if get_security_flag_status("DIS_DOWNLOAD_ICACHE", flags): + print("Icache in UART download mode: Disabled") + + hard_dis_jtag = get_security_flag_status("HARD_DIS_JTAG", flags) + soft_dis_jtag = get_security_flag_status("SOFT_DIS_JTAG", flags) + if hard_dis_jtag: + print("JTAG: Permenantly Disabled") + elif soft_dis_jtag: + print("JTAG: Software Access Disabled") + if get_security_flag_status("DIS_USB", flags): + print("USB Access: Disabled") def merge_bin(args): @@ -1198,9 +1284,9 @@ def merge_bin(args): msg = ( "Please specify the chip argument" if args.chip == "auto" - else "Invalid chip choice: '{}'".format(args.chip) + else f"Invalid chip choice: '{args.chip}'" ) - msg = msg + " (choose from {})".format(", ".join(CHIP_LIST)) + msg = f"{msg} (choose from {', '.join(CHIP_LIST)})" raise FatalError(msg) # sort the files by offset. @@ -1211,31 +1297,57 @@ def merge_bin(args): first_addr = input_files[0][0] if first_addr < args.target_offset: raise FatalError( - "Output file target offset is 0x%x. Input file offset 0x%x is before this." - % (args.target_offset, first_addr) + f"Output file target offset is {args.target_offset:#x}. " + f"Input file offset {first_addr:#x} is before this." ) - if args.format != "raw": - raise FatalError( - "This version of esptool only supports the 'raw' output format" + if args.format == "uf2": + with UF2Writer( + chip_class.UF2_FAMILY_ID, + args.output, + args.chunk_size, + md5_enabled=not args.md5_disable, + ) as writer: + for addr, argfile in input_files: + print(f"Adding {argfile.name} at {addr:#x}") + image = argfile.read() + image = _update_image_flash_params(chip_class, addr, args, image) + writer.add_file(addr, image) + print( + f"Wrote {os.path.getsize(args.output):#x} bytes to file {args.output}, " + f"ready to be flashed with any ESP USB Bridge" ) - with open(args.output, "wb") as of: + elif args.format == "raw": + with open(args.output, "wb") as of: - def pad_to(flash_offs): - # account for output file offset if there is any - of.write(b"\xFF" * (flash_offs - args.target_offset - of.tell())) + def pad_to(flash_offs): + # account for output file offset if there is any + of.write(b"\xFF" * (flash_offs - args.target_offset - of.tell())) + for addr, argfile in input_files: + pad_to(addr) + image = argfile.read() + image = _update_image_flash_params(chip_class, addr, args, image) + of.write(image) + if args.fill_flash_size: + pad_to(flash_size_bytes(args.fill_flash_size)) + print( + f"Wrote {of.tell():#x} bytes to file {args.output}, " + f"ready to flash to offset {args.target_offset:#x}" + ) + elif args.format == "hex": + out = IntelHex() for addr, argfile in input_files: - pad_to(addr) + ihex = IntelHex() image = argfile.read() image = _update_image_flash_params(chip_class, addr, args, image) - of.write(image) - if args.fill_flash_size: - pad_to(flash_size_bytes(args.fill_flash_size)) + ihex.frombytes(image, addr) + out.merge(ihex) + out.write_hex_file(args.output) print( - "Wrote 0x%x bytes to file %s, ready to flash to offset 0x%x" - % (of.tell(), args.output, args.target_offset) + f"Wrote {os.path.getsize(args.output):#x} bytes to file {args.output}, " + f"ready to flash to offset {args.target_offset:#x}" ) diff --git a/tools/python/esptool/intelhex/__init__.py b/tools/python/esptool/intelhex/__init__.py new file mode 100644 index 00000000..c6423a6e --- /dev/null +++ b/tools/python/esptool/intelhex/__init__.py @@ -0,0 +1,1372 @@ +# Copyright (c) 2005-2018, Alexander Belchenko +# All rights reserved. +# +# Redistribution and use in source and binary forms, +# with or without modification, are permitted provided +# that the following conditions are met: +# +# * Redistributions of source code must retain +# the above copyright notice, this list of conditions +# and the following disclaimer. +# * Redistributions in binary form must reproduce +# the above copyright notice, this list of conditions +# and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * Neither the name of the author nor the names +# of its contributors may be used to endorse +# or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, +# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +'''Intel HEX format manipulation library.''' + +__docformat__ = "javadoc" + +from array import array +from binascii import hexlify, unhexlify +from bisect import bisect_right +import os +import sys + +from intelhex.compat import ( + IntTypes, + StrType, + StringIO, + array_tobytes, + asbytes, + asstr, + dict_items_g, + dict_keys, + dict_keys_g, + range_g, + range_l, + ) + +from intelhex.getsizeof import total_size + + +class _DeprecatedParam(object): + pass + +_DEPRECATED = _DeprecatedParam() + + +class IntelHex(object): + ''' Intel HEX file reader. ''' + + def __init__(self, source=None): + ''' Constructor. If source specified, object will be initialized + with the contents of source. Otherwise the object will be empty. + + @param source source for initialization + (file name of HEX file, file object, addr dict or + other IntelHex object) + ''' + # public members + self.padding = 0x0FF + # Start Address + self.start_addr = None + + # private members + self._buf = {} + self._offset = 0 + + if source is not None: + if isinstance(source, StrType) or getattr(source, "read", None): + # load hex file + self.loadhex(source) + elif isinstance(source, dict): + self.fromdict(source) + elif isinstance(source, IntelHex): + self.padding = source.padding + if source.start_addr: + self.start_addr = source.start_addr.copy() + self._buf = source._buf.copy() + else: + raise ValueError("source: bad initializer type") + + def _decode_record(self, s, line=0): + '''Decode one record of HEX file. + + @param s line with HEX record. + @param line line number (for error messages). + + @raise EndOfFile if EOF record encountered. + ''' + s = s.rstrip('\r\n') + if not s: + return # empty line + + if s[0] == ':': + try: + bin = array('B', unhexlify(asbytes(s[1:]))) + except (TypeError, ValueError): + # this might be raised by unhexlify when odd hexascii digits + raise HexRecordError(line=line) + length = len(bin) + if length < 5: + raise HexRecordError(line=line) + else: + raise HexRecordError(line=line) + + record_length = bin[0] + if length != (5 + record_length): + raise RecordLengthError(line=line) + + addr = bin[1]*256 + bin[2] + + record_type = bin[3] + if not (0 <= record_type <= 5): + raise RecordTypeError(line=line) + + crc = sum(bin) + crc &= 0x0FF + if crc != 0: + raise RecordChecksumError(line=line) + + if record_type == 0: + # data record + addr += self._offset + for i in range_g(4, 4+record_length): + if not self._buf.get(addr, None) is None: + raise AddressOverlapError(address=addr, line=line) + self._buf[addr] = bin[i] + addr += 1 # FIXME: addr should be wrapped + # BUT after 02 record (at 64K boundary) + # and after 04 record (at 4G boundary) + + elif record_type == 1: + # end of file record + if record_length != 0: + raise EOFRecordError(line=line) + raise _EndOfFile + + elif record_type == 2: + # Extended 8086 Segment Record + if record_length != 2 or addr != 0: + raise ExtendedSegmentAddressRecordError(line=line) + self._offset = (bin[4]*256 + bin[5]) * 16 + + elif record_type == 4: + # Extended Linear Address Record + if record_length != 2 or addr != 0: + raise ExtendedLinearAddressRecordError(line=line) + self._offset = (bin[4]*256 + bin[5]) * 65536 + + elif record_type == 3: + # Start Segment Address Record + if record_length != 4 or addr != 0: + raise StartSegmentAddressRecordError(line=line) + if self.start_addr: + raise DuplicateStartAddressRecordError(line=line) + self.start_addr = {'CS': bin[4]*256 + bin[5], + 'IP': bin[6]*256 + bin[7], + } + + elif record_type == 5: + # Start Linear Address Record + if record_length != 4 or addr != 0: + raise StartLinearAddressRecordError(line=line) + if self.start_addr: + raise DuplicateStartAddressRecordError(line=line) + self.start_addr = {'EIP': (bin[4]*16777216 + + bin[5]*65536 + + bin[6]*256 + + bin[7]), + } + + def loadhex(self, fobj): + """Load hex file into internal buffer. This is not necessary + if object was initialized with source set. This will overwrite + addresses if object was already initialized. + + @param fobj file name or file-like object + """ + if getattr(fobj, "read", None) is None: + fobj = open(fobj, "r") + fclose = fobj.close + else: + fclose = None + + self._offset = 0 + line = 0 + + try: + decode = self._decode_record + try: + for s in fobj: + line += 1 + decode(s, line) + except _EndOfFile: + pass + finally: + if fclose: + fclose() + + def loadbin(self, fobj, offset=0): + """Load bin file into internal buffer. Not needed if source set in + constructor. This will overwrite addresses without warning + if object was already initialized. + + @param fobj file name or file-like object + @param offset starting address offset + """ + fread = getattr(fobj, "read", None) + if fread is None: + f = open(fobj, "rb") + fread = f.read + fclose = f.close + else: + fclose = None + + try: + self.frombytes(array('B', asbytes(fread())), offset=offset) + finally: + if fclose: + fclose() + + def loadfile(self, fobj, format): + """Load data file into internal buffer. Preferred wrapper over + loadbin or loadhex. + + @param fobj file name or file-like object + @param format file format ("hex" or "bin") + """ + if format == "hex": + self.loadhex(fobj) + elif format == "bin": + self.loadbin(fobj) + else: + raise ValueError('format should be either "hex" or "bin";' + ' got %r instead' % format) + + # alias (to be consistent with method tofile) + fromfile = loadfile + + def fromdict(self, dikt): + """Load data from dictionary. Dictionary should contain int keys + representing addresses. Values should be the data to be stored in + those addresses in unsigned char form (i.e. not strings). + The dictionary may contain the key, ``start_addr`` + to indicate the starting address of the data as described in README. + + The contents of the dict will be merged with this object and will + overwrite any conflicts. This function is not necessary if the + object was initialized with source specified. + """ + s = dikt.copy() + start_addr = s.get('start_addr') + if start_addr is not None: + del s['start_addr'] + for k in dict_keys_g(s): + if type(k) not in IntTypes or k < 0: + raise ValueError('Source dictionary should have only int keys') + self._buf.update(s) + if start_addr is not None: + self.start_addr = start_addr + + def frombytes(self, bytes, offset=0): + """Load data from array or list of bytes. + Similar to loadbin() method but works directly with iterable bytes. + """ + for b in bytes: + self._buf[offset] = b + offset += 1 + + def _get_start_end(self, start=None, end=None, size=None): + """Return default values for start and end if they are None. + If this IntelHex object is empty then it's error to + invoke this method with both start and end as None. + """ + if (start,end) == (None,None) and self._buf == {}: + raise EmptyIntelHexError + if size is not None: + if None not in (start, end): + raise ValueError("tobinarray: you can't use start,end and size" + " arguments in the same time") + if (start, end) == (None, None): + start = self.minaddr() + if start is not None: + end = start + size - 1 + else: + start = end - size + 1 + if start < 0: + raise ValueError("tobinarray: invalid size (%d) " + "for given end address (%d)" % (size,end)) + else: + if start is None: + start = self.minaddr() + if end is None: + end = self.maxaddr() + if start > end: + start, end = end, start + return start, end + + def tobinarray(self, start=None, end=None, pad=_DEPRECATED, size=None): + ''' Convert this object to binary form as array. If start and end + unspecified, they will be inferred from the data. + @param start start address of output bytes. + @param end end address of output bytes (inclusive). + @param pad [DEPRECATED PARAMETER, please use self.padding instead] + fill empty spaces with this value + (if pad is None then this method uses self.padding). + @param size size of the block, used with start or end parameter. + @return array of unsigned char data. + ''' + if not isinstance(pad, _DeprecatedParam): + print ("IntelHex.tobinarray: 'pad' parameter is deprecated.") + if pad is not None: + print ("Please, use IntelHex.padding attribute instead.") + else: + print ("Please, don't pass it explicitly.") + print ("Use syntax like this: ih.tobinarray(start=xxx, end=yyy, size=zzz)") + else: + pad = None + return self._tobinarray_really(start, end, pad, size) + + def _tobinarray_really(self, start, end, pad, size): + """Return binary array.""" + if pad is None: + pad = self.padding + bin = array('B') + if self._buf == {} and None in (start, end): + return bin + if size is not None and size <= 0: + raise ValueError("tobinarray: wrong value for size") + start, end = self._get_start_end(start, end, size) + for i in range_g(start, end+1): + bin.append(self._buf.get(i, pad)) + return bin + + def tobinstr(self, start=None, end=None, pad=_DEPRECATED, size=None): + ''' Convert to binary form and return as binary string. + @param start start address of output bytes. + @param end end address of output bytes (inclusive). + @param pad [DEPRECATED PARAMETER, please use self.padding instead] + fill empty spaces with this value + (if pad is None then this method uses self.padding). + @param size size of the block, used with start or end parameter. + @return bytes string of binary data. + ''' + if not isinstance(pad, _DeprecatedParam): + print ("IntelHex.tobinstr: 'pad' parameter is deprecated.") + if pad is not None: + print ("Please, use IntelHex.padding attribute instead.") + else: + print ("Please, don't pass it explicitly.") + print ("Use syntax like this: ih.tobinstr(start=xxx, end=yyy, size=zzz)") + else: + pad = None + return self._tobinstr_really(start, end, pad, size) + + def _tobinstr_really(self, start, end, pad, size): + return array_tobytes(self._tobinarray_really(start, end, pad, size)) + + def tobinfile(self, fobj, start=None, end=None, pad=_DEPRECATED, size=None): + '''Convert to binary and write to file. + + @param fobj file name or file object for writing output bytes. + @param start start address of output bytes. + @param end end address of output bytes (inclusive). + @param pad [DEPRECATED PARAMETER, please use self.padding instead] + fill empty spaces with this value + (if pad is None then this method uses self.padding). + @param size size of the block, used with start or end parameter. + ''' + if not isinstance(pad, _DeprecatedParam): + print ("IntelHex.tobinfile: 'pad' parameter is deprecated.") + if pad is not None: + print ("Please, use IntelHex.padding attribute instead.") + else: + print ("Please, don't pass it explicitly.") + print ("Use syntax like this: ih.tobinfile(start=xxx, end=yyy, size=zzz)") + else: + pad = None + if getattr(fobj, "write", None) is None: + fobj = open(fobj, "wb") + close_fd = True + else: + close_fd = False + + fobj.write(self._tobinstr_really(start, end, pad, size)) + + if close_fd: + fobj.close() + + def todict(self): + '''Convert to python dictionary. + + @return dict suitable for initializing another IntelHex object. + ''' + r = {} + r.update(self._buf) + if self.start_addr: + r['start_addr'] = self.start_addr + return r + + def addresses(self): + '''Returns all used addresses in sorted order. + @return list of occupied data addresses in sorted order. + ''' + aa = dict_keys(self._buf) + aa.sort() + return aa + + def minaddr(self): + '''Get minimal address of HEX content. + @return minimal address or None if no data + ''' + aa = dict_keys(self._buf) + if aa == []: + return None + else: + return min(aa) + + def maxaddr(self): + '''Get maximal address of HEX content. + @return maximal address or None if no data + ''' + aa = dict_keys(self._buf) + if aa == []: + return None + else: + return max(aa) + + def __getitem__(self, addr): + ''' Get requested byte from address. + @param addr address of byte. + @return byte if address exists in HEX file, or self.padding + if no data found. + ''' + t = type(addr) + if t in IntTypes: + if addr < 0: + raise TypeError('Address should be >= 0.') + return self._buf.get(addr, self.padding) + elif t == slice: + addresses = dict_keys(self._buf) + ih = IntelHex() + if addresses: + addresses.sort() + start = addr.start or addresses[0] + stop = addr.stop or (addresses[-1]+1) + step = addr.step or 1 + for i in range_g(start, stop, step): + x = self._buf.get(i) + if x is not None: + ih[i] = x + return ih + else: + raise TypeError('Address has unsupported type: %s' % t) + + def __setitem__(self, addr, byte): + """Set byte at address.""" + t = type(addr) + if t in IntTypes: + if addr < 0: + raise TypeError('Address should be >= 0.') + self._buf[addr] = byte + elif t == slice: + if not isinstance(byte, (list, tuple)): + raise ValueError('Slice operation expects sequence of bytes') + start = addr.start + stop = addr.stop + step = addr.step or 1 + if None not in (start, stop): + ra = range_l(start, stop, step) + if len(ra) != len(byte): + raise ValueError('Length of bytes sequence does not match ' + 'address range') + elif (start, stop) == (None, None): + raise TypeError('Unsupported address range') + elif start is None: + start = stop - len(byte) + elif stop is None: + stop = start + len(byte) + if start < 0: + raise TypeError('start address cannot be negative') + if stop < 0: + raise TypeError('stop address cannot be negative') + j = 0 + for i in range_g(start, stop, step): + self._buf[i] = byte[j] + j += 1 + else: + raise TypeError('Address has unsupported type: %s' % t) + + def __delitem__(self, addr): + """Delete byte at address.""" + t = type(addr) + if t in IntTypes: + if addr < 0: + raise TypeError('Address should be >= 0.') + del self._buf[addr] + elif t == slice: + addresses = dict_keys(self._buf) + if addresses: + addresses.sort() + start = addr.start or addresses[0] + stop = addr.stop or (addresses[-1]+1) + step = addr.step or 1 + for i in range_g(start, stop, step): + x = self._buf.get(i) + if x is not None: + del self._buf[i] + else: + raise TypeError('Address has unsupported type: %s' % t) + + def __len__(self): + """Return count of bytes with real values.""" + return len(dict_keys(self._buf)) + + def _get_eol_textfile(eolstyle, platform): + if eolstyle == 'native': + return '\n' + elif eolstyle == 'CRLF': + if platform != 'win32': + return '\r\n' + else: + return '\n' + else: + raise ValueError("wrong eolstyle %s" % repr(eolstyle)) + _get_eol_textfile = staticmethod(_get_eol_textfile) + + def write_hex_file(self, f, write_start_addr=True, eolstyle='native', byte_count=16): + """Write data to file f in HEX format. + + @param f filename or file-like object for writing + @param write_start_addr enable or disable writing start address + record to file (enabled by default). + If there is no start address in obj, nothing + will be written regardless of this setting. + @param eolstyle can be used to force CRLF line-endings + for output file on different platforms. + Supported eol styles: 'native', 'CRLF'. + @param byte_count number of bytes in the data field + """ + if byte_count > 255 or byte_count < 1: + raise ValueError("wrong byte_count value: %s" % byte_count) + fwrite = getattr(f, "write", None) + if fwrite: + fobj = f + fclose = None + else: + fobj = open(f, 'w') + fwrite = fobj.write + fclose = fobj.close + + eol = IntelHex._get_eol_textfile(eolstyle, sys.platform) + + # Translation table for uppercasing hex ascii string. + # timeit shows that using hexstr.translate(table) + # is faster than hexstr.upper(): + # 0.452ms vs. 0.652ms (translate vs. upper) + if sys.version_info[0] >= 3: + # Python 3 + table = bytes(range_l(256)).upper() + else: + # Python 2 + table = ''.join(chr(i).upper() for i in range_g(256)) + + # start address record if any + if self.start_addr and write_start_addr: + keys = dict_keys(self.start_addr) + keys.sort() + bin = array('B', asbytes('\0'*9)) + if keys == ['CS','IP']: + # Start Segment Address Record + bin[0] = 4 # reclen + bin[1] = 0 # offset msb + bin[2] = 0 # offset lsb + bin[3] = 3 # rectyp + cs = self.start_addr['CS'] + bin[4] = (cs >> 8) & 0x0FF + bin[5] = cs & 0x0FF + ip = self.start_addr['IP'] + bin[6] = (ip >> 8) & 0x0FF + bin[7] = ip & 0x0FF + bin[8] = (-sum(bin)) & 0x0FF # chksum + fwrite(':' + + asstr(hexlify(array_tobytes(bin)).translate(table)) + + eol) + elif keys == ['EIP']: + # Start Linear Address Record + bin[0] = 4 # reclen + bin[1] = 0 # offset msb + bin[2] = 0 # offset lsb + bin[3] = 5 # rectyp + eip = self.start_addr['EIP'] + bin[4] = (eip >> 24) & 0x0FF + bin[5] = (eip >> 16) & 0x0FF + bin[6] = (eip >> 8) & 0x0FF + bin[7] = eip & 0x0FF + bin[8] = (-sum(bin)) & 0x0FF # chksum + fwrite(':' + + asstr(hexlify(array_tobytes(bin)).translate(table)) + + eol) + else: + if fclose: + fclose() + raise InvalidStartAddressValueError(start_addr=self.start_addr) + + # data + addresses = dict_keys(self._buf) + addresses.sort() + addr_len = len(addresses) + if addr_len: + minaddr = addresses[0] + maxaddr = addresses[-1] + + if maxaddr > 65535: + need_offset_record = True + else: + need_offset_record = False + high_ofs = 0 + + cur_addr = minaddr + cur_ix = 0 + + while cur_addr <= maxaddr: + if need_offset_record: + bin = array('B', asbytes('\0'*7)) + bin[0] = 2 # reclen + bin[1] = 0 # offset msb + bin[2] = 0 # offset lsb + bin[3] = 4 # rectyp + high_ofs = int(cur_addr>>16) + b = divmod(high_ofs, 256) + bin[4] = b[0] # msb of high_ofs + bin[5] = b[1] # lsb of high_ofs + bin[6] = (-sum(bin)) & 0x0FF # chksum + fwrite(':' + + asstr(hexlify(array_tobytes(bin)).translate(table)) + + eol) + + while True: + # produce one record + low_addr = cur_addr & 0x0FFFF + # chain_len off by 1 + chain_len = min(byte_count-1, 65535-low_addr, maxaddr-cur_addr) + + # search continuous chain + stop_addr = cur_addr + chain_len + if chain_len: + ix = bisect_right(addresses, stop_addr, + cur_ix, + min(cur_ix+chain_len+1, addr_len)) + chain_len = ix - cur_ix # real chain_len + # there could be small holes in the chain + # but we will catch them by try-except later + # so for big continuous files we will work + # at maximum possible speed + else: + chain_len = 1 # real chain_len + + bin = array('B', asbytes('\0'*(5+chain_len))) + b = divmod(low_addr, 256) + bin[1] = b[0] # msb of low_addr + bin[2] = b[1] # lsb of low_addr + bin[3] = 0 # rectype + try: # if there is small holes we'll catch them + for i in range_g(chain_len): + bin[4+i] = self._buf[cur_addr+i] + except KeyError: + # we catch a hole so we should shrink the chain + chain_len = i + bin = bin[:5+i] + bin[0] = chain_len + bin[4+chain_len] = (-sum(bin)) & 0x0FF # chksum + fwrite(':' + + asstr(hexlify(array_tobytes(bin)).translate(table)) + + eol) + + # adjust cur_addr/cur_ix + cur_ix += chain_len + if cur_ix < addr_len: + cur_addr = addresses[cur_ix] + else: + cur_addr = maxaddr + 1 + break + high_addr = int(cur_addr>>16) + if high_addr > high_ofs: + break + + # end-of-file record + fwrite(":00000001FF"+eol) + if fclose: + fclose() + + def tofile(self, fobj, format, byte_count=16): + """Write data to hex or bin file. Preferred method over tobin or tohex. + + @param fobj file name or file-like object + @param format file format ("hex" or "bin") + @param byte_count bytes per line + """ + if format == 'hex': + self.write_hex_file(fobj, byte_count=byte_count) + elif format == 'bin': + self.tobinfile(fobj) + else: + raise ValueError('format should be either "hex" or "bin";' + ' got %r instead' % format) + + def gets(self, addr, length): + """Get string of bytes from given address. If any entries are blank + from addr through addr+length, a NotEnoughDataError exception will + be raised. Padding is not used. + """ + a = array('B', asbytes('\0'*length)) + try: + for i in range_g(length): + a[i] = self._buf[addr+i] + except KeyError: + raise NotEnoughDataError(address=addr, length=length) + return array_tobytes(a) + + def puts(self, addr, s): + """Put string of bytes at given address. Will overwrite any previous + entries. + """ + a = array('B', asbytes(s)) + for i in range_g(len(a)): + self._buf[addr+i] = a[i] + + def getsz(self, addr): + """Get zero-terminated bytes string from given address. Will raise + NotEnoughDataError exception if a hole is encountered before a 0. + """ + i = 0 + try: + while True: + if self._buf[addr+i] == 0: + break + i += 1 + except KeyError: + raise NotEnoughDataError(msg=('Bad access at 0x%X: ' + 'not enough data to read zero-terminated string') % addr) + return self.gets(addr, i) + + def putsz(self, addr, s): + """Put bytes string in object at addr and append terminating zero at end.""" + self.puts(addr, s) + self._buf[addr+len(s)] = 0 + + def find(self, sub, start=None, end=None): + """Return the lowest index in self[start:end] where subsection sub is found. + Optional arguments start and end are interpreted as in slice notation. + + @param sub bytes-like subsection to find + @param start start of section to search within (optional) + @param end end of section to search within (optional) + """ + sub = bytes(sub) + for start, end in self[slice(start,end)].segments(): + b = self.gets(start, end-start) + i = b.find(sub) + if i != -1: + return start+i + return -1 + + def dump(self, tofile=None, width=16, withpadding=False): + """Dump object content to specified file object or to stdout if None. + Format is a hexdump with some header information at the beginning, + addresses on the left, and data on right. + + @param tofile file-like object to dump to + @param width number of bytes per line (i.e. columns) + @param withpadding print padding character instead of '--' + @raise ValueError if width is not a positive integer + """ + + if not isinstance(width,int) or width < 1: + raise ValueError('width must be a positive integer.') + # The integer can be of float type - does not work with bit operations + width = int(width) + if tofile is None: + tofile = sys.stdout + + # start addr possibly + if self.start_addr is not None: + cs = self.start_addr.get('CS') + ip = self.start_addr.get('IP') + eip = self.start_addr.get('EIP') + if eip is not None and cs is None and ip is None: + tofile.write('EIP = 0x%08X\n' % eip) + elif eip is None and cs is not None and ip is not None: + tofile.write('CS = 0x%04X, IP = 0x%04X\n' % (cs, ip)) + else: + tofile.write('start_addr = %r\n' % start_addr) + # actual data + addresses = dict_keys(self._buf) + if addresses: + addresses.sort() + minaddr = addresses[0] + maxaddr = addresses[-1] + startaddr = (minaddr // width) * width + endaddr = ((maxaddr // width) + 1) * width + maxdigits = max(len(hex(endaddr)) - 2, 4) # Less 2 to exclude '0x' + templa = '%%0%dX' % maxdigits + rangewidth = range_l(width) + if withpadding: + pad = self.padding + else: + pad = None + for i in range_g(startaddr, endaddr, width): + tofile.write(templa % i) + tofile.write(' ') + s = [] + for j in rangewidth: + x = self._buf.get(i+j, pad) + if x is not None: + tofile.write(' %02X' % x) + if 32 <= x < 127: # GNU less does not like 0x7F (128 decimal) so we'd better show it as dot + s.append(chr(x)) + else: + s.append('.') + else: + tofile.write(' --') + s.append(' ') + tofile.write(' |' + ''.join(s) + '|\n') + + def merge(self, other, overlap='error'): + """Merge content of other IntelHex object into current object (self). + @param other other IntelHex object. + @param overlap action on overlap of data or starting addr: + - error: raising OverlapError; + - ignore: ignore other data and keep current data + in overlapping region; + - replace: replace data with other data + in overlapping region. + + @raise TypeError if other is not instance of IntelHex + @raise ValueError if other is the same object as self + (it can't merge itself) + @raise ValueError if overlap argument has incorrect value + @raise AddressOverlapError on overlapped data + """ + # check args + if not isinstance(other, IntelHex): + raise TypeError('other should be IntelHex object') + if other is self: + raise ValueError("Can't merge itself") + if overlap not in ('error', 'ignore', 'replace'): + raise ValueError("overlap argument should be either " + "'error', 'ignore' or 'replace'") + # merge data + this_buf = self._buf + other_buf = other._buf + for i in other_buf: + if i in this_buf: + if overlap == 'error': + raise AddressOverlapError( + 'Data overlapped at address 0x%X' % i) + elif overlap == 'ignore': + continue + this_buf[i] = other_buf[i] + # merge start_addr + if self.start_addr != other.start_addr: + if self.start_addr is None: # set start addr from other + self.start_addr = other.start_addr + elif other.start_addr is None: # keep existing start addr + pass + else: # conflict + if overlap == 'error': + raise AddressOverlapError( + 'Starting addresses are different') + elif overlap == 'replace': + self.start_addr = other.start_addr + + def segments(self, min_gap=1): + """Return a list of ordered tuple objects, representing contiguous occupied data addresses. + Each tuple has a length of two and follows the semantics of the range and xrange objects. + The second entry of the tuple is always an integer greater than the first entry. + @param min_gap the minimum gap size between data in order to separate the segments + """ + addresses = self.addresses() + if not addresses: + return [] + elif len(addresses) == 1: + return([(addresses[0], addresses[0]+1)]) + adjacent_differences = [(b - a) for (a, b) in zip(addresses[:-1], addresses[1:])] + breaks = [i for (i, x) in enumerate(adjacent_differences) if x > min_gap] + endings = [addresses[b] for b in breaks] + endings.append(addresses[-1]) + beginnings = [addresses[b+1] for b in breaks] + beginnings.insert(0, addresses[0]) + return [(a, b+1) for (a, b) in zip(beginnings, endings)] + + def get_memory_size(self): + """Returns the approximate memory footprint for data.""" + n = sys.getsizeof(self) + n += sys.getsizeof(self.padding) + n += total_size(self.start_addr) + n += total_size(self._buf) + n += sys.getsizeof(self._offset) + return n + +#/IntelHex + + +class IntelHex16bit(IntelHex): + """Access to data as 16-bit words. Intended to use with Microchip HEX files.""" + + def __init__(self, source=None): + """Construct class from HEX file + or from instance of ordinary IntelHex class. If IntelHex object + is passed as source, the original IntelHex object should not be used + again because this class will alter it. This class leaves padding + alone unless it was precisely 0xFF. In that instance it is sign + extended to 0xFFFF. + + @param source file name of HEX file or file object + or instance of ordinary IntelHex class. + Will also accept dictionary from todict method. + """ + if isinstance(source, IntelHex): + # from ihex8 + self.padding = source.padding + self.start_addr = source.start_addr + # private members + self._buf = source._buf + self._offset = source._offset + elif isinstance(source, dict): + raise IntelHexError("IntelHex16bit does not support initialization from dictionary yet.\n" + "Patches are welcome.") + else: + IntelHex.__init__(self, source) + + if self.padding == 0x0FF: + self.padding = 0x0FFFF + + def __getitem__(self, addr16): + """Get 16-bit word from address. + Raise error if only one byte from the pair is set. + We assume a Little Endian interpretation of the hex file. + + @param addr16 address of word (addr8 = 2 * addr16). + @return word if bytes exists in HEX file, or self.padding + if no data found. + """ + addr1 = addr16 * 2 + addr2 = addr1 + 1 + byte1 = self._buf.get(addr1, None) + byte2 = self._buf.get(addr2, None) + + if byte1 != None and byte2 != None: + return byte1 | (byte2 << 8) # low endian + + if byte1 == None and byte2 == None: + return self.padding + + raise BadAccess16bit(address=addr16) + + def __setitem__(self, addr16, word): + """Sets the address at addr16 to word assuming Little Endian mode. + """ + addr_byte = addr16 * 2 + b = divmod(word, 256) + self._buf[addr_byte] = b[1] + self._buf[addr_byte+1] = b[0] + + def minaddr(self): + '''Get minimal address of HEX content in 16-bit mode. + + @return minimal address used in this object + ''' + aa = dict_keys(self._buf) + if aa == []: + return 0 + else: + return min(aa)>>1 + + def maxaddr(self): + '''Get maximal address of HEX content in 16-bit mode. + + @return maximal address used in this object + ''' + aa = dict_keys(self._buf) + if aa == []: + return 0 + else: + return max(aa)>>1 + + def tobinarray(self, start=None, end=None, size=None): + '''Convert this object to binary form as array (of 2-bytes word data). + If start and end unspecified, they will be inferred from the data. + @param start start address of output data. + @param end end address of output data (inclusive). + @param size size of the block (number of words), + used with start or end parameter. + @return array of unsigned short (uint16_t) data. + ''' + bin = array('H') + + if self._buf == {} and None in (start, end): + return bin + + if size is not None and size <= 0: + raise ValueError("tobinarray: wrong value for size") + + start, end = self._get_start_end(start, end, size) + + for addr in range_g(start, end+1): + bin.append(self[addr]) + + return bin + + +#/class IntelHex16bit + + +def hex2bin(fin, fout, start=None, end=None, size=None, pad=None): + """Hex-to-Bin convertor engine. + @return 0 if all OK + + @param fin input hex file (filename or file-like object) + @param fout output bin file (filename or file-like object) + @param start start of address range (optional) + @param end end of address range (inclusive; optional) + @param size size of resulting file (in bytes) (optional) + @param pad padding byte (optional) + """ + try: + h = IntelHex(fin) + except HexReaderError: + e = sys.exc_info()[1] # current exception + txt = "ERROR: bad HEX file: %s" % str(e) + print(txt) + return 1 + + # start, end, size + if size != None and size != 0: + if end == None: + if start == None: + start = h.minaddr() + end = start + size - 1 + else: + if (end+1) >= size: + start = end + 1 - size + else: + start = 0 + + try: + if pad is not None: + # using .padding attribute rather than pad argument to function call + h.padding = pad + h.tobinfile(fout, start, end) + except IOError: + e = sys.exc_info()[1] # current exception + txt = "ERROR: Could not write to file: %s: %s" % (fout, str(e)) + print(txt) + return 1 + + return 0 +#/def hex2bin + + +def bin2hex(fin, fout, offset=0): + """Simple bin-to-hex convertor. + @return 0 if all OK + + @param fin input bin file (filename or file-like object) + @param fout output hex file (filename or file-like object) + @param offset starting address offset for loading bin + """ + h = IntelHex() + try: + h.loadbin(fin, offset) + except IOError: + e = sys.exc_info()[1] # current exception + txt = 'ERROR: unable to load bin file:', str(e) + print(txt) + return 1 + + try: + h.tofile(fout, format='hex') + except IOError: + e = sys.exc_info()[1] # current exception + txt = "ERROR: Could not write to file: %s: %s" % (fout, str(e)) + print(txt) + return 1 + + return 0 +#/def bin2hex + + +def diff_dumps(ih1, ih2, tofile=None, name1="a", name2="b", n_context=3): + """Diff 2 IntelHex objects and produce unified diff output for their + hex dumps. + + @param ih1 first IntelHex object to compare + @param ih2 second IntelHex object to compare + @param tofile file-like object to write output + @param name1 name of the first hex file to show in the diff header + @param name2 name of the first hex file to show in the diff header + @param n_context number of context lines in the unidiff output + """ + def prepare_lines(ih): + sio = StringIO() + ih.dump(sio) + dump = sio.getvalue() + lines = dump.splitlines() + return lines + a = prepare_lines(ih1) + b = prepare_lines(ih2) + import difflib + result = list(difflib.unified_diff(a, b, fromfile=name1, tofile=name2, n=n_context, lineterm='')) + if tofile is None: + tofile = sys.stdout + output = '\n'.join(result)+'\n' + tofile.write(output) + + +class Record(object): + """Helper methods to build valid ihex records.""" + + def _from_bytes(bytes): + """Takes a list of bytes, computes the checksum, and outputs the entire + record as a string. bytes should be the hex record without the colon + or final checksum. + + @param bytes list of byte values so far to pack into record. + @return String representation of one HEX record + """ + assert len(bytes) >= 4 + # calculate checksum + s = (-sum(bytes)) & 0x0FF + bin = array('B', bytes + [s]) + return ':' + asstr(hexlify(array_tobytes(bin))).upper() + _from_bytes = staticmethod(_from_bytes) + + def data(offset, bytes): + """Return Data record. This constructs the full record, including + the length information, the record type (0x00), the + checksum, and the offset. + + @param offset load offset of first byte. + @param bytes list of byte values to pack into record. + + @return String representation of one HEX record + """ + assert 0 <= offset < 65536 + assert 0 < len(bytes) < 256 + b = [len(bytes), (offset>>8)&0x0FF, offset&0x0FF, 0x00] + bytes + return Record._from_bytes(b) + data = staticmethod(data) + + def eof(): + """Return End of File record as a string. + @return String representation of Intel Hex EOF record + """ + return ':00000001FF' + eof = staticmethod(eof) + + def extended_segment_address(usba): + """Return Extended Segment Address Record. + @param usba Upper Segment Base Address. + + @return String representation of Intel Hex USBA record. + """ + b = [2, 0, 0, 0x02, (usba>>8)&0x0FF, usba&0x0FF] + return Record._from_bytes(b) + extended_segment_address = staticmethod(extended_segment_address) + + def start_segment_address(cs, ip): + """Return Start Segment Address Record. + @param cs 16-bit value for CS register. + @param ip 16-bit value for IP register. + + @return String representation of Intel Hex SSA record. + """ + b = [4, 0, 0, 0x03, (cs>>8)&0x0FF, cs&0x0FF, + (ip>>8)&0x0FF, ip&0x0FF] + return Record._from_bytes(b) + start_segment_address = staticmethod(start_segment_address) + + def extended_linear_address(ulba): + """Return Extended Linear Address Record. + @param ulba Upper Linear Base Address. + + @return String representation of Intel Hex ELA record. + """ + b = [2, 0, 0, 0x04, (ulba>>8)&0x0FF, ulba&0x0FF] + return Record._from_bytes(b) + extended_linear_address = staticmethod(extended_linear_address) + + def start_linear_address(eip): + """Return Start Linear Address Record. + @param eip 32-bit linear address for the EIP register. + + @return String representation of Intel Hex SLA record. + """ + b = [4, 0, 0, 0x05, (eip>>24)&0x0FF, (eip>>16)&0x0FF, + (eip>>8)&0x0FF, eip&0x0FF] + return Record._from_bytes(b) + start_linear_address = staticmethod(start_linear_address) + + +class _BadFileNotation(Exception): + """Special error class to use with _get_file_and_addr_range.""" + pass + +def _get_file_and_addr_range(s, _support_drive_letter=None): + """Special method for hexmerge.py script to split file notation + into 3 parts: (filename, start, end) + + @raise _BadFileNotation when string cannot be safely split. + """ + if _support_drive_letter is None: + _support_drive_letter = (os.name == 'nt') + drive = '' + if _support_drive_letter: + if s[1:2] == ':' and s[0].upper() in ''.join([chr(i) for i in range_g(ord('A'), ord('Z')+1)]): + drive = s[:2] + s = s[2:] + parts = s.split(':') + n = len(parts) + if n == 1: + fname = parts[0] + fstart = None + fend = None + elif n != 3: + raise _BadFileNotation + else: + fname = parts[0] + def ascii_hex_to_int(ascii): + if ascii is not None: + try: + return int(ascii, 16) + except ValueError: + raise _BadFileNotation + return ascii + fstart = ascii_hex_to_int(parts[1] or None) + fend = ascii_hex_to_int(parts[2] or None) + return drive+fname, fstart, fend + + +## +# IntelHex Errors Hierarchy: +# +# IntelHexError - basic error +# HexReaderError - general hex reader error +# AddressOverlapError - data for the same address overlap +# HexRecordError - hex record decoder base error +# RecordLengthError - record has invalid length +# RecordTypeError - record has invalid type (RECTYP) +# RecordChecksumError - record checksum mismatch +# EOFRecordError - invalid EOF record (type 01) +# ExtendedAddressRecordError - extended address record base error +# ExtendedSegmentAddressRecordError - invalid extended segment address record (type 02) +# ExtendedLinearAddressRecordError - invalid extended linear address record (type 04) +# StartAddressRecordError - start address record base error +# StartSegmentAddressRecordError - invalid start segment address record (type 03) +# StartLinearAddressRecordError - invalid start linear address record (type 05) +# DuplicateStartAddressRecordError - start address record appears twice +# InvalidStartAddressValueError - invalid value of start addr record +# _EndOfFile - it's not real error, used internally by hex reader as signal that EOF record found +# BadAccess16bit - not enough data to read 16 bit value (deprecated, see NotEnoughDataError) +# NotEnoughDataError - not enough data to read N contiguous bytes +# EmptyIntelHexError - requested operation cannot be performed with empty object + +class IntelHexError(Exception): + '''Base Exception class for IntelHex module''' + + _fmt = 'IntelHex base error' #: format string + + def __init__(self, msg=None, **kw): + """Initialize the Exception with the given message. + """ + self.msg = msg + for key, value in dict_items_g(kw): + setattr(self, key, value) + + def __str__(self): + """Return the message in this Exception.""" + if self.msg: + return self.msg + try: + return self._fmt % self.__dict__ + except (NameError, ValueError, KeyError): + e = sys.exc_info()[1] # current exception + return 'Unprintable exception %s: %s' \ + % (repr(e), str(e)) + +class _EndOfFile(IntelHexError): + """Used for internal needs only.""" + _fmt = 'EOF record reached -- signal to stop read file' + +class HexReaderError(IntelHexError): + _fmt = 'Hex reader base error' + +class AddressOverlapError(HexReaderError): + _fmt = 'Hex file has data overlap at address 0x%(address)X on line %(line)d' + +# class NotAHexFileError was removed in trunk.revno.54 because it's not used + + +class HexRecordError(HexReaderError): + _fmt = 'Hex file contains invalid record at line %(line)d' + + +class RecordLengthError(HexRecordError): + _fmt = 'Record at line %(line)d has invalid length' + +class RecordTypeError(HexRecordError): + _fmt = 'Record at line %(line)d has invalid record type' + +class RecordChecksumError(HexRecordError): + _fmt = 'Record at line %(line)d has invalid checksum' + +class EOFRecordError(HexRecordError): + _fmt = 'File has invalid End-of-File record' + + +class ExtendedAddressRecordError(HexRecordError): + _fmt = 'Base class for extended address exceptions' + +class ExtendedSegmentAddressRecordError(ExtendedAddressRecordError): + _fmt = 'Invalid Extended Segment Address Record at line %(line)d' + +class ExtendedLinearAddressRecordError(ExtendedAddressRecordError): + _fmt = 'Invalid Extended Linear Address Record at line %(line)d' + + +class StartAddressRecordError(HexRecordError): + _fmt = 'Base class for start address exceptions' + +class StartSegmentAddressRecordError(StartAddressRecordError): + _fmt = 'Invalid Start Segment Address Record at line %(line)d' + +class StartLinearAddressRecordError(StartAddressRecordError): + _fmt = 'Invalid Start Linear Address Record at line %(line)d' + +class DuplicateStartAddressRecordError(StartAddressRecordError): + _fmt = 'Start Address Record appears twice at line %(line)d' + +class InvalidStartAddressValueError(StartAddressRecordError): + _fmt = 'Invalid start address value: %(start_addr)s' + + +class NotEnoughDataError(IntelHexError): + _fmt = ('Bad access at 0x%(address)X: ' + 'not enough data to read %(length)d contiguous bytes') + +class BadAccess16bit(NotEnoughDataError): + _fmt = 'Bad access at 0x%(address)X: not enough data to read 16 bit value' + +class EmptyIntelHexError(IntelHexError): + _fmt = "Requested operation cannot be executed with empty object" diff --git a/tools/python/esptool/intelhex/__main__.py b/tools/python/esptool/intelhex/__main__.py new file mode 100644 index 00000000..50db2840 --- /dev/null +++ b/tools/python/esptool/intelhex/__main__.py @@ -0,0 +1,39 @@ +# Copyright (c) 2016-2018, Alexander Belchenko +# All rights reserved. +# +# Redistribution and use in source and binary forms, +# with or without modification, are permitted provided +# that the following conditions are met: +# +# * Redistributions of source code must retain +# the above copyright notice, this list of conditions +# and the following disclaimer. +# * Redistributions in binary form must reproduce +# the above copyright notice, this list of conditions +# and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * Neither the name of the author nor the names +# of its contributors may be used to endorse +# or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, +# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +if __name__ == '__main__': + print("Welcome to IntelHex Python library.") + print() + print("The intelhex package has some executable points:") + print(" python -m intelhex.test -- easy way to run unit tests.") + print(" python -m intelhex.bench -- run benchmarks.") diff --git a/tools/python/esptool/intelhex/__version__.py b/tools/python/esptool/intelhex/__version__.py new file mode 100644 index 00000000..36edd5c2 --- /dev/null +++ b/tools/python/esptool/intelhex/__version__.py @@ -0,0 +1,3 @@ +# IntelHex library version information +version_info = (2, 3, 0) +version_str = '.'.join([str(i) for i in version_info]) diff --git a/tools/python/esptool/intelhex/bench.py b/tools/python/esptool/intelhex/bench.py new file mode 100644 index 00000000..df484479 --- /dev/null +++ b/tools/python/esptool/intelhex/bench.py @@ -0,0 +1,360 @@ +#!/usr/bin/python +# (c) Alexander Belchenko, 2007, 2009 + +# [2013/08] NOTE: This file is keeping for historical reasons. +# It may or may not work actually with current version of intelhex, +# and most likely it requires some fixes here and there. + +"""Benchmarking. + +Run each test 3 times and get median value. +Using 10K array as base test time. + +Each other test compared with base with next formula:: + + Tc * Nb + q = --------- + Tb * Nc + +Here: + +* Tc - execution time of current test +* Tb - execution time of base +* Nb - array size of base (10K) +* Nc - array size of current test + +If resulting value is ``q <= 1.0`` it's the best possible result, +i.e. time increase proportionally to array size. +""" + +import gc +import sys +import time + +import intelhex +from intelhex.compat import StringIO, range_g + +def median(values): + """Return median value for the list of values. + @param values: list of values for processing. + @return: median value. + """ + values.sort() + n = int(len(values) / 2) + return values[n] + +def run_test(func, fobj): + """Run func with argument fobj and measure execution time. + @param func: function for test + @param fobj: data for test + @return: execution time + """ + gc.disable() + try: + begin = time.time() + func(fobj) + end = time.time() + finally: + gc.enable() + return end - begin + +def run_readtest_N_times(func, hexstr, n): + """Run each test N times. + @param func: function for test + @param hexstr: string with content of hex file to read + @param n: times to repeat. + @return: (median time, times list) + """ + assert n > 0 + times = [] + for i in range_g(n): + sio = StringIO(hexstr) + times.append(run_test(func, sio)) + sio.close() + t = median(times) + return t, times + +def run_writetest_N_times(func, n): + """Run each test N times. + @param func: function for test + @param n: times to repeat. + @return: (median time, times list) + """ + assert n > 0 + times = [] + for i in range_g(n): + sio = StringIO() + times.append(run_test(func, sio)) + sio.close() + t = median(times) + return t, times + +def time_coef(tc, nc, tb, nb): + """Return time coefficient relative to base numbers. + @param tc: current test time + @param nc: current test data size + @param tb: base test time + @param nb: base test data size + @return: time coef. + """ + tc = float(tc) + nc = float(nc) + tb = float(tb) + nb = float(nb) + q = (tc * nb) / (tb * nc) + return q + +def get_test_data(n1, offset, n2): + """Create test data on given pattern. + @param n1: size of first part of array at base address 0. + @param offset: offset for second part of array. + @param n2: size of second part of array at given offset. + @return: (overall size, hex file, IntelHex object) + """ + # make IntelHex object + ih = intelhex.IntelHex() + addr = 0 + for i in range_g(n1): + ih[addr] = addr % 256 + addr += 1 + addr += offset + for i in range_g(n2): + ih[addr] = addr % 256 + addr += 1 + # make hex file + sio = StringIO() + ih.write_hex_file(sio) + hexstr = sio.getvalue() + sio.close() + # + return n1+n2, hexstr, ih + +def get_base_50K(): + return get_test_data(50000, 0, 0) + +def get_250K(): + return get_test_data(250000, 0, 0) + +def get_100K_100K(): + return get_test_data(100000, 1000000, 100000) + +def get_0_100K(): + return get_test_data(0, 1000000, 100000) + +def get_1M(): + return get_test_data(1000000, 0, 0) + + +class Measure(object): + """Measure execution time helper.""" + + data_set = [ + # (data name, getter) + ('base 50K', get_base_50K), # first should be base numbers + ('250K', get_250K), + ('1M', get_1M), + ('100K+100K', get_100K_100K), + ('0+100K', get_0_100K), + ] + + def __init__(self, n=3, read=True, write=True): + self.n = n + self.read = read + self.write = write + self.results = [] + + def measure_one(self, data): + """Do measuring of read and write operations. + @param data: 3-tuple from get_test_data + @return: (time readhex, time writehex) + """ + _unused, hexstr, ih = data + tread, twrite = 0.0, 0.0 + if self.read: + tread = run_readtest_N_times(intelhex.IntelHex, hexstr, self.n)[0] + if self.write: + twrite = run_writetest_N_times(ih.write_hex_file, self.n)[0] + return tread, twrite + + def measure_all(self): + for name, getter in self.data_set: + data = getter() + times = self.measure_one(data) + self.results.append((name, times, data[0])) + + def print_report(self, to_file=None): + if to_file is None: + to_file = sys.stdout + + base_title, base_times, base_n = self.results[0] + base_read, base_write = base_times + read_report = ['%-10s\t%7.3f' % (base_title, base_read)] + write_report = ['%-10s\t%7.3f' % (base_title, base_write)] + + for item in self.results[1:]: + cur_title, cur_times, cur_n = item + cur_read, cur_write = cur_times + if self.read: + qread = time_coef(cur_read, cur_n, + base_read, base_n) + read_report.append('%-10s\t%7.3f\t%7.3f' % (cur_title, + cur_read, + qread)) + if self.write: + qwrite = time_coef(cur_write, cur_n, + base_write, base_n) + write_report.append('%-10s\t%7.3f\t%7.3f' % (cur_title, + cur_write, + qwrite)) + if self.read: + to_file.write('Read operation:\n') + to_file.write('\n'.join(read_report)) + to_file.write('\n\n') + if self.write: + to_file.write('Write operation:\n') + to_file.write('\n'.join(write_report)) + to_file.write('\n\n') + + +HELP = """\ +Usage: python _bench.py [OPTIONS] + +Options: + -h this help + -n N repeat tests N times + -r run only tests for read operation + -w run only tests for write operation + +If option -r or -w is not specified then all tests will be run. +""" + + +def main(argv=None): + """Main function to run benchmarks. + @param argv: command-line arguments. + @return: exit code (0 is OK). + """ + import getopt + + # default values + test_read = None + test_write = None + n = 3 # number of repeat + + if argv is None: + argv = sys.argv[1:] + + try: + opts, args = getopt.getopt(argv, 'hn:rw', []) + + for o,a in opts: + if o == '-h': + print(HELP) + return 0 + elif o == '-n': + n = int(a) + elif o == '-r': + test_read = True + elif o == '-w': + test_write = True + + if args: + raise getopt.GetoptError('Arguments are not used.') + except getopt.GetoptError: + msg = sys.exc_info()[1] # current exception + txt = str(msg) + print(txt) + return 1 + + if (test_read, test_write) == (None, None): + test_read = test_write = True + + m = Measure(n, test_read, test_write) + m.measure_all() + m.print_report() + + return 0 + + +if __name__ == '__main__': + sys.exit(main(sys.argv[1:])) + + +""" + +Some Results +************ + + +21/04/2007 revno.40 +Python 2.5 @ Windows XP, Intel Celeron M CPU 430 @ 1.73GHz + +Read operation: +base 10K 0.031 +100K 0.360 1.161 +1M 3.500 1.129 +100K+100K 0.719 1.160 +0+100K 0.360 1.161 + +Write operation: +base 10K 0.031 +100K 0.297 0.958 +1M 2.953 0.953 +100K+100K 1.328 2.142 +0+100K 0.312 1.006 + + +21/04/2007 revno.46 +Python 2.5 @ Windows XP, Intel Celeron M CPU 430 @ 1.73GHz + +Read operation: +base 10K 0.016 +100K 0.203 1.269 +1M 2.000 1.250 +100K+100K 0.422 1.319 +0+100K 0.203 1.269 + +Write operation: +base 10K 0.031 +100K 0.297 0.958 +1M 2.969 0.958 +100K+100K 1.328 2.142 +0+100K 0.312 1.006 + + +22/04/2007 revno.48 +Python 2.5 @ Windows XP, Intel Celeron M CPU 430 @ 1.73GHz + +Read operation: +base 10K 0.016 +100K 0.187 1.169 +1M 1.891 1.182 +100K+100K 0.406 1.269 +0+100K 0.188 1.175 + +Write operation: +base 10K 0.031 +100K 0.296 0.955 +1M 2.969 0.958 +100K+100K 1.328 2.142 +0+100K 0.312 1.006 + + +19/08/2008 revno.72 +Python 2.5.2 @ Windows XP, Intel Celeron M CPU 430 @ 1.73GHz + +Read operation: +base 10K 0.016 +100K 0.171 1.069 +1M 1.734 1.084 +100K+100K 0.375 1.172 +0+100K 0.172 1.075 + +Write operation: +base 10K 0.016 +100K 0.156 0.975 +1M 1.532 0.957 +100K+100K 0.344 1.075 +0+100K 0.156 0.975 + +""" diff --git a/tools/python/esptool/intelhex/compat.py b/tools/python/esptool/intelhex/compat.py new file mode 100644 index 00000000..2a6bee6c --- /dev/null +++ b/tools/python/esptool/intelhex/compat.py @@ -0,0 +1,160 @@ +# Copyright (c) 2011, Bernhard Leiner +# Copyright (c) 2013-2018 Alexander Belchenko +# All rights reserved. +# +# Redistribution and use in source and binary forms, +# with or without modification, are permitted provided +# that the following conditions are met: +# +# * Redistributions of source code must retain +# the above copyright notice, this list of conditions +# and the following disclaimer. +# * Redistributions in binary form must reproduce +# the above copyright notice, this list of conditions +# and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * Neither the name of the author nor the names +# of its contributors may be used to endorse +# or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, +# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +'''Compatibility functions for python 2 and 3. + +@author Bernhard Leiner (bleiner AT gmail com) +@author Alexander Belchenko (alexander belchenko AT gmail com) +''' + +__docformat__ = "javadoc" + + +import sys, array + + +if sys.version_info[0] >= 3: + # Python 3 + Python = 3 + + def asbytes(s): + if isinstance(s, bytes): + return s + return s.encode('latin1') + def asstr(s): + if isinstance(s, str): + return s + return s.decode('latin1') + + # for python >= 3.2 use 'tobytes', otherwise 'tostring' + array_tobytes = array.array.tobytes if sys.version_info[1] >= 2 else array.array.tostring + + IntTypes = (int,) + StrType = str + UnicodeType = str + + range_g = range # range generator + def range_l(*args): # range list + return list(range(*args)) + + def dict_keys(dikt): # dict keys list + return list(dikt.keys()) + def dict_keys_g(dikt): # dict keys generator + return dikt.keys() + def dict_items_g(dikt): # dict items generator + return dikt.items() + + from io import StringIO, BytesIO + + def get_binary_stdout(): + return sys.stdout.buffer + + def get_binary_stdin(): + return sys.stdin.buffer + +else: + # Python 2 + Python = 2 + + asbytes = str + asstr = str + + array_tobytes = array.array.tostring + + IntTypes = (int, long) + StrType = basestring + UnicodeType = unicode + + #range_g = xrange # range generator + def range_g(*args): + # we want to use xrange here but on python 2 it does not work with long ints + try: + return xrange(*args) + except OverflowError: + start = 0 + stop = 0 + step = 1 + n = len(args) + if n == 1: + stop = args[0] + elif n == 2: + start, stop = args + elif n == 3: + start, stop, step = args + else: + raise TypeError('wrong number of arguments in range_g call!') + if step == 0: + raise ValueError('step cannot be zero') + if step > 0: + def up(start, stop, step): + while start < stop: + yield start + start += step + return up(start, stop, step) + else: + def down(start, stop, step): + while start > stop: + yield start + start += step + return down(start, stop, step) + + range_l = range # range list + + def dict_keys(dikt): # dict keys list + return dikt.keys() + def dict_keys_g(dikt): # dict keys generator + return dikt.keys() + def dict_items_g(dikt): # dict items generator + return dikt.items() + + from cStringIO import StringIO + BytesIO = StringIO + + import os + def _force_stream_binary(stream): + """Force binary mode for stream on Windows.""" + if os.name == 'nt': + f_fileno = getattr(stream, 'fileno', None) + if f_fileno: + fileno = f_fileno() + if fileno >= 0: + import msvcrt + msvcrt.setmode(fileno, os.O_BINARY) + return stream + + def get_binary_stdout(): + return _force_stream_binary(sys.stdout) + + def get_binary_stdin(): + return _force_stream_binary(sys.stdin) diff --git a/tools/python/esptool/intelhex/getsizeof.py b/tools/python/esptool/intelhex/getsizeof.py new file mode 100644 index 00000000..b91d7ebc --- /dev/null +++ b/tools/python/esptool/intelhex/getsizeof.py @@ -0,0 +1,64 @@ +# Recursive version sys.getsizeof(). Extendable with custom handlers. +# Code from http://code.activestate.com/recipes/577504/ +# Created by Raymond Hettinger on Fri, 17 Dec 2010 (MIT) + +import sys +from itertools import chain +from collections import deque +try: + from reprlib import repr +except ImportError: + pass + +def total_size(o, handlers={}, verbose=False): + """ Returns the approximate memory footprint an object and all of its contents. + + Automatically finds the contents of the following builtin containers and + their subclasses: tuple, list, deque, dict, set and frozenset. + To search other containers, add handlers to iterate over their contents: + + handlers = {SomeContainerClass: iter, + OtherContainerClass: OtherContainerClass.get_elements} + + """ + dict_handler = lambda d: chain.from_iterable(d.items()) + all_handlers = {tuple: iter, + list: iter, + deque: iter, + dict: dict_handler, + set: iter, + frozenset: iter, + } + all_handlers.update(handlers) # user handlers take precedence + seen = set() # track which object id's have already been seen + default_size = sys.getsizeof(0) # estimate sizeof object without __sizeof__ + + def sizeof(o): + if id(o) in seen: # do not double count the same object + return 0 + seen.add(id(o)) + s = sys.getsizeof(o, default_size) + + if verbose: + print(s, type(o), repr(o))#, file=stderr) + + for typ, handler in all_handlers.items(): + if isinstance(o, typ): + s += sum(map(sizeof, handler(o))) + break + return s + + return sizeof(o) + + +##### Example call ##### + +if __name__ == '__main__': + #d = dict(a=1, b=2, c=3, d=[4,5,6,7], e='a string of chars') + print("dict 3 elements") + d = {0:0xFF, 1:0xEE, 2:0xCC} + print(total_size(d, verbose=True)) + + #print("array 3 elements") + #import array + #print(total_size(array.array('B', b'\x01\x02\x03'))) diff --git a/tools/python/esptool/intelhex/test.py b/tools/python/esptool/intelhex/test.py new file mode 100644 index 00000000..50276b0a --- /dev/null +++ b/tools/python/esptool/intelhex/test.py @@ -0,0 +1,1799 @@ +# Copyright (c) 2005-2018, Alexander Belchenko +# All rights reserved. +# +# Redistribution and use in source and binary forms, +# with or without modification, are permitted provided +# that the following conditions are met: +# +# * Redistributions of source code must retain +# the above copyright notice, this list of conditions +# and the following disclaimer. +# * Redistributions in binary form must reproduce +# the above copyright notice, this list of conditions +# and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * Neither the name of the author nor the names +# of its contributors may be used to endorse +# or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, +# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""Test suite for IntelHex library.""" + +import array +import os +import shlex +import subprocess +import sys +import tempfile +import unittest + +import intelhex +from intelhex import ( + IntelHex, + IntelHexError, + HexReaderError, + AddressOverlapError, + HexRecordError, + RecordLengthError, + RecordTypeError, + RecordChecksumError, + EOFRecordError, + ExtendedSegmentAddressRecordError, + ExtendedLinearAddressRecordError, + StartSegmentAddressRecordError, + StartLinearAddressRecordError, + DuplicateStartAddressRecordError, + InvalidStartAddressValueError, + _EndOfFile, + BadAccess16bit, + hex2bin, + Record, + ) +from intelhex import compat +from intelhex.compat import ( + BytesIO, + StringIO, + UnicodeType, + array_tobytes, + asbytes, + asstr, + dict_items_g, + range_g, + range_l, + ) +from intelhex.__version__ import version_str + +__docformat__ = 'restructuredtext' + +## +# Data for tests + +hex8 = '''\ +:1004E300CFF0FBE2FDF220FF20F2E120E2FBE6F396 +:1004F3000A00FDE0E1E2E3B4E4E5BAE6E7B3BFE80E +:10050300E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8E0 +:10051300F9FCFEFF00C0C1C2C3A5C4C5AAC6C7B2C9 +:10052300AFC8C9CACBCCCDCECFD0D1D2D3D4D5D6F8 +:07053300D7D8D9DCDEDF00A0 +:10053A0078227C007D007BFF7A0479F57E007F2398 +:10054A0012042F78457C007D007BFF7A0579187E9E +:10055A00007F2212042F759850438920758DDDD2B1 +:10056A008ED2996390017BFF7A0479E31200658049 +:01057A00FE82 +:030000000205A254 +:0C05A200787FE4F6D8FD75817A02053AF6 +:10035F00E709F608DFFA8046E709F208DFFA803E80 +:10036F0088828C83E709F0A3DFFA8032E309F6086D +:10037F00DFFA8078E309F208DFFA807088828C83D5 +:10038F00E309F0A3DFFA806489828A83E0A3F60889 +:10039F00DFFA805889828A83E0A3F208DFFA804C63 +:1003AF0080D280FA80C680D4806980F2803380103A +:1003BF0080A680EA809A80A880DA80E280CA8033A3 +:1003CF0089828A83ECFAE493A3C8C582C8CCC5831B +:1003DF00CCF0A3C8C582C8CCC583CCDFE9DEE780EB +:1003EF000D89828A83E493A3F608DFF9ECFAA9F06A +:1003FF00EDFB2289828A83ECFAE0A3C8C582C8CCC0 +:10040F00C583CCF0A3C8C582C8CCC583CCDFEADED8 +:10041F00E880DB89828A83E493A3F208DFF980CC3A +:10042F0088F0EF60010E4E60C388F0ED2402B40433 +:10043F000050B9F582EB2402B4040050AF232345DA +:06044F0082239003AF734D +:10000300E576246AF8E60576227867300702786A8F +:10001300E475F0011204AD0204552000EB7F2ED2EB +:10002300008018EF540F2490D43440D4FF30040BD5 +:10003300EF24BFB41A0050032461FFE57760021573 +:1000430077057AE57A7002057930070D7867E475EC +:10005300F0011204ADEF02049B02057B7403D20787 +:100063008003E4C207F5768B678A688969E4F577CC +:10007300F579F57AE57760077F2012003E80F57504 +:1000830078FFC201C200C202C203C205C206C2088F +:1000930012000CFF700D3007057F0012004FAF7A7E +:1000A300AE7922B4255FC2D5C20412000CFF24D05E +:1000B300B40A00501A75F00A787730D50508B6FFF0 +:1000C3000106C6A426F620D5047002D20380D924E3 +:1000D300CFB41A00EF5004C2E5D20402024FD2019A +:1000E30080C6D20080C0D20280BCD2D580BAD205ED +:1000F30080B47F2012003E2002077401B5770040D0 +:10010300F1120003FF12003E020077D208D20680EC +:1001130095120003FB120003FA120003F94A4B7015 +:100123000679207A037BFF20022EE577602A7E0082 +:100133008E8275830012046E60060EEE657870F091 +:10014300C2D5EBC0E0EAC0E0E9C0E0EE120296D00F +:10015300E0F9D0E0FAD0E0FB120455FF60AAEBC04F +:10016300E0EAC0E0E9C0E012003ED0E02401F9D0AB +:10017300E03400FAD0E0FBE5780460DCD578D98080 +:10018300877BFF7A027992D202809C791080027970 +:1001930008C206C2088008D2D5790A8004790AC247 +:1001A300D5E578047002F578E4FAFDFEFF1200034A +:1001B300FC7B08200113120003FD7B1030000A12A0 +:1001C3000003FE120003FF7B20EC3382D592D5504F +:1001D30013C3E43000069FFFE49EFEE42001039D69 +:1001E300FDE49CFCE4CBF8C201EC700CCFCECDCC8B +:1001F300E824F8F870F38017C3EF33FFEE33FEED16 +:1002030033FDEC33FCEB33FB994002FB0FD8E9EBF6 +:10021300300105F8D0E0C448B201C0E00AEC4D4E0D +:100223004F78207B0070C2EAB5780040BCC0E01272 +:100233000298D0F0D0E0200104C4C0E0C4B201C0F1 +:10024300F0120027D0F0D5F0EB0200771204BD01C5 +:100253001453018E5800E54C00E14201924F019A7C +:0F02630044019A4900FA4301A0550184460184E1 +:100272004501844703405000E92D00ED2E01102B6B +:1002820000F123010E2003292A00A94800000108D9 +:100292003F3F3F00790AA2D5200314300509B91067 +:1002A200020404B9080104A2D52006025001042068 +:1002B20002689202B577005034C0E07F2030031903 +:1002C2007F30A20272067205500F1202EFC202C202 +:1002D20006C205C2087F30800F300503E9C0E01274 +:1002E200003E300503D0E0F9D0E0B577CC300517F9 +:1002F2007F30B9100C12003E7F583004077F78809F +:1003020003B9080312003E3002057F2D02003E7F32 +:10031200202008F87F2B2006F322920280CF286E3D +:10032200756C6C2900D2011200033001F8C2017809 +:100332007730D50108F60200A92D50434958120022 +:10034200032403B405004001E490033B9312002F01 +:0D035200743A12002FD20375770402018E59 +:10045500BB010689828A83E0225002E722BBFE02A5 +:09046500E32289828A83E49322D8 +:10046E00BB010CE58229F582E5833AF583E0225043 +:10047E0006E92582F8E622BBFE06E92582F8E2228D +:0D048E00E58229F582E5833AF583E49322A7 +:10049B00BB010689828A83F0225002F722BBFE0140 +:0204AB00F3223A +:1004AD00FAE6FB0808E6F925F0F618E6CA3AF62250 +:1004BD00D083D082F8E4937012740193700DA3A3CE +:1004CD0093F8740193F5828883E4737402936860E2 +:0604DD00EFA3A3A380DFE2 +:10057B00EFB40A07740D120586740A309811A89906 +:10058B00B8130CC2983098FDA899C298B811F630E0 +:07059B0099FDC299F59922B8 +:00000001FF +''' +bin8 = array.array('B',[2, 5, 162, 229, 118, 36, 106, 248, 230, 5, 118, 34, + 120, 103, 48, 7, 2, 120, 106, 228, 117, 240, 1, 18, + 4, 173, 2, 4, 85, 32, 0, 235, 127, 46, 210, 0, 128, + 24, 239, 84, 15, 36, 144, 212, 52, 64, 212, 255, 48, + 4, 11, 239, 36, 191, 180, 26, 0, 80, 3, 36, 97, 255, + 229, 119, 96, 2, 21, 119, 5, 122, 229, 122, 112, 2, + 5, 121, 48, 7, 13, 120, 103, 228, 117, 240, 1, 18, + 4, 173, 239, 2, 4, 155, 2, 5, 123, 116, 3, 210, 7, + 128, 3, 228, 194, 7, 245, 118, 139, 103, 138, 104, + 137, 105, 228, 245, 119, 245, 121, 245, 122, 229, + 119, 96, 7, 127, 32, 18, 0, 62, 128, 245, 117, 120, + 255, 194, 1, 194, 0, 194, 2, 194, 3, 194, 5, 194, 6, + 194, 8, 18, 0, 12, 255, 112, 13, 48, 7, 5, 127, 0, + 18, 0, 79, 175, 122, 174, 121, 34, 180, 37, 95, 194, + 213, 194, 4, 18, 0, 12, 255, 36, 208, 180, 10, 0, 80, + 26, 117, 240, 10, 120, 119, 48, 213, 5, 8, 182, 255, + 1, 6, 198, 164, 38, 246, 32, 213, 4, 112, 2, 210, 3, + 128, 217, 36, 207, 180, 26, 0, 239, 80, 4, 194, 229, + 210, 4, 2, 2, 79, 210, 1, 128, 198, 210, 0, 128, 192, + 210, 2, 128, 188, 210, 213, 128, 186, 210, 5, 128, + 180, 127, 32, 18, 0, 62, 32, 2, 7, 116, 1, 181, 119, + 0, 64, 241, 18, 0, 3, 255, 18, 0, 62, 2, 0, 119, 210, + 8, 210, 6, 128, 149, 18, 0, 3, 251, 18, 0, 3, 250, + 18, 0, 3, 249, 74, 75, 112, 6, 121, 32, 122, 3, 123, + 255, 32, 2, 46, 229, 119, 96, 42, 126, 0, 142, 130, + 117, 131, 0, 18, 4, 110, 96, 6, 14, 238, 101, 120, + 112, 240, 194, 213, 235, 192, 224, 234, 192, 224, + 233, 192, 224, 238, 18, 2, 150, 208, 224, 249, 208, + 224, 250, 208, 224, 251, 18, 4, 85, 255, 96, 170, + 235, 192, 224, 234, 192, 224, 233, 192, 224, 18, 0, + 62, 208, 224, 36, 1, 249, 208, 224, 52, 0, 250, 208, + 224, 251, 229, 120, 4, 96, 220, 213, 120, 217, 128, + 135, 123, 255, 122, 2, 121, 146, 210, 2, 128, 156, + 121, 16, 128, 2, 121, 8, 194, 6, 194, 8, 128, 8, 210, + 213, 121, 10, 128, 4, 121, 10, 194, 213, 229, 120, 4, + 112, 2, 245, 120, 228, 250, 253, 254, 255, 18, 0, 3, + 252, 123, 8, 32, 1, 19, 18, 0, 3, 253, 123, 16, 48, + 0, 10, 18, 0, 3, 254, 18, 0, 3, 255, 123, 32, 236, + 51, 130, 213, 146, 213, 80, 19, 195, 228, 48, 0, 6, + 159, 255, 228, 158, 254, 228, 32, 1, 3, 157, 253, + 228, 156, 252, 228, 203, 248, 194, 1, 236, 112, 12, + 207, 206, 205, 204, 232, 36, 248, 248, 112, 243, 128, + 23, 195, 239, 51, 255, 238, 51, 254, 237, 51, 253, + 236, 51, 252, 235, 51, 251, 153, 64, 2, 251, 15, 216, + 233, 235, 48, 1, 5, 248, 208, 224, 196, 72, 178, 1, + 192, 224, 10, 236, 77, 78, 79, 120, 32, 123, 0, 112, + 194, 234, 181, 120, 0, 64, 188, 192, 224, 18, 2, 152, + 208, 240, 208, 224, 32, 1, 4, 196, 192, 224, 196, + 178, 1, 192, 240, 18, 0, 39, 208, 240, 213, 240, 235, + 2, 0, 119, 18, 4, 189, 1, 20, 83, 1, 142, 88, 0, 229, + 76, 0, 225, 66, 1, 146, 79, 1, 154, 68, 1, 154, 73, + 0, 250, 67, 1, 160, 85, 1, 132, 70, 1, 132, 69, 1, + 132, 71, 3, 64, 80, 0, 233, 45, 0, 237, 46, 1, 16, + 43, 0, 241, 35, 1, 14, 32, 3, 41, 42, 0, 169, 72, 0, + 0, 1, 8, 63, 63, 63, 0, 121, 10, 162, 213, 32, 3, 20, + 48, 5, 9, 185, 16, 2, 4, 4, 185, 8, 1, 4, 162, 213, + 32, 6, 2, 80, 1, 4, 32, 2, 104, 146, 2, 181, 119, 0, + 80, 52, 192, 224, 127, 32, 48, 3, 25, 127, 48, 162, + 2, 114, 6, 114, 5, 80, 15, 18, 2, 239, 194, 2, 194, + 6, 194, 5, 194, 8, 127, 48, 128, 15, 48, 5, 3, 233, + 192, 224, 18, 0, 62, 48, 5, 3, 208, 224, 249, 208, + 224, 181, 119, 204, 48, 5, 23, 127, 48, 185, 16, 12, + 18, 0, 62, 127, 88, 48, 4, 7, 127, 120, 128, 3, 185, + 8, 3, 18, 0, 62, 48, 2, 5, 127, 45, 2, 0, 62, 127, + 32, 32, 8, 248, 127, 43, 32, 6, 243, 34, 146, 2, 128, + 207, 40, 110, 117, 108, 108, 41, 0, 210, 1, 18, 0, 3, + 48, 1, 248, 194, 1, 120, 119, 48, 213, 1, 8, 246, 2, + 0, 169, 45, 80, 67, 73, 88, 18, 0, 3, 36, 3, 180, 5, + 0, 64, 1, 228, 144, 3, 59, 147, 18, 0, 47, 116, 58, + 18, 0, 47, 210, 3, 117, 119, 4, 2, 1, 142, 231, 9, + 246, 8, 223, 250, 128, 70, 231, 9, 242, 8, 223, 250, + 128, 62, 136, 130, 140, 131, 231, 9, 240, 163, 223, + 250, 128, 50, 227, 9, 246, 8, 223, 250, 128, 120, + 227, 9, 242, 8, 223, 250, 128, 112, 136, 130, 140, + 131, 227, 9, 240, 163, 223, 250, 128, 100, 137, + 130, 138, 131, 224, 163, 246, 8, 223, 250, 128, 88, + 137, 130, 138, 131, 224, 163, 242, 8, 223, 250, 128, + 76, 128, 210, 128, 250, 128, 198, 128, 212, 128, 105, + 128, 242, 128, 51, 128, 16, 128, 166, 128, 234, 128, + 154, 128, 168, 128, 218, 128, 226, 128, 202, 128, 51, + 137, 130, 138, 131, 236, 250, 228, 147, 163, 200, + 197, 130, 200, 204, 197, 131, 204, 240, 163, 200, + 197, 130, 200, 204, 197, 131, 204, 223, 233, 222, + 231, 128, 13, 137, 130, 138, 131, 228, 147, 163, 246, + 8, 223, 249, 236, 250, 169, 240, 237, 251, 34, 137, + 130, 138, 131, 236, 250, 224, 163, 200, 197, 130, + 200, 204, 197, 131, 204, 240, 163, 200, 197, 130, + 200, 204, 197, 131, 204, 223, 234, 222, 232, 128, + 219, 137, 130, 138, 131, 228, 147, 163, 242, 8, + 223, 249, 128, 204, 136, 240, 239, 96, 1, 14, 78, + 96, 195, 136, 240, 237, 36, 2, 180, 4, 0, 80, 185, + 245, 130, 235, 36, 2, 180, 4, 0, 80, 175, 35, 35, + 69, 130, 35, 144, 3, 175, 115, 187, 1, 6, 137, 130, + 138, 131, 224, 34, 80, 2, 231, 34, 187, 254, 2, 227, + 34, 137, 130, 138, 131, 228, 147, 34, 187, 1, 12, + 229, 130, 41, 245, 130, 229, 131, 58, 245, 131, 224, + 34, 80, 6, 233, 37, 130, 248, 230, 34, 187, 254, 6, + 233, 37, 130, 248, 226, 34, 229, 130, 41, 245, 130, + 229, 131, 58, 245, 131, 228, 147, 34, 187, 1, 6, + 137, 130, 138, 131, 240, 34, 80, 2, 247, 34, 187, + 254, 1, 243, 34, 250, 230, 251, 8, 8, 230, 249, 37, + 240, 246, 24, 230, 202, 58, 246, 34, 208, 131, 208, + 130, 248, 228, 147, 112, 18, 116, 1, 147, 112, 13, + 163, 163, 147, 248, 116, 1, 147, 245, 130, 136, + 131, 228, 115, 116, 2, 147, 104, 96, 239, 163, 163, + 163, 128, 223, 207, 240, 251, 226, 253, 242, 32, + 255, 32, 242, 225, 32, 226, 251, 230, 243, 10, 0, + 253, 224, 225, 226, 227, 180, 228, 229, 186, 230, + 231, 179, 191, 232, 233, 234, 235, 236, 237, 238, + 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, + 249, 252, 254, 255, 0, 192, 193, 194, 195, 165, 196, + 197, 170, 198, 199, 178, 175, 200, 201, 202, 203, + 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, + 214, 215, 216, 217, 220, 222, 223, 0, 120, 34, 124, + 0, 125, 0, 123, 255, 122, 4, 121, 245, 126, 0, 127, + 35, 18, 4, 47, 120, 69, 124, 0, 125, 0, 123, 255, + 122, 5, 121, 24, 126, 0, 127, 34, 18, 4, 47, 117, + 152, 80, 67, 137, 32, 117, 141, 221, 210, 142, 210, + 153, 99, 144, 1, 123, 255, 122, 4, 121, 227, 18, 0, + 101, 128, 254, 239, 180, 10, 7, 116, 13, 18, 5, 134, + 116, 10, 48, 152, 17, 168, 153, 184, 19, 12, 194, + 152, 48, 152, 253, 168, 153, 194, 152, 184, 17, + 246, 48, 153, 253, 194, 153, 245, 153, 34, 120, 127, + 228, 246, 216, 253, 117, 129, 122, 2, 5, 58]) + + +hex16 = """:020000040000FA +:10000000000083120313072055301820042883169C +:10001000031340309900181598168312031318160D +:1000200098170800831203138C1E14281A0808005E +:0C003000831203130C1E1A28990008000C +:00000001FF +""" +bin16 = array.array('H', [0x0000, 0x1283, 0x1303, 0x2007, + 0x3055, 0x2018, 0x2804, 0x1683, + 0x1303, 0x3040, 0x0099, 0x1518, + 0x1698, 0x1283, 0x1303, 0x1618, + 0x1798, 0x0008, 0x1283, 0x1303, + 0x1E8C, 0x2814, 0x081A, 0x0008, + 0x1283, 0x1303, 0x1E0C, 0x281A, + 0x0099, 0x0008, 0x3FFF, 0x3FFF]) + + +hex64k = """:020000040000FA +:0100000001FE +:020000040001F9 +:0100000002FD +:00000001FF +""" +data64k = {0: 1, 0x10000: 2} + + +hex_rectype3 = """:0400000312345678E5 +:0100000001FE +:00000001FF +""" +data_rectype3 = {0: 1} +start_addr_rectype3 = {'CS': 0x1234, 'IP': 0x5678} + + +hex_rectype5 = """:0400000512345678E3 +:0100000002FD +:00000001FF +""" +data_rectype5 = {0: 2} +start_addr_rectype5 = {'EIP': 0x12345678} + +hex_empty_file = ':00000001FF\n' + +hex_simple = """\ +:10000000000083120313072055301820042883169C +:10001000031340309900181598168312031318160D +:1000200098170800831203138C1E14281A0808005E +:0C003000831203130C1E1A28990008000C +:00000001FF +""" + +hex_bug_lp_341051 = """\ +:020FEC00E4E738 +:040FF00022E122E1F7 +:00000001FF +""" + + +## +# Test cases + +class TestIntelHexBase(unittest.TestCase): + """Base class for all tests. + Provide additional functionality for testing. + """ + + def assertRaisesMsg(self, excClass, msg, callableObj, *args, **kwargs): + """Just like unittest.TestCase.assertRaises, + but checks that the message is right too. + + Borrowed from Ned Batchelder Blog. + See: http://www.nedbatchelder.com/blog/200609.html#e20060905T064418 + + Typical usage:: + + self.assertRaisesMsg(MyException, "Exception message", + my_function, (arg1, arg2)) + """ + try: + callableObj(*args, **kwargs) + except excClass: + exc = sys.exc_info()[1] # current exception + excMsg = str(exc) + if not msg: + # No message provided: any message is fine. + return + elif excMsg == msg: + # Message provided, and we got the right message: it passes. + return + else: + # Message provided, and it didn't match: fail! + raise self.failureException( + "Right exception, wrong message: got '%s' expected '%s'" % + (excMsg, msg) + ) + else: + if hasattr(excClass, '__name__'): + excName = excClass.__name__ + else: + excName = str(excClass) + raise self.failureException( + "Expected to raise %s, didn't get an exception at all" % + excName + ) + + def assertEqualWrittenData(self, a, b): + return self.assertEqual(a, b, """Written data is incorrect +Should be: +%s + +Written: +%s +""" % (a, b)) +#/class TestIntelHexBase + + +class TestIntelHex(TestIntelHexBase): + + def setUp(self): + self.f = StringIO(hex8) + + def tearDown(self): + self.f.close() + del self.f + + def test_init_from_file(self): + ih = IntelHex(self.f) + for addr in range_g(len(bin8)): + expected = bin8[addr] + actual = ih[addr] + self.assertEqual(expected, actual, + "Data different at address " + "%x (%x != %x)" % (addr, expected, actual)) + + def test_hex_fromfile(self): + ih = IntelHex() + ih.fromfile(self.f, format='hex') + for addr in range_g(len(bin8)): + expected = bin8[addr] + actual = ih[addr] + self.assertEqual(expected, actual, + "Data different at address " + "%x (%x != %x)" % (addr, expected, actual)) + + def test_unicode_filename(self): + handle, fname = tempfile.mkstemp(UnicodeType('')) + os.close(handle) + try: + self.assertTrue(isinstance(fname, UnicodeType)) + f = open(fname, 'w') + try: + f.write(hex8) + finally: + f.close() + ih = IntelHex(fname) + self.assertEqual(0, ih.minaddr()) + self.assertEqual(len(bin8)-1, ih.maxaddr()) + finally: + os.remove(fname) + + def test_tobinarray_empty(self): + ih = IntelHex() + ih.padding = 0xFF # set-up explicit padding value and don't use pad parameter + self.assertEqual(array.array('B', []), ih.tobinarray()) + self.assertEqual(array.array('B', []), ih.tobinarray(start=0)) + self.assertEqual(array.array('B', []), ih.tobinarray(end=2)) + self.assertEqual(array.array('B', [255,255,255]), ih.tobinarray(0,2)) + + def test_tobinarray_with_size(self): + ih = IntelHex(self.f) + self.assertEqual(array.array('B', [2, 5, 162, 229, 118, 36, 106, 248]), + ih.tobinarray(size=8)) # from addr 0 + self.assertEqual(array.array('B', [120, 103, 48, 7, 2, 120, 106, 228]), + ih.tobinarray(start=12, size=8)) + self.assertEqual(array.array('B', [2, 5, 162, 229, 118, 36, 106, 248]), + ih.tobinarray(end=7, size=8)) # addr: 0..7, 8 bytes + self.assertEqual(array.array('B', [120, 103, 48, 7, 2, 120, 106, 228]), + ih.tobinarray(end=19, size=8)) # addr: 12..19, 8 bytes + self.assertRaises(ValueError, ih.tobinarray, start=0, end=7, size=8) + self.assertRaises(ValueError, ih.tobinarray, end=3, size=8) + self.assertRaises(ValueError, ih.tobinarray, size=0) + self.assertRaises(ValueError, ih.tobinarray, size=-1) + + def test_tobinstr(self): + ih = IntelHex(self.f) + s1 = ih.tobinstr() + s2 = array_tobytes(bin8) + self.assertEqual(s2, s1, "data not equal\n%s\n\n%s" % (s1, s2)) + + def test_tobinfile(self): + ih = IntelHex(self.f) + sio = BytesIO() + ih.tobinfile(sio) + s1 = sio.getvalue() + sio.close() + s2 = array_tobytes(bin8) + self.assertEqual(s2, s1, "data not equal\n%s\n\n%s" % (s1, s2)) + # new API: .tofile universal method + sio = BytesIO() + ih.tofile(sio, format='bin') + s1 = sio.getvalue() + sio.close() + s2 = array_tobytes(bin8) + self.assertEqual(s2, s1, "data not equal\n%s\n\n%s" % (s1, s2)) + + def test_tobinfile_realfile(self): + ih = IntelHex(self.f) + tf = tempfile.TemporaryFile(mode='wb') + try: + ih.tobinfile(tf) + finally: + tf.close() + + def test__get_eol_textfile(self): + self.assertEqual('\n', IntelHex._get_eol_textfile('native', 'win32')) + self.assertEqual('\n', IntelHex._get_eol_textfile('native', 'linux')) + self.assertEqual('\n', IntelHex._get_eol_textfile('CRLF', 'win32')) + self.assertEqual('\r\n', IntelHex._get_eol_textfile('CRLF', 'linux')) + self.assertRaisesMsg(ValueError, "wrong eolstyle 'LF'", + IntelHex._get_eol_textfile, 'LF', 'win32') + + def test_write_empty_hexfile(self): + ih = intelhex.IntelHex() + sio = StringIO() + ih.write_hex_file(sio) + s = sio.getvalue() + sio.close() + self.assertEqualWrittenData(hex_empty_file, s) + + def test_write_hexfile(self): + ih = intelhex.IntelHex(StringIO(hex_simple)) + sio = StringIO() + ih.write_hex_file(sio) + s = sio.getvalue() + sio.close() + self.assertEqualWrittenData(hex_simple, s) + # new API: .tofile universal method + sio = StringIO() + ih.tofile(sio, format='hex') + s = sio.getvalue() + sio.close() + self.assertEqualWrittenData(hex_simple, s) + + def test_write_hex_bug_341051(self): + ih = intelhex.IntelHex(StringIO(hex_bug_lp_341051)) + sio = StringIO() + ih.tofile(sio, format='hex') + s = sio.getvalue() + sio.close() + self.assertEqualWrittenData(hex_bug_lp_341051, s) + + def test_write_hex_first_extended_linear_address(self): + ih = IntelHex({0x20000: 0x01}) + sio = StringIO() + ih.write_hex_file(sio) + s = sio.getvalue() + sio.close() + # should be + r = [Record.extended_linear_address(2), + Record.data(0x0000, [0x01]), + Record.eof()] + h = '\n'.join(r) + '\n' + # compare + self.assertEqual(h, s) + + def test_tofile_wrong_format(self): + ih = IntelHex() + sio = StringIO() + self.assertRaises(ValueError, ih.tofile, sio, {'format': 'bad'}) + + def test_todict(self): + ih = IntelHex() + self.assertEqual({}, ih.todict()) + ih = IntelHex(StringIO(hex64k)) + self.assertEqual(data64k, ih.todict()) + ih = IntelHex() + ih[1] = 2 + ih.start_addr = {'EIP': 1234} + self.assertEqual({1: 2, 'start_addr': {'EIP': 1234}}, ih.todict()) + + def test_fromdict(self): + ih = IntelHex() + ih.fromdict({1:2, 3:4}) + self.assertEqual({1:2, 3:4}, ih.todict()) + ih.fromdict({1:5, 6:7}) + self.assertEqual({1:5, 3:4, 6:7}, ih.todict()) + ih = IntelHex() + ih.fromdict({1: 2, 'start_addr': {'EIP': 1234}}) + self.assertEqual({1: 2, 'start_addr': {'EIP': 1234}}, ih.todict()) + # bad dict + self.assertRaises(ValueError, ih.fromdict, {'EIP': 1234}) + self.assertRaises(ValueError, ih.fromdict, {-1: 1234}) + + def test_init_from_obj(self): + ih = IntelHex({1:2, 3:4}) + self.assertEqual({1:2, 3:4}, ih.todict()) + ih.start_addr = {'EIP': 1234} + ih2 = IntelHex(ih) + ih[1] = 5 + ih.start_addr = {'EIP': 5678} + self.assertEqual({1:2, 3:4, 'start_addr': {'EIP': 1234}}, ih2.todict()) + self.assertNotEqual(id(ih), id(ih2)) + + def test_dict_interface(self): + ih = IntelHex() + self.assertEqual(0xFF, ih[0]) # padding byte substitution + ih[0] = 1 + self.assertEqual(1, ih[0]) + del ih[0] + self.assertEqual({}, ih.todict()) # padding byte substitution + + def test_len(self): + ih = IntelHex() + self.assertEqual(0, len(ih)) + ih[2] = 1 + self.assertEqual(1, len(ih)) + ih[1000] = 2 + self.assertEqual(2, len(ih)) + + def test__getitem__(self): + ih = IntelHex() + # simple cases + self.assertEqual(0xFF, ih[0]) + ih[0] = 1 + self.assertEqual(1, ih[0]) + # big address + self.assertEqual(0xFF, ih[2**32-1]) + # wrong addr type/value for indexing operations + def getitem(index): + return ih[index] + self.assertRaisesMsg(TypeError, + 'Address should be >= 0.', + getitem, -1) + self.assertRaisesMsg(TypeError, + "Address has unsupported type: %s" % type('foo'), + getitem, 'foo') + # new object with some data + ih = IntelHex() + ih[0] = 1 + ih[1] = 2 + ih[2] = 3 + ih[10] = 4 + # full copy via slicing + ih2 = ih[:] + self.assertTrue(isinstance(ih2, IntelHex)) + self.assertEqual({0:1, 1:2, 2:3, 10:4}, ih2.todict()) + # other slice operations + self.assertEqual({}, ih[3:8].todict()) + self.assertEqual({0:1, 1:2}, ih[0:2].todict()) + self.assertEqual({0:1, 1:2}, ih[:2].todict()) + self.assertEqual({2:3, 10:4}, ih[2:].todict()) + self.assertEqual({0:1, 2:3, 10:4}, ih[::2].todict()) + self.assertEqual({10:4}, ih[3:11].todict()) + + def test__setitem__(self): + ih = IntelHex() + # simple indexing operation + ih[0] = 1 + self.assertEqual({0:1}, ih.todict()) + # errors + def setitem(a,b): + ih[a] = b + self.assertRaisesMsg(TypeError, + 'Address should be >= 0.', + setitem, -1, 0) + self.assertRaisesMsg(TypeError, + "Address has unsupported type: %s" % type('foo'), + setitem, 'foo', 0) + # slice operations + ih[0:4] = range_l(4) + self.assertEqual({0:0, 1:1, 2:2, 3:3}, ih.todict()) + ih[0:] = range_l(5,9) + self.assertEqual({0:5, 1:6, 2:7, 3:8}, ih.todict()) + ih[:4] = range_l(9,13) + self.assertEqual({0:9, 1:10, 2:11, 3:12}, ih.todict()) + # with step + ih = IntelHex() + ih[0:8:2] = range_l(4) + self.assertEqual({0:0, 2:1, 4:2, 6:3}, ih.todict()) + # errors in slice operations + # ih[1:2] = 'a' + self.assertRaisesMsg(ValueError, + 'Slice operation expects sequence of bytes', + setitem, slice(1,2,None), 'a') + # ih[0:1] = [1,2,3] + self.assertRaisesMsg(ValueError, + 'Length of bytes sequence does not match address range', + setitem, slice(0,1,None), [1,2,3]) + # ih[:] = [1,2,3] + self.assertRaisesMsg(TypeError, + 'Unsupported address range', + setitem, slice(None,None,None), [1,2,3]) + # ih[:2] = [1,2,3] + self.assertRaisesMsg(TypeError, + 'start address cannot be negative', + setitem, slice(None,2,None), [1,2,3]) + # ih[0:-3:-1] = [1,2,3] + self.assertRaisesMsg(TypeError, + 'stop address cannot be negative', + setitem, slice(0,-3,-1), [1,2,3]) + + def test__delitem__(self): + ih = IntelHex() + ih[0] = 1 + del ih[0] + self.assertEqual({}, ih.todict()) + # errors + def delitem(addr): + del ih[addr] + self.assertRaises(KeyError, delitem, 1) + self.assertRaisesMsg(TypeError, + 'Address should be >= 0.', + delitem, -1) + self.assertRaisesMsg(TypeError, + "Address has unsupported type: %s" % type('foo'), + delitem, 'foo') + # deleting slice + del ih[0:1] # no error here because of slicing + # + def ihex(size=8): + ih = IntelHex() + for i in range_g(size): + ih[i] = i + return ih + ih = ihex(8) + del ih[:] # delete all data + self.assertEqual({}, ih.todict()) + ih = ihex(8) + del ih[2:6] + self.assertEqual({0:0, 1:1, 6:6, 7:7}, ih.todict()) + ih = ihex(8) + del ih[::2] + self.assertEqual({1:1, 3:3, 5:5, 7:7}, ih.todict()) + + def test_addresses(self): + # empty object + ih = IntelHex() + self.assertEqual([], ih.addresses()) + self.assertEqual(None, ih.minaddr()) + self.assertEqual(None, ih.maxaddr()) + # normal object + ih = IntelHex({1:2, 7:8, 10:0}) + self.assertEqual([1,7,10], ih.addresses()) + self.assertEqual(1, ih.minaddr()) + self.assertEqual(10, ih.maxaddr()) + + def test__get_start_end(self): + # test for private method _get_start_end + # for empty object + ih = IntelHex() + self.assertRaises(intelhex.EmptyIntelHexError, ih._get_start_end) + self.assertRaises(intelhex.EmptyIntelHexError, ih._get_start_end, size=10) + self.assertEqual((0,9), ih._get_start_end(start=0, size=10)) + self.assertEqual((1,10), ih._get_start_end(end=10, size=10)) + # normal object + ih = IntelHex({1:2, 7:8, 10:0}) + self.assertEqual((1,10), ih._get_start_end()) + self.assertEqual((1,10), ih._get_start_end(size=10)) + self.assertEqual((0,9), ih._get_start_end(start=0, size=10)) + self.assertEqual((1,10), ih._get_start_end(end=10, size=10)) + + def test_segments(self): + # test that address segments are correctly summarized + ih = IntelHex() + sg = ih.segments() + self.assertTrue(isinstance(sg, list)) + self.assertEqual(len(sg), 0) + ih[0x100] = 0 + sg = ih.segments() + self.assertTrue(isinstance(sg, list)) + self.assertEqual(len(sg), 1) + self.assertTrue(isinstance(sg[0], tuple)) + self.assertTrue(len(sg[0]) == 2) + self.assertTrue(sg[0][0] < sg[0][1]) + self.assertEqual(min(sg[0]), 0x100) + self.assertEqual(max(sg[0]), 0x101) + ih[0x101] = 1 + sg = ih.segments() + self.assertTrue(isinstance(sg, list)) + self.assertEqual(len(sg), 1) + self.assertTrue(isinstance(sg[0], tuple)) + self.assertTrue(len(sg[0]) == 2) + self.assertTrue(sg[0][0] < sg[0][1]) + self.assertEqual(min(sg[0]), 0x100) + self.assertEqual(max(sg[0]), 0x102) + ih[0x200] = 2 + ih[0x201] = 3 + ih[0x202] = 4 + sg = ih.segments() + self.assertTrue(isinstance(sg, list)) + self.assertEqual(len(sg), 2) + self.assertTrue(isinstance(sg[0], tuple)) + self.assertTrue(len(sg[0]) == 2) + self.assertTrue(sg[0][0] < sg[0][1]) + self.assertTrue(isinstance(sg[1], tuple)) + self.assertTrue(len(sg[1]) == 2) + self.assertTrue(sg[1][0] < sg[1][1]) + self.assertEqual(min(sg[0]), 0x100) + self.assertEqual(max(sg[0]), 0x102) + self.assertEqual(min(sg[1]), 0x200) + self.assertEqual(max(sg[1]), 0x203) + ih[0x204] = 5 + sg = ih.segments() + self.assertEqual(len(sg), 3) + sg = ih.segments(min_gap=2) + self.assertEqual(len(sg), 2) + self.assertEqual(min(sg[1]), 0x200) + self.assertEqual(max(sg[1]), 0x205) + pass + +class TestIntelHexLoadBin(TestIntelHexBase): + + def setUp(self): + self.bytes = asbytes('0123456789') + self.f = BytesIO(self.bytes) + + def tearDown(self): + self.f.close() + + def test_loadbin(self): + ih = IntelHex() + ih.loadbin(self.f) + self.assertEqual(0, ih.minaddr()) + self.assertEqual(9, ih.maxaddr()) + self.assertEqual(self.bytes, ih.tobinstr()) + + def test_bin_fromfile(self): + ih = IntelHex() + ih.fromfile(self.f, format='bin') + self.assertEqual(0, ih.minaddr()) + self.assertEqual(9, ih.maxaddr()) + self.assertEqual(self.bytes, ih.tobinstr()) + + def test_loadbin_w_offset(self): + ih = IntelHex() + ih.loadbin(self.f, offset=100) + self.assertEqual(100, ih.minaddr()) + self.assertEqual(109, ih.maxaddr()) + self.assertEqual(self.bytes, ih.tobinstr()) + + def test_loadfile_format_bin(self): + ih = IntelHex() + ih.loadfile(self.f, format='bin') + self.assertEqual(0, ih.minaddr()) + self.assertEqual(9, ih.maxaddr()) + self.assertEqual(self.bytes, ih.tobinstr()) + + +class TestIntelHexStartingAddressRecords(TestIntelHexBase): + + def _test_read(self, hexstr, data, start_addr): + sio = StringIO(hexstr) + ih = IntelHex(sio) + sio.close() + # test data + self.assertEqual(data, ih._buf, + "Internal buffer: %r != %r" % + (data, ih._buf)) + self.assertEqual(start_addr, ih.start_addr, + "Start address: %r != %r" % + (start_addr, ih.start_addr)) + + def test_read_rectype3(self): + self._test_read(hex_rectype3, data_rectype3, start_addr_rectype3) + + def test_read_rectype5(self): + self._test_read(hex_rectype5, data_rectype5, start_addr_rectype5) + + def _test_write(self, hexstr, data, start_addr, write_start_addr=True): + # prepare + ih = IntelHex(None) + ih._buf = data + ih.start_addr = start_addr + # write + sio = StringIO() + ih.write_hex_file(sio, write_start_addr) + s = sio.getvalue() + sio.close() + # check + self.assertEqualWrittenData(hexstr, s) + + def _test_dont_write(self, hexstr, data, start_addr): + expected = ''.join(hexstr.splitlines(True)[1:]) + self._test_write(expected, data, start_addr, False) + + def test_write_rectype3(self): + self._test_write(hex_rectype3, data_rectype3, start_addr_rectype3) + + def test_dont_write_rectype3(self): + self._test_dont_write(hex_rectype3, data_rectype3, start_addr_rectype3) + + def test_write_rectype5(self): + self._test_write(hex_rectype5, data_rectype5, start_addr_rectype5) + + def test_dont_write_rectype5(self): + self._test_dont_write(hex_rectype5, data_rectype5, start_addr_rectype5) + + def test_write_invalid_start_addr_value(self): + ih = IntelHex() + ih.start_addr = {'foo': 1} + sio = StringIO() + self.assertRaises(InvalidStartAddressValueError, ih.write_hex_file, sio) + + +class TestIntelHex_big_files(TestIntelHexBase): + """Test that data bigger than 64K read/write correctly""" + + def setUp(self): + self.f = StringIO(hex64k) + + def tearDown(self): + self.f.close() + del self.f + + def test_readfile(self): + ih = intelhex.IntelHex(self.f) + for addr, byte in dict_items_g(data64k): + readed = ih[addr] + self.assertEqual(byte, readed, + "data not equal at addr %X " + "(%X != %X)" % (addr, byte, readed)) + + def test_write_hex_file(self): + ih = intelhex.IntelHex(self.f) + sio = StringIO() + ih.write_hex_file(sio) + s = sio.getvalue() + sio.close() + self.assertEqualWrittenData(hex64k, s) + + +class TestIntelHexGetPutString(TestIntelHexBase): + + def setUp(self): + self.ih = IntelHex() + for i in range_g(10): + self.ih[i] = i + + def test_gets(self): + self.assertEqual(asbytes('\x00\x01\x02\x03\x04\x05\x06\x07'), self.ih.gets(0, 8)) + self.assertEqual(asbytes('\x07\x08\x09'), self.ih.gets(7, 3)) + self.assertRaisesMsg(intelhex.NotEnoughDataError, + 'Bad access at 0x1: ' + 'not enough data to read 10 contiguous bytes', + self.ih.gets, 1, 10) + + def test_puts(self): + self.ih.puts(0x03, asbytes('hello')) + self.assertEqual(asbytes('\x00\x01\x02hello\x08\x09'), self.ih.gets(0, 10)) + + def test_getsz(self): + self.assertEqual(asbytes(''), self.ih.getsz(0)) + self.assertRaisesMsg(intelhex.NotEnoughDataError, + 'Bad access at 0x1: ' + 'not enough data to read zero-terminated string', + self.ih.getsz, 1) + self.ih[4] = 0 + self.assertEqual(asbytes('\x01\x02\x03'), self.ih.getsz(1)) + + def test_putsz(self): + self.ih.putsz(0x03, asbytes('hello')) + self.assertEqual(asbytes('\x00\x01\x02hello\x00\x09'), self.ih.gets(0, 10)) + + def test_find(self): + self.assertEqual(0, self.ih.find(asbytes('\x00\x01\x02\x03\x04\x05\x06'))) + self.assertEqual(0, self.ih.find(asbytes('\x00'))) + self.assertEqual(3, self.ih.find(asbytes('\x03\x04\x05\x06'))) + self.assertEqual(3, self.ih.find(asbytes('\x03'))) + self.assertEqual(7, self.ih.find(asbytes('\x07\x08\x09'))) + self.assertEqual(7, self.ih.find(asbytes('\x07'))) + self.assertEqual(-1, self.ih.find(asbytes('\x0a'))) + self.assertEqual(-1, self.ih.find(asbytes('\x02\x01'))) + self.assertEqual(-1, self.ih.find(asbytes('\x08\x07'))) + + def test_find_start(self): + self.assertEqual(-1, self.ih.find(asbytes('\x00\x01\x02\x03\x04\x05\x06'), start=3)) + self.assertEqual(-1, self.ih.find(asbytes('\x00'), start=3)) + self.assertEqual(3, self.ih.find(asbytes('\x03\x04\x05\x06'), start=3)) + self.assertEqual(3, self.ih.find(asbytes('\x03'), start=3)) + self.assertEqual(7, self.ih.find(asbytes('\x07\x08\x09'), start=3)) + self.assertEqual(7, self.ih.find(asbytes('\x07'), start=3)) + self.assertEqual(-1, self.ih.find(asbytes('\x0a'), start=3)) + self.assertEqual(-1, self.ih.find(asbytes('\x02\x01'), start=3)) + self.assertEqual(-1, self.ih.find(asbytes('\x08\x07'), start=3)) + + def test_find_end(self): + self.assertEqual(-1, self.ih.find(asbytes('\x00\x01\x02\x03\x04\x05\x06'), end=4)) + self.assertEqual(0, self.ih.find(asbytes('\x00'), end=4)) + self.assertEqual(-1, self.ih.find(asbytes('\x03\x04\x05\x06'), end=4)) + self.assertEqual(3, self.ih.find(asbytes('\x03'), end=4)) + self.assertEqual(-1, self.ih.find(asbytes('\x07\x08\x09'), end=4)) + self.assertEqual(-1, self.ih.find(asbytes('\x07'), end=4)) + self.assertEqual(-1, self.ih.find(asbytes('\x0a'), end=4)) + self.assertEqual(-1, self.ih.find(asbytes('\x02\x01'), end=4)) + self.assertEqual(-1, self.ih.find(asbytes('\x08\x07'), end=4)) + + def test_find_start_end(self): + self.assertEqual(-1, self.ih.find(asbytes('\x00\x01\x02\x03\x04\x05\x06'), start=3, end=7)) + self.assertEqual(-1, self.ih.find(asbytes('\x00'), start=3, end=7)) + self.assertEqual(3, self.ih.find(asbytes('\x03\x04\x05\x06'), start=3, end=7)) + self.assertEqual(3, self.ih.find(asbytes('\x03'), start=3, end=7)) + self.assertEqual(-1, self.ih.find(asbytes('\x07\x08\x09'), start=3, end=7)) + self.assertEqual(-1, self.ih.find(asbytes('\x07'), start=3, end=7)) + self.assertEqual(-1, self.ih.find(asbytes('\x0a'), start=3, end=7)) + self.assertEqual(-1, self.ih.find(asbytes('\x02\x01'), start=3, end=7)) + self.assertEqual(-1, self.ih.find(asbytes('\x08\x07'), start=3, end=7)) + + +class TestIntelHexDump(TestIntelHexBase): + + def test_empty(self): + ih = IntelHex() + sio = StringIO() + ih.dump(sio) + self.assertEqual('', sio.getvalue()) + + def test_simple(self): + ih = IntelHex() + ih[0] = 0x12 + ih[1] = 0x34 + sio = StringIO() + ih.dump(sio) + self.assertEqual( + '0000 12 34 -- -- -- -- -- -- -- -- -- -- -- -- -- -- |.4 |\n', + sio.getvalue()) + ih[16] = 0x56 + ih[30] = 0x98 + sio = StringIO() + ih.dump(sio) + self.assertEqual( + '0000 12 34 -- -- -- -- -- -- -- -- -- -- -- -- -- -- |.4 |\n' + '0010 56 -- -- -- -- -- -- -- -- -- -- -- -- -- 98 -- |V . |\n', + sio.getvalue()) + + def test_minaddr_not_zero(self): + ih = IntelHex() + ih[16] = 0x56 + ih[30] = 0x98 + sio = StringIO() + ih.dump(sio) + self.assertEqual( + '0010 56 -- -- -- -- -- -- -- -- -- -- -- -- -- 98 -- |V . |\n', + sio.getvalue()) + + def test_start_addr(self): + ih = IntelHex() + ih[0] = 0x12 + ih[1] = 0x34 + ih.start_addr = {'CS': 0x1234, 'IP': 0x5678} + sio = StringIO() + ih.dump(sio) + self.assertEqual( + 'CS = 0x1234, IP = 0x5678\n' + '0000 12 34 -- -- -- -- -- -- -- -- -- -- -- -- -- -- |.4 |\n', + sio.getvalue()) + ih.start_addr = {'EIP': 0x12345678} + sio = StringIO() + ih.dump(sio) + self.assertEqual( + 'EIP = 0x12345678\n' + '0000 12 34 -- -- -- -- -- -- -- -- -- -- -- -- -- -- |.4 |\n', + sio.getvalue()) + + def test_bad_width(self): + ih = IntelHex() + sio = StringIO() + badwidths = [0, -1, -10.5, 2.5] + for bw in badwidths: + self.assertRaisesMsg(ValueError, "width must be a positive integer.", + ih.dump, sio, bw) + badwidthtypes = ['', {}, [], sio] + for bwt in badwidthtypes: + self.assertRaisesMsg(ValueError, "width must be a positive integer.", + ih.dump, sio, bwt) + + def test_simple_width3(self): + ih = IntelHex() + ih[0] = 0x12 + ih[1] = 0x34 + sio = StringIO() + ih.dump(tofile=sio, width=3) + self.assertEqual( + '0000 12 34 -- |.4 |\n', + sio.getvalue()) + + ih[16] = 0x56 + ih[30] = 0x98 + sio = StringIO() + ih.dump(tofile=sio, width=3) + self.assertEqual( + '0000 12 34 -- |.4 |\n' + '0003 -- -- -- | |\n' + '0006 -- -- -- | |\n' + '0009 -- -- -- | |\n' + '000C -- -- -- | |\n' + '000F -- 56 -- | V |\n' + '0012 -- -- -- | |\n' + '0015 -- -- -- | |\n' + '0018 -- -- -- | |\n' + '001B -- -- -- | |\n' + '001E 98 -- -- |. |\n', + sio.getvalue()) + + def test_minaddr_not_zero_width3_padding(self): + ih = IntelHex() + ih[17] = 0x56 + ih[30] = 0x98 + sio = StringIO() + ih.dump(tofile=sio, width=3, withpadding=True) + self.assertEqual( + '000F FF FF 56 |..V|\n' + '0012 FF FF FF |...|\n' + '0015 FF FF FF |...|\n' + '0018 FF FF FF |...|\n' + '001B FF FF FF |...|\n' + '001E 98 FF FF |...|\n', + sio.getvalue()) + + +class TestIntelHexMerge(TestIntelHexBase): + + def test_merge_empty(self): + ih1 = IntelHex() + ih2 = IntelHex() + ih1.merge(ih2) + self.assertEqual({}, ih1.todict()) + + def test_merge_simple(self): + ih1 = IntelHex({0:1, 1:2, 2:3}) + ih2 = IntelHex({3:4, 4:5, 5:6}) + ih1.merge(ih2) + self.assertEqual({0:1, 1:2, 2:3, 3:4, 4:5, 5:6}, ih1.todict()) + + def test_merge_wrong_args(self): + ih1 = IntelHex() + self.assertRaisesMsg(TypeError, 'other should be IntelHex object', + ih1.merge, {0:1}) + self.assertRaisesMsg(ValueError, "Can't merge itself", + ih1.merge, ih1) + ih2 = IntelHex() + self.assertRaisesMsg(ValueError, "overlap argument should be either " + "'error', 'ignore' or 'replace'", + ih1.merge, ih2, overlap='spam') + + def test_merge_overlap(self): + # error + ih1 = IntelHex({0:1}) + ih2 = IntelHex({0:2}) + self.assertRaisesMsg(intelhex.AddressOverlapError, + 'Data overlapped at address 0x0', + ih1.merge, ih2, overlap='error') + # ignore + ih1 = IntelHex({0:1}) + ih2 = IntelHex({0:2}) + ih1.merge(ih2, overlap='ignore') + self.assertEqual({0:1}, ih1.todict()) + # replace + ih1 = IntelHex({0:1}) + ih2 = IntelHex({0:2}) + ih1.merge(ih2, overlap='replace') + self.assertEqual({0:2}, ih1.todict()) + + def test_merge_start_addr(self): + # this, None + ih1 = IntelHex({'start_addr': {'EIP': 0x12345678}}) + ih2 = IntelHex() + ih1.merge(ih2) + self.assertEqual({'start_addr': {'EIP': 0x12345678}}, ih1.todict()) + # None, other + ih1 = IntelHex() + ih2 = IntelHex({'start_addr': {'EIP': 0x12345678}}) + ih1.merge(ih2) + self.assertEqual({'start_addr': {'EIP': 0x12345678}}, ih1.todict()) + # this == other: no conflict + ih1 = IntelHex({'start_addr': {'EIP': 0x12345678}}) + ih2 = IntelHex({'start_addr': {'EIP': 0x12345678}}) + ih1.merge(ih2) + self.assertEqual({'start_addr': {'EIP': 0x12345678}}, ih1.todict()) + # this != other: conflict + ## overlap=error + ih1 = IntelHex({'start_addr': {'EIP': 0x12345678}}) + ih2 = IntelHex({'start_addr': {'EIP': 0x87654321}}) + self.assertRaisesMsg(AddressOverlapError, + 'Starting addresses are different', + ih1.merge, ih2, overlap='error') + ## overlap=ignore + ih1 = IntelHex({'start_addr': {'EIP': 0x12345678}}) + ih2 = IntelHex({'start_addr': {'EIP': 0x87654321}}) + ih1.merge(ih2, overlap='ignore') + self.assertEqual({'start_addr': {'EIP': 0x12345678}}, ih1.todict()) + ## overlap=replace + ih1 = IntelHex({'start_addr': {'EIP': 0x12345678}}) + ih2 = IntelHex({'start_addr': {'EIP': 0x87654321}}) + ih1.merge(ih2, overlap='replace') + self.assertEqual({'start_addr': {'EIP': 0x87654321}}, ih1.todict()) + + +class TestIntelHex16bit(TestIntelHexBase): + + def setUp(self): + self.f = StringIO(hex16) + + def tearDown(self): + self.f.close() + del self.f + + def test_init_from_file(self): + ih = intelhex.IntelHex16bit(self.f) + + def test_init_from_ih(self): + ih = intelhex.IntelHex(self.f) + ih16 = intelhex.IntelHex16bit(ih) + + def test_default_padding(self): + ih16 = intelhex.IntelHex16bit() + self.assertEqual(0x0FFFF, ih16.padding) + self.assertEqual(0x0FFFF, ih16[0]) + + def test_minaddr(self): + ih = intelhex.IntelHex16bit(self.f) + addr = ih.minaddr() + self.assertEqual(0, addr, + 'Error in detection of minaddr (0 != 0x%x)' % addr) + + def test_maxaddr(self): + ih = intelhex.IntelHex16bit(self.f) + addr = ih.maxaddr() + self.assertEqual(0x001D, addr, + 'Error in detection of maxaddr ' + '(0x001D != 0x%x)' % addr) + + def test_getitem(self): + ih = intelhex.IntelHex16bit(self.f) + ih.padding = 0x3FFF + for addr, word in enumerate(bin16): + self.assertEqual(word, ih[addr], + 'Data mismatch at address ' + '0x%x (0x%x != 0x%x)' % (addr, word, ih[addr])) + + def test_not_enough_data(self): + ih = intelhex.IntelHex() + ih[0] = 1 + ih16 = intelhex.IntelHex16bit(ih) + self.assertRaisesMsg(BadAccess16bit, + 'Bad access at 0x0: ' + 'not enough data to read 16 bit value', + lambda x: ih16[x], + 0) + + def test_write_hex_file(self): + ih = intelhex.IntelHex16bit(self.f) + sio = StringIO() + ih.write_hex_file(sio) + s = sio.getvalue() + sio.close() + + fin = StringIO(s) + ih2 = intelhex.IntelHex16bit(fin) + + self.assertEqual(ih.tobinstr(), ih2.tobinstr(), + "Written hex file does not equal with original") + + def test_bug_988148(self): + # see https://bugs.launchpad.net/intelhex/+bug/988148 + ih = intelhex.IntelHex16bit(intelhex.IntelHex()) + ih[0] = 25 + sio = StringIO() + ih.write_hex_file(sio) + + def test_setitem(self): + ih = intelhex.IntelHex16bit(self.f) + + old = ih[0] + ih[0] = old ^ 0xFFFF + + self.assertNotEqual(old, ih[0], + "Setting new value to internal buffer failed") + + def test_tobinarray(self): + ih = intelhex.IntelHex16bit() + ih[0] = 0x1234 + ih[1] = 0x5678 + self.assertEqual(array.array('H', [0x1234,0x5678,0xFFFF]), + ih.tobinarray(start=0, end=2)) + # change padding + ih.padding = 0x3FFF + self.assertEqual(array.array('H', [0x1234,0x5678,0x3FFF]), + ih.tobinarray(start=0, end=2)) +#/class TestIntelHex16bit + + +class TestIntelHexErrors(TestIntelHexBase): + """Tests for custom errors classes""" + + def assertEqualExc(self, message, exception): + return self.assertEqual(message, str(exception)) + + def test_IntelHexError(self): + self.assertEqualExc('IntelHex base error', IntelHexError()) + + def test_IntelHexError_message(self): + self.assertEqualExc('IntelHex custom error message', + IntelHexError(msg='IntelHex custom error message')) + self.assertEqualExc('IntelHex base error', IntelHexError(msg='')) + + def test_HexReaderError(self): + self.assertEqualExc('Hex reader base error', HexReaderError()) + + def test_HexRecordError(self): + self.assertEqualExc('Hex file contains invalid record at line 1', + HexRecordError(line=1)) + + def test_RecordLengthError(self): + self.assertEqualExc('Record at line 1 has invalid length', + RecordLengthError(line=1)) + + def test_RecordTypeError(self): + self.assertEqualExc('Record at line 1 has invalid record type', + RecordTypeError(line=1)) + + def test_RecordChecksumError(self): + self.assertEqualExc('Record at line 1 has invalid checksum', + RecordChecksumError(line=1)) + + def test_EOFRecordError(self): + self.assertEqualExc('File has invalid End-of-File record', + EOFRecordError()) + + def test_ExtendedSegmentAddressRecordError(self): + self.assertEqualExc( + 'Invalid Extended Segment Address Record at line 1', + ExtendedSegmentAddressRecordError(line=1)) + + def test_ExtendedLinearAddressRecordError(self): + self.assertEqualExc('Invalid Extended Linear Address Record at line 1', + ExtendedLinearAddressRecordError(line=1)) + + def test_StartSegmentAddressRecordError(self): + self.assertEqualExc('Invalid Start Segment Address Record at line 1', + StartSegmentAddressRecordError(line=1)) + + def test_StartLinearAddressRecordError(self): + self.assertEqualExc('Invalid Start Linear Address Record at line 1', + StartLinearAddressRecordError(line=1)) + + def test_DuplicateStartAddressRecord(self): + self.assertEqualExc('Start Address Record appears twice at line 1', + DuplicateStartAddressRecordError(line=1)) + + def test_InvalidStartAddressValue(self): + self.assertEqualExc("Invalid start address value: {'foo': 1}", + InvalidStartAddressValueError(start_addr={'foo': 1})) + + def test_AddressOverlapError(self): + self.assertEqualExc('Hex file has data overlap at address 0x1234 ' + 'on line 1', + AddressOverlapError(address=0x1234, line=1)) + + def test_NotEnoughDataError(self): + self.assertEqualExc('Bad access at 0x1234: ' + 'not enough data to read 10 contiguous bytes', + intelhex.NotEnoughDataError(address=0x1234, length=10)) + + def test_BadAccess16bit(self): + self.assertEqualExc('Bad access at 0x1234: ' + 'not enough data to read 16 bit value', + BadAccess16bit(address=0x1234)) +#/class TestIntelHexErrors + + +class TestDecodeHexRecords(TestIntelHexBase): + """Testing that decoding of records is correct + and all errors raised when needed + """ + + def setUp(self): + self.ih = IntelHex() + self.decode_record = self.ih._decode_record + + def tearDown(self): + del self.ih + + def test_empty_line(self): + # do we could to accept empty lines in hex files? + # standard don't say anything about this + self.decode_record('') + + def test_non_empty_line(self): + self.assertRaisesMsg(HexRecordError, + 'Hex file contains invalid record at line 1', + self.decode_record, + ' ', + 1) + + def test_short_record(self): + # if record too short it's not a hex record + self.assertRaisesMsg(HexRecordError, + 'Hex file contains invalid record at line 1', + self.decode_record, + ':', + 1) + + def test_odd_hexascii_digits(self): + self.assertRaisesMsg(HexRecordError, + 'Hex file contains invalid record at line 1', + self.decode_record, + ':0100000100F', + 1) + + def test_invalid_length(self): + self.assertRaisesMsg(RecordLengthError, + 'Record at line 1 has invalid length', + self.decode_record, + ':FF00000100', + 1) + + def test_invalid_record_type(self): + self.assertRaisesMsg(RecordTypeError, + 'Record at line 1 has invalid record type', + self.decode_record, + ':000000FF01', + 1) + + def test_invalid_checksum(self): + self.assertRaisesMsg(RecordChecksumError, + 'Record at line 1 has invalid checksum', + self.decode_record, + ':0000000100', + 1) + + def test_invalid_eof(self): + self.assertRaisesMsg(EOFRecordError, + 'File has invalid End-of-File record', + self.decode_record, + ':0100000100FE', + 1) + + def test_invalid_extended_segment(self): + # length + self.assertRaisesMsg(ExtendedSegmentAddressRecordError, + 'Invalid Extended Segment Address Record at line 1', + self.decode_record, + ':00000002FE', + 1) + # addr field + self.assertRaisesMsg(ExtendedSegmentAddressRecordError, + 'Invalid Extended Segment Address Record at line 1', + self.decode_record, + ':020001020000FB', + 1) + + def test_invalid_linear_address(self): + # length + self.assertRaisesMsg(ExtendedLinearAddressRecordError, + 'Invalid Extended Linear Address Record ' + 'at line 1', + self.decode_record, + ':00000004FC', + 1) + # addr field + self.assertRaisesMsg(ExtendedLinearAddressRecordError, + 'Invalid Extended Linear Address Record ' + 'at line 1', + self.decode_record, + ':020001040000F9', + 1) + + def test_invalid_start_segment_addr(self): + # length + self.assertRaisesMsg(StartSegmentAddressRecordError, + 'Invalid Start Segment Address Record at line 1', + self.decode_record, + ':00000003FD', + 1) + # addr field + self.assertRaisesMsg(StartSegmentAddressRecordError, + 'Invalid Start Segment Address Record at line 1', + self.decode_record, + ':0400010300000000F8', + 1) + + def test_duplicate_start_segment_addr(self): + self.decode_record(':0400000312345678E5') + self.assertRaisesMsg(DuplicateStartAddressRecordError, + 'Start Address Record appears twice at line 2', + self.decode_record, + ':0400000300000000F9', + 2) + + def test_invalid_start_linear_addr(self): + # length + self.assertRaisesMsg(StartLinearAddressRecordError, + 'Invalid Start Linear Address Record at line 1', + self.decode_record, + ':00000005FB', + 1) + # addr field + self.assertRaisesMsg(StartLinearAddressRecordError, + 'Invalid Start Linear Address Record at line 1', + self.decode_record, + ':0400010500000000F6', + 1) + + def test_duplicate_start_linear_addr(self): + self.decode_record(':0400000512345678E3') + self.assertRaisesMsg(DuplicateStartAddressRecordError, + 'Start Address Record appears twice at line 2', + self.decode_record, + ':0400000500000000F7', + 2) + + def test_addr_overlap(self): + self.decode_record(':0100000000FF') + self.assertRaisesMsg(AddressOverlapError, + 'Hex file has data overlap at address 0x0 ' + 'on line 1', + self.decode_record, + ':0100000000FF', + 1) + + def test_data_record(self): + # should be no exceptions + self.decode_record(':0100000000FF\n') + self.decode_record(':03000100000102F9\r\n') + self.decode_record(':1004E300CFF0FBE2FDF220FF20F2E120E2FBE6F396') + + def test_eof(self): + # EOF should raise special exception + self.assertRaises(_EndOfFile, self.decode_record, ':00000001FF') + +#/class TestDecodeHexRecords + + +class TestHex2Bin(unittest.TestCase): + + def setUp(self): + self.fin = StringIO(hex8) + self.fout = BytesIO() + + def tearDown(self): + self.fin.close() + self.fout.close() + + def test_hex2bin(self): + ih = hex2bin(self.fin, self.fout) + data = array.array('B', asbytes(self.fout.getvalue())) + for addr in range_g(len(bin8)): + expected = bin8[addr] + actual = data[addr] + self.assertEqual(expected, actual, + "Data different at address " + "%x (%x != %x)" % (addr, expected, actual)) + + +class TestDiffDumps(unittest.TestCase): + + def test_simple(self): + ih1 = IntelHex({1:0x30, 20:0x31, 40:0x33}) + ih2 = IntelHex({1:0x30, 20:0x32, 40:0x33}) + sio = StringIO() + intelhex.diff_dumps(ih1, ih2, sio) + result = sio.getvalue() + extra = ' ' + if sys.version_info[0] >= 3 or sys.version >= '2.7': + extra = '' + shouldbe = ( + "--- a%(extra)s\n" + "+++ b%(extra)s\n" + "@@ -1,3 +1,3 @@\n" + " 0000 -- 30 -- -- -- -- -- -- -- -- -- -- -- -- -- -- | 0 |\n" + "-0010 -- -- -- -- 31 -- -- -- -- -- -- -- -- -- -- -- | 1 |\n" + "+0010 -- -- -- -- 32 -- -- -- -- -- -- -- -- -- -- -- | 2 |\n" + " 0020 -- -- -- -- -- -- -- -- 33 -- -- -- -- -- -- -- | 3 |\n" + ) % dict(extra=extra) + self.assertEqual(shouldbe, result) + + +class TestBuildRecords(TestIntelHexBase): + + def test__from_bytes(self): + self.assertEqual(':00000001FF', + intelhex.Record._from_bytes([0,0,0,1])) + + def test_data(self): + self.assertEqual(':011234005663', intelhex.Record.data(0x1234, [0x56])) + self.assertEqual(':0312340056789059', + intelhex.Record.data(0x1234, [0x56, 0x78, 0x90])) + + def test_eof(self): + self.assertEqual(':00000001FF', intelhex.Record.eof()) + + def test_extended_segment_address(self): + self.assertEqual(':020000021234B6', + intelhex.Record.extended_segment_address(0x1234)) + + def test_start_segment_address(self): + self.assertEqual(':0400000312345678E5', + intelhex.Record.start_segment_address(0x1234, 0x5678)) + + def test_extended_linear_address(self): + self.assertEqual(':020000041234B4', + intelhex.Record.extended_linear_address(0x1234)) + + def test_start_linear_address(self): + self.assertEqual(':0400000512345678E3', + intelhex.Record.start_linear_address(0x12345678)) + + +class Test_GetFileAndAddrRange(TestIntelHexBase): + + def test_simple(self): + self.assertEqual(('filename.hex', None, None), + intelhex._get_file_and_addr_range('filename.hex')) + self.assertEqual(('f', None, None), + intelhex._get_file_and_addr_range('f')) + self.assertEqual(('filename.hex', 1, None), + intelhex._get_file_and_addr_range('filename.hex:1:')) + self.assertEqual(('filename.hex', None, 10), + intelhex._get_file_and_addr_range('filename.hex::A')) + self.assertEqual(('filename.hex', 1, 10), + intelhex._get_file_and_addr_range('filename.hex:1:A')) + self.assertEqual(('filename.hex', 1, 10), + intelhex._get_file_and_addr_range('filename.hex:0001:000A')) + + def test_bad_notation(self): + self.assertRaises(intelhex._BadFileNotation, + intelhex._get_file_and_addr_range, 'filename.hex:') + self.assertRaises(intelhex._BadFileNotation, + intelhex._get_file_and_addr_range, 'filename.hex:::') + self.assertRaises(intelhex._BadFileNotation, + intelhex._get_file_and_addr_range, 'C:\\filename.hex:', True) + + def test_drive_letter(self): + self.assertEqual(('C:\\filename.hex', None, None), + intelhex._get_file_and_addr_range('C:\\filename.hex', True)) + self.assertEqual(('C:\\filename.hex', 1, None), + intelhex._get_file_and_addr_range('C:\\filename.hex:1:', True)) + self.assertEqual(('C:\\filename.hex', None, 10), + intelhex._get_file_and_addr_range('C:\\filename.hex::A', True)) + self.assertEqual(('C:\\filename.hex', 1, 10), + intelhex._get_file_and_addr_range('C:\\filename.hex:1:A', True)) + self.assertEqual(('C:\\filename.hex', 1, 10), + intelhex._get_file_and_addr_range('C:\\filename.hex:0001:000A', True)) + + +class TestXrangeLongInt(unittest.TestCase): + + def test_xrange_longint(self): + # Bug #1408934: xrange(longint) blows with OverflowError: + if compat.Python == 2: + self.assertRaises(OverflowError, xrange, sys.maxint, sys.maxint+3) + # + upr = compat.range_g(2684625744, 2684625747) + self.assertEqual([2684625744, 2684625745, 2684625746], list(upr)) + upr = compat.range_g(2684625744, 2684625747, 2) + self.assertEqual([2684625744, 2684625746], list(upr)) + # + dnr = compat.range_g(2684625746, 2684625743, -1) + self.assertEqual([2684625746, 2684625745, 2684625744], list(dnr)) + dnr = compat.range_g(2684625746, 2684625743, -2) + self.assertEqual([2684625746, 2684625744], list(dnr)) + + +class TestInSubprocess(unittest.TestCase): + + def runProcessAndGetAsciiStdoutOrStderr(self, cmdline): + if sys.platform != 'win32': + cmdline = shlex.split(cmdline) + p = subprocess.Popen(cmdline, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + stdout, stderr = p.communicate() + retcode = p.poll() + if stdout: + output = stdout.decode('ascii', 'replace') + elif stderr: + output = stderr.decode('ascii', 'replace') + output = output.replace('\r', '') + return retcode, output + + def versionChecker(self, cmdline_template): + cmdline = cmdline_template % sys.executable + retcode, output = self.runProcessAndGetAsciiStdoutOrStderr(cmdline) + self.assertEqual(version_str, output.rstrip()) + self.assertEqual(0, retcode) + + def test_setup_version(self): + self.versionChecker('%s setup.py --version') + + def test_sripts_bin2hex_version(self): + self.versionChecker('%s scripts/bin2hex.py --version') + + def test_sripts_hex2bin_version(self): + self.versionChecker('%s scripts/hex2bin.py --version') + + def test_sripts_hex2dump_version(self): + self.versionChecker('%s scripts/hex2dump.py --version') + + def test_sripts_hexdiff_version(self): + self.versionChecker('%s scripts/hexdiff.py --version') + + def test_sripts_hexmerge_version(self): + self.versionChecker('%s scripts/hexmerge.py --version') + + +class TestWriteHexFileByteCount(unittest.TestCase): + + def setUp(self): + self.f = StringIO(hex8) + + def tearDown(self): + self.f.close() + del self.f + + def test_write_hex_file_bad_byte_count(self): + ih = intelhex.IntelHex(self.f) + sio = StringIO() + self.assertRaises(ValueError, ih.write_hex_file, sio, byte_count=0) + self.assertRaises(ValueError, ih.write_hex_file, sio, byte_count=-1) + self.assertRaises(ValueError, ih.write_hex_file, sio, byte_count=256) + + def test_write_hex_file_byte_count_1(self): + ih = intelhex.IntelHex(self.f) + ih1 = ih[:4] + sio = StringIO() + ih1.write_hex_file(sio, byte_count=1) + s = sio.getvalue() + sio.close() + # check that we have all data records with data length == 1 + self.assertEqual(( + ':0100000002FD\n' + ':0100010005F9\n' + ':01000200A25B\n' + ':01000300E517\n' + ':00000001FF\n' + ), s, + "Written hex is not in byte count 1") + # read back and check content + fin = StringIO(s) + ih2 = intelhex.IntelHex(fin) + self.assertEqual(ih1.tobinstr(), ih2.tobinstr(), + "Written hex file does not equal with original") + + def test_write_hex_file_byte_count_13(self): + ih = intelhex.IntelHex(self.f) + sio = StringIO() + ih.write_hex_file(sio, byte_count=13) + s = sio.getvalue() + # control written hex first line to check that byte count is 13 + sio.seek(0) + self.assertEqual(sio.readline(), + ':0D0000000205A2E576246AF8E6057622786E\n', + "Written hex is not in byte count 13") + sio.close() + + fin = StringIO(s) + ih2 = intelhex.IntelHex(fin) + + self.assertEqual(ih.tobinstr(), ih2.tobinstr(), + "Written hex file does not equal with original") + + def test_write_hex_file_byte_count_255(self): + ih = intelhex.IntelHex(self.f) + sio = StringIO() + ih.write_hex_file(sio, byte_count=255) + s = sio.getvalue() + # control written hex first line to check that byte count is 255 + sio.seek(0) + self.assertEqual(sio.readline(), + (':FF0000000205A2E576246AF8E60576227867300702786AE475F0011204AD02' + '04552000EB7F2ED2008018EF540F2490D43440D4FF30040BEF24BFB41A0050' + '032461FFE57760021577057AE57A7002057930070D7867E475F0011204ADEF' + '02049B02057B7403D2078003E4C207F5768B678A688969E4F577F579F57AE5' + '7760077F2012003E80F57578FFC201C200C202C203C205C206C20812000CFF' + '700D3007057F0012004FAF7AAE7922B4255FC2D5C20412000CFF24D0B40A00' + '501A75F00A787730D50508B6FF0106C6A426F620D5047002D20380D924CFB4' + '1A00EF5004C2E5D20402024FD20180C6D20080C0D20280BCD2D580BAD20580' + 'B47F2012003E20020774010E\n'), + "Written hex is not in byte count 255") + sio.close() + + fin = StringIO(s) + ih2 = intelhex.IntelHex(fin) + + self.assertEqual(ih.tobinstr(), ih2.tobinstr(), + "Written hex file does not equal with original") + +## +# MAIN +if __name__ == '__main__': + unittest.main() diff --git a/tools/python/esptool/loader.py b/tools/python/esptool/loader.py index e88e174d..2c6b0369 100644 --- a/tools/python/esptool/loader.py +++ b/tools/python/esptool/loader.py @@ -170,6 +170,8 @@ class StubFlasher: self.data = None self.data_start = None + self.bss_start = stub.get("bss_start") + class ESPLoader(object): """Base class providing access to ESP ROM & software stub bootloaders. @@ -184,8 +186,6 @@ class ESPLoader(object): CHIP_NAME = "Espressif device" IS_STUB = False - FPGA_SLOW_BOOT = False - DEFAULT_PORT = "/dev/ttyUSB0" USES_RFC2217 = False @@ -301,8 +301,39 @@ class ESPLoader(object): if isinstance(port, str): try: self._port = serial.serial_for_url(port) - except serial.serialutil.SerialException: - raise FatalError(f"Could not open {port}, the port doesn't exist") + except serial.serialutil.SerialException as e: + port_issues = [ + [ # does not exist error + re.compile(r"Errno 2|FileNotFoundError", re.IGNORECASE), + "Check if the port is correct and ESP connected", + ], + [ # busy port error + re.compile(r"Access is denied", re.IGNORECASE), + "Check if the port is not used by another task", + ], + ] + if sys.platform.startswith("linux"): + port_issues.append( + [ # permission denied error + re.compile(r"Permission denied", re.IGNORECASE), + ( + "Try to add user into dialout group: " + "sudo usermod -a -G dialout $USER" + ), + ], + ) + + hint_msg = "" + for port_issue in port_issues: + if port_issue[0].search(str(e)): + hint_msg = f"\nHint: {port_issue[1]}\n" + break + + raise FatalError( + f"Could not open {port}, the port is busy or doesn't exist." + f"\n({e})\n" + f"{hint_msg}" + ) else: self._port = port self._slip_reader = slip_reader(self._port, self.trace) @@ -597,7 +628,7 @@ class ESPLoader(object): # This FPGA delay is for Espressif internal use if ( - self.FPGA_SLOW_BOOT + self.CHIP_NAME == "ESP32" and os.environ.get("ESPTOOL_ENV_FPGA", "").strip() == "1" ): delay = extra_delay = 7 @@ -651,8 +682,17 @@ class ESPLoader(object): print("") # end 'Connecting...' line if last_error is not None: + additional_msg = "" + if self.CHIP_NAME == "ESP32-C2" and self._port.baudrate < 115200: + additional_msg = ( + "\nNote: Please set a higher baud rate (--baud)" + " if ESP32-C2 doesn't connect" + " (at least 115200 Bd is recommended)." + ) + raise FatalError( "Failed to connect to {}: {}" + f"{additional_msg}" "\nFor troubleshooting steps visit: " "https://docs.espressif.com/projects/esptool/en/latest/troubleshooting.html".format( # noqa E501 self.CHIP_NAME, last_error @@ -751,17 +791,17 @@ class ESPLoader(object): stub = StubFlasher(get_stub_json_path(self.CHIP_NAME)) load_start = offset load_end = offset + size - for start, end in [ - (stub.data_start, stub.data_start + len(stub.data)), - (stub.text_start, stub.text_start + len(stub.text)), + for stub_start, stub_end in [ + (stub.bss_start, stub.data_start + len(stub.data)), # DRAM = bss+data + (stub.text_start, stub.text_start + len(stub.text)), # IRAM ]: - if load_start < end and load_end > start: + if load_start < stub_end and load_end > stub_start: raise FatalError( "Software loader is resident at 0x%08x-0x%08x. " "Can't load binary at overlapping address range 0x%08x-0x%08x. " "Either change binary loading address, or use the --no-stub " "option to disable the software loader." - % (start, end, load_start, load_end) + % (stub_start, stub_end, load_start, load_end) ) return self.check_command( diff --git a/tools/python/esptool/targets/__init__.py b/tools/python/esptool/targets/__init__.py index 9d76ca54..dd1ba485 100644 --- a/tools/python/esptool/targets/__init__.py +++ b/tools/python/esptool/targets/__init__.py @@ -6,6 +6,7 @@ from .esp32c6beta import ESP32C6BETAROM from .esp32h2 import ESP32H2ROM from .esp32h2beta1 import ESP32H2BETA1ROM from .esp32h2beta2 import ESP32H2BETA2ROM +from .esp32p4 import ESP32P4ROM from .esp32s2 import ESP32S2ROM from .esp32s3 import ESP32S3ROM from .esp32s3beta2 import ESP32S3BETA2ROM @@ -25,6 +26,7 @@ CHIP_DEFS = { "esp32c2": ESP32C2ROM, "esp32c6": ESP32C6ROM, "esp32h2": ESP32H2ROM, + "esp32p4": ESP32P4ROM, } CHIP_LIST = list(CHIP_DEFS.keys()) diff --git a/tools/python/esptool/targets/esp32.py b/tools/python/esptool/targets/esp32.py index 487b3e7a..cbc7fb8f 100644 --- a/tools/python/esptool/targets/esp32.py +++ b/tools/python/esptool/targets/esp32.py @@ -17,8 +17,6 @@ class ESP32ROM(ESPLoader): IMAGE_CHIP_ID = 0 IS_STUB = False - FPGA_SLOW_BOOT = True - CHIP_DETECT_MAGIC_VALUE = [0x00F01D83] IROM_MAP_START = 0x400D0000 @@ -105,6 +103,8 @@ class ESP32ROM(ESPLoader): FLASH_ENCRYPTED_WRITE_ALIGN = 32 + UF2_FAMILY_ID = 0x1C5F21B0 + """ Try to read the BLOCK1 (encryption key) and check if it is valid """ def is_flash_encryption_key_valid(self): @@ -281,7 +281,7 @@ class ESP32ROM(ESPLoader): return self.read_reg(self.EFUSE_RD_REG_BASE + (4 * n)) def chip_id(self): - raise NotSupportedError(self, "chip_id") + raise NotSupportedError(self, "Function chip_id") def read_mac(self, mac_type="BASE_MAC"): """Read MAC from EFUSE region""" @@ -361,6 +361,7 @@ class ESP32ROM(ESPLoader): return rom_calculated_freq def change_baud(self, baud): + assert self.CHIP_NAME == "ESP32", "This workaround should only apply to ESP32" # It's a workaround to avoid esp32 CK_8M frequency drift. rom_calculated_freq = self.get_rom_cal_crystal_freq() valid_freq = 40000000 if rom_calculated_freq > 33000000 else 26000000 @@ -373,6 +374,11 @@ class ESP32ROM(ESPLoader): time.sleep(0.05) # get rid of garbage sent during baud rate change self.flush_input() + def check_spi_connection(self, spi_connection): + # Pins 30, 31 do not exist + if not set(spi_connection).issubset(set(range(0, 30)) | set((32, 33))): + raise FatalError("SPI Pin numbers must be in the range 0-29, 32, or 33.") + class ESP32StubLoader(ESP32ROM): """Access class for ESP32 stub loader, runs on top of ROM.""" diff --git a/tools/python/esptool/targets/esp32c2.py b/tools/python/esptool/targets/esp32c2.py index e1b6a2d5..e1f22809 100644 --- a/tools/python/esptool/targets/esp32c2.py +++ b/tools/python/esptool/targets/esp32c2.py @@ -8,6 +8,7 @@ import time from .esp32c3 import ESP32C3ROM from loader import ESPLoader +from util import FatalError class ESP32C2ROM(ESP32C3ROM): @@ -61,6 +62,8 @@ class ESP32C2ROM(ESP32C3ROM): [0x4037C000, 0x403C0000, "IRAM"], ] + UF2_FAMILY_ID = 0x2B88D29C + def get_pkg_version(self): num_word = 1 return (self.read_reg(self.EFUSE_BLOCK2_ADDR + (4 * num_word)) >> 22) & 0x07 @@ -82,6 +85,16 @@ class ESP32C2ROM(ESP32C3ROM): num_word = 1 return (self.read_reg(self.EFUSE_BLOCK2_ADDR + (4 * num_word)) >> 20) & 0x3 + def get_flash_cap(self): + # ESP32-C2 doesn't have eFuse field FLASH_CAP. + # Can't get info about the flash chip. + return 0 + + def get_flash_vendor(self): + # ESP32-C2 doesn't have eFuse field FLASH_VENDOR. + # Can't get info about the flash chip. + return "" + def get_crystal_freq(self): # The crystal detection algorithm of ESP32/ESP8266 works for ESP32-C2 as well. return ESPLoader.get_crystal_freq(self) @@ -110,7 +123,7 @@ class ESP32C2ROM(ESP32C3ROM): def _post_connect(self): # ESP32C2 ECO0 is no longer supported by the flasher stub - if self.get_chip_revision() == 0: + if not self.secure_download_mode and self.get_chip_revision() == 0: self.stub_is_disabled = True self.IS_STUB = False @@ -142,6 +155,10 @@ class ESP32C2ROM(ESP32C3ROM): return True return False + def check_spi_connection(self, spi_connection): + if not set(spi_connection).issubset(set(range(0, 21))): + raise FatalError("SPI Pin numbers must be in the range 0-20.") + class ESP32C2StubLoader(ESP32C2ROM): """Access class for ESP32C2 stub loader, runs on top of ROM. diff --git a/tools/python/esptool/targets/esp32c3.py b/tools/python/esptool/targets/esp32c3.py index 04dbe4f2..276b7d66 100644 --- a/tools/python/esptool/targets/esp32c3.py +++ b/tools/python/esptool/targets/esp32c3.py @@ -14,8 +14,6 @@ class ESP32C3ROM(ESP32ROM): CHIP_NAME = "ESP32-C3" IMAGE_CHIP_ID = 5 - FPGA_SLOW_BOOT = False - IROM_MAP_START = 0x42000000 IROM_MAP_END = 0x42800000 DROM_MAP_START = 0x3C000000 @@ -31,8 +29,8 @@ class ESP32C3ROM(ESP32ROM): BOOTLOADER_FLASH_OFFSET = 0x0 - # Magic value for ESP32C3 eco 1+2 and ESP32C3 eco3 respectivly - CHIP_DETECT_MAGIC_VALUE = [0x6921506F, 0x1B31506F] + # Magic values for ESP32-C3 eco 1+2, eco 3, eco 6, and eco 7 respectively + CHIP_DETECT_MAGIC_VALUE = [0x6921506F, 0x1B31506F, 0x4881606F, 0x4361606F] UART_DATE_REG_ADDR = 0x60000000 + 0x7C @@ -99,6 +97,8 @@ class ESP32C3ROM(ESP32ROM): [0x600FE000, 0x60100000, "MEM_INTERNAL2"], ] + UF2_FAMILY_ID = 0xD42BA06C + def get_pkg_version(self): num_word = 3 return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 21) & 0x07 @@ -114,16 +114,39 @@ class ESP32C3ROM(ESP32ROM): num_word = 5 return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 24) & 0x03 + def get_flash_cap(self): + num_word = 3 + return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 27) & 0x07 + + def get_flash_vendor(self): + num_word = 4 + vendor_id = (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 0) & 0x07 + return {1: "XMC", 2: "GD", 3: "FM", 4: "TT", 5: "ZBIT"}.get(vendor_id, "") + def get_chip_description(self): chip_name = { - 0: "ESP32-C3", + 0: "ESP32-C3 (QFN32)", + 1: "ESP8685 (QFN28)", + 2: "ESP32-C3 AZ (QFN32)", + 3: "ESP8686 (QFN24)", }.get(self.get_pkg_version(), "unknown ESP32-C3") major_rev = self.get_major_chip_version() minor_rev = self.get_minor_chip_version() return f"{chip_name} (revision v{major_rev}.{minor_rev})" def get_chip_features(self): - return ["WiFi", "BLE"] + features = ["WiFi", "BLE"] + + flash = { + 0: None, + 1: "Embedded Flash 4MB", + 2: "Embedded Flash 2MB", + 3: "Embedded Flash 1MB", + 4: "Embedded Flash 8MB", + }.get(self.get_flash_cap(), "Unknown Embedded Flash") + if flash is not None: + features += [flash + f" ({self.get_flash_vendor()})"] + return features def get_crystal_freq(self): # ESP32C3 XTAL is fixed to 40MHz @@ -205,6 +228,15 @@ class ESP32C3ROM(ESP32ROM): if not self.sync_stub_detected: # Don't run if stub is reused self.disable_watchdogs() + def check_spi_connection(self, spi_connection): + if not set(spi_connection).issubset(set(range(0, 22))): + raise FatalError("SPI Pin numbers must be in the range 0-21.") + if any([v for v in spi_connection if v in [18, 19]]): + print( + "WARNING: GPIO pins 18 and 19 are used by USB-Serial/JTAG, " + "consider using other pins for SPI flash connection." + ) + class ESP32C3StubLoader(ESP32C3ROM): """Access class for ESP32C3 stub loader, runs on top of ROM. diff --git a/tools/python/esptool/targets/esp32c6.py b/tools/python/esptool/targets/esp32c6.py index e3d801c7..003238ad 100644 --- a/tools/python/esptool/targets/esp32c6.py +++ b/tools/python/esptool/targets/esp32c6.py @@ -13,8 +13,6 @@ class ESP32C6ROM(ESP32C3ROM): CHIP_NAME = "ESP32-C6" IMAGE_CHIP_ID = 13 - FPGA_SLOW_BOOT = False - IROM_MAP_START = 0x42000000 IROM_MAP_END = 0x42800000 DROM_MAP_START = 0x42800000 @@ -101,6 +99,8 @@ class ESP32C6ROM(ESP32C3ROM): [0x600FE000, 0x60100000, "MEM_INTERNAL2"], ] + UF2_FAMILY_ID = 0x540DDF62 + def get_pkg_version(self): num_word = 3 return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 24) & 0x07 @@ -180,6 +180,15 @@ class ESP32C6ROM(ESP32C3ROM): return any(p == self.PURPOSE_VAL_XTS_AES128_KEY for p in purposes) + def check_spi_connection(self, spi_connection): + if not set(spi_connection).issubset(set(range(0, 31))): + raise FatalError("SPI Pin numbers must be in the range 0-30.") + if any([v for v in spi_connection if v in [12, 13]]): + print( + "WARNING: GPIO pins 12 and 13 are used by USB-Serial/JTAG, " + "consider using other pins for SPI flash connection." + ) + class ESP32C6StubLoader(ESP32C6ROM): """Access class for ESP32C6 stub loader, runs on top of ROM. diff --git a/tools/python/esptool/targets/esp32h2.py b/tools/python/esptool/targets/esp32h2.py index 88a0bba1..43d0ed46 100644 --- a/tools/python/esptool/targets/esp32h2.py +++ b/tools/python/esptool/targets/esp32h2.py @@ -4,6 +4,7 @@ # SPDX-License-Identifier: GPL-2.0-or-later from .esp32c6 import ESP32C6ROM +from util import FatalError class ESP32H2ROM(ESP32C6ROM): @@ -29,6 +30,8 @@ class ESP32H2ROM(ESP32C6ROM): "12m": 0x2, } + UF2_FAMILY_ID = 0x332726F6 + def get_pkg_version(self): num_word = 4 return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 0) & 0x07 @@ -56,6 +59,15 @@ class ESP32H2ROM(ESP32C6ROM): # ESP32H2 XTAL is fixed to 32MHz return 32 + def check_spi_connection(self, spi_connection): + if not set(spi_connection).issubset(set(range(0, 28))): + raise FatalError("SPI Pin numbers must be in the range 0-27.") + if any([v for v in spi_connection if v in [26, 27]]): + print( + "WARNING: GPIO pins 26 and 27 are used by USB-Serial/JTAG, " + "consider using other pins for SPI flash connection." + ) + class ESP32H2StubLoader(ESP32H2ROM): """Access class for ESP32H2 stub loader, runs on top of ROM. diff --git a/tools/python/esptool/targets/esp32p4.py b/tools/python/esptool/targets/esp32p4.py new file mode 100644 index 00000000..2c18205b --- /dev/null +++ b/tools/python/esptool/targets/esp32p4.py @@ -0,0 +1,195 @@ +# SPDX-FileCopyrightText: 2023 Fredrik Ahlberg, Angus Gratton, +# Espressif Systems (Shanghai) CO LTD, other contributors as noted. +# +# SPDX-License-Identifier: GPL-2.0-or-later + +import struct + +from .esp32 import ESP32ROM +from loader import ESPLoader +from util import FatalError, NotImplementedInROMError + + +class ESP32P4ROM(ESP32ROM): + CHIP_NAME = "ESP32-P4" + IMAGE_CHIP_ID = 18 + + IROM_MAP_START = 0x40000000 + IROM_MAP_END = 0x4C000000 + DROM_MAP_START = 0x40000000 + DROM_MAP_END = 0x4C000000 + + BOOTLOADER_FLASH_OFFSET = 0x2000 # First 2 sectors are reserved for FE purposes + + CHIP_DETECT_MAGIC_VALUE = [0x0] + + UART_DATE_REG_ADDR = 0x500CA000 + 0x8C + + EFUSE_BASE = 0x5012D000 + EFUSE_BLOCK1_ADDR = EFUSE_BASE + 0x044 + MAC_EFUSE_REG = EFUSE_BASE + 0x044 + + SPI_REG_BASE = 0x5008D000 # SPIMEM1 + SPI_USR_OFFS = 0x18 + SPI_USR1_OFFS = 0x1C + SPI_USR2_OFFS = 0x20 + SPI_MOSI_DLEN_OFFS = 0x24 + SPI_MISO_DLEN_OFFS = 0x28 + SPI_W0_OFFS = 0x58 + + EFUSE_RD_REG_BASE = EFUSE_BASE + 0x030 # BLOCK0 read base address + + EFUSE_PURPOSE_KEY0_REG = EFUSE_BASE + 0x34 + EFUSE_PURPOSE_KEY0_SHIFT = 24 + EFUSE_PURPOSE_KEY1_REG = EFUSE_BASE + 0x34 + EFUSE_PURPOSE_KEY1_SHIFT = 28 + EFUSE_PURPOSE_KEY2_REG = EFUSE_BASE + 0x38 + EFUSE_PURPOSE_KEY2_SHIFT = 0 + EFUSE_PURPOSE_KEY3_REG = EFUSE_BASE + 0x38 + EFUSE_PURPOSE_KEY3_SHIFT = 4 + EFUSE_PURPOSE_KEY4_REG = EFUSE_BASE + 0x38 + EFUSE_PURPOSE_KEY4_SHIFT = 8 + EFUSE_PURPOSE_KEY5_REG = EFUSE_BASE + 0x38 + EFUSE_PURPOSE_KEY5_SHIFT = 12 + + EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT_REG = EFUSE_RD_REG_BASE + EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT = 1 << 20 + + EFUSE_SPI_BOOT_CRYPT_CNT_REG = EFUSE_BASE + 0x034 + EFUSE_SPI_BOOT_CRYPT_CNT_MASK = 0x7 << 18 + + EFUSE_SECURE_BOOT_EN_REG = EFUSE_BASE + 0x038 + EFUSE_SECURE_BOOT_EN_MASK = 1 << 20 + + PURPOSE_VAL_XTS_AES256_KEY_1 = 2 + PURPOSE_VAL_XTS_AES256_KEY_2 = 3 + PURPOSE_VAL_XTS_AES128_KEY = 4 + + SUPPORTS_ENCRYPTED_FLASH = True + + FLASH_ENCRYPTED_WRITE_ALIGN = 16 + + MEMORY_MAP = [ + [0x00000000, 0x00010000, "PADDING"], + [0x40000000, 0x4C000000, "DROM"], + [0x4FF00000, 0x4FFA0000, "DRAM"], + [0x4FF00000, 0x4FFA0000, "BYTE_ACCESSIBLE"], + [0x4FC00000, 0x4FC20000, "DROM_MASK"], + [0x4FC00000, 0x4FC20000, "IROM_MASK"], + [0x40000000, 0x4C000000, "IROM"], + [0x4FF00000, 0x4FFA0000, "IRAM"], + [0x50108000, 0x50110000, "RTC_IRAM"], + [0x50108000, 0x50110000, "RTC_DRAM"], + [0x600FE000, 0x60100000, "MEM_INTERNAL2"], + ] + + UF2_FAMILY_ID = 0x3D308E94 + + def get_pkg_version(self): + # ESP32P4 TODO + return 0 + + def get_minor_chip_version(self): + # ESP32P4 TODO + return 0 + + def get_major_chip_version(self): + # ESP32P4 TODO + return 0 + + def get_chip_description(self): + chip_name = { + 0: "ESP32-P4", + }.get(self.get_pkg_version(), "unknown ESP32-P4") + major_rev = self.get_major_chip_version() + minor_rev = self.get_minor_chip_version() + return f"{chip_name} (revision v{major_rev}.{minor_rev})" + + def get_chip_features(self): + return ["High-Performance MCU"] + + def get_crystal_freq(self): + # ESP32P4 XTAL is fixed to 40MHz + return 40 + + def override_vddsdio(self, new_voltage): + raise NotImplementedInROMError( + "VDD_SDIO overrides are not supported for ESP32-P4" + ) + + def read_mac(self, mac_type="BASE_MAC"): + """Read MAC from EFUSE region""" + if mac_type != "BASE_MAC": + return None + mac0 = self.read_reg(self.MAC_EFUSE_REG) + mac1 = self.read_reg(self.MAC_EFUSE_REG + 4) # only bottom 16 bits are MAC + bitstring = struct.pack(">II", mac1, mac0)[2:] + return tuple(bitstring) + + def get_flash_crypt_config(self): + return None # doesn't exist on ESP32-P4 + + def get_secure_boot_enabled(self): + return ( + self.read_reg(self.EFUSE_SECURE_BOOT_EN_REG) + & self.EFUSE_SECURE_BOOT_EN_MASK + ) + + def get_key_block_purpose(self, key_block): + if key_block < 0 or key_block > 5: + raise FatalError("Valid key block numbers must be in range 0-5") + + reg, shift = [ + (self.EFUSE_PURPOSE_KEY0_REG, self.EFUSE_PURPOSE_KEY0_SHIFT), + (self.EFUSE_PURPOSE_KEY1_REG, self.EFUSE_PURPOSE_KEY1_SHIFT), + (self.EFUSE_PURPOSE_KEY2_REG, self.EFUSE_PURPOSE_KEY2_SHIFT), + (self.EFUSE_PURPOSE_KEY3_REG, self.EFUSE_PURPOSE_KEY3_SHIFT), + (self.EFUSE_PURPOSE_KEY4_REG, self.EFUSE_PURPOSE_KEY4_SHIFT), + (self.EFUSE_PURPOSE_KEY5_REG, self.EFUSE_PURPOSE_KEY5_SHIFT), + ][key_block] + return (self.read_reg(reg) >> shift) & 0xF + + def is_flash_encryption_key_valid(self): + # Need to see either an AES-128 key or two AES-256 keys + purposes = [self.get_key_block_purpose(b) for b in range(6)] + + if any(p == self.PURPOSE_VAL_XTS_AES128_KEY for p in purposes): + return True + + return any(p == self.PURPOSE_VAL_XTS_AES256_KEY_1 for p in purposes) and any( + p == self.PURPOSE_VAL_XTS_AES256_KEY_2 for p in purposes + ) + + def change_baud(self, baud): + ESPLoader.change_baud(self, baud) + + def _post_connect(self): + pass + # TODO: Disable watchdogs when USB modes are supported in the stub + # if not self.sync_stub_detected: # Don't run if stub is reused + # self.disable_watchdogs() + + def check_spi_connection(self, spi_connection): + pass # TODO: Define GPIOs for --spi-connection + + +class ESP32P4StubLoader(ESP32P4ROM): + """Access class for ESP32P4 stub loader, runs on top of ROM. + + (Basically the same as ESP32StubLoader, but different base class. + Can possibly be made into a mixin.) + """ + + FLASH_WRITE_SIZE = 0x4000 # matches MAX_WRITE_BLOCK in stub_loader.c + STATUS_BYTES_LENGTH = 2 # same as ESP8266, different to ESP32 ROM + IS_STUB = True + + def __init__(self, rom_loader): + self.secure_download_mode = rom_loader.secure_download_mode + self._port = rom_loader._port + self._trace_enabled = rom_loader._trace_enabled + self.cache = rom_loader.cache + self.flush_input() # resets _slip_reader + + +ESP32P4ROM.STUB_CLASS = ESP32P4StubLoader diff --git a/tools/python/esptool/targets/esp32s2.py b/tools/python/esptool/targets/esp32s2.py index 79083a79..e77db53d 100644 --- a/tools/python/esptool/targets/esp32s2.py +++ b/tools/python/esptool/targets/esp32s2.py @@ -16,8 +16,6 @@ class ESP32S2ROM(ESP32ROM): CHIP_NAME = "ESP32-S2" IMAGE_CHIP_ID = 2 - FPGA_SLOW_BOOT = False - IROM_MAP_START = 0x40080000 IROM_MAP_END = 0x40B80000 DROM_MAP_START = 0x3F000000 @@ -101,6 +99,8 @@ class ESP32S2ROM(ESP32ROM): [0x50000000, 0x50002000, "RTC_DATA"], ] + UF2_FAMILY_ID = 0xBFDD4EEE + def get_pkg_version(self): num_word = 4 return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 0) & 0x0F @@ -120,10 +120,16 @@ class ESP32S2ROM(ESP32ROM): num_word = 3 return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 21) & 0x0F + def get_flash_cap(self): + return self.get_flash_version() + def get_psram_version(self): num_word = 3 return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 28) & 0x0F + def get_psram_cap(self): + return self.get_psram_version() + def get_block2_version(self): # BLK_VERSION_MINOR num_word = 4 @@ -137,7 +143,7 @@ class ESP32S2ROM(ESP32ROM): 102: "ESP32-S2FNR2", 100: "ESP32-S2R2", }.get( - self.get_flash_version() + self.get_psram_version() * 100, + self.get_flash_cap() + self.get_psram_cap() * 100, "unknown ESP32-S2", ) major_rev = self.get_major_chip_version() @@ -154,14 +160,14 @@ class ESP32S2ROM(ESP32ROM): 0: "No Embedded Flash", 1: "Embedded Flash 2MB", 2: "Embedded Flash 4MB", - }.get(self.get_flash_version(), "Unknown Embedded Flash") + }.get(self.get_flash_cap(), "Unknown Embedded Flash") features += [flash_version] psram_version = { 0: "No Embedded PSRAM", 1: "Embedded PSRAM 2MB", 2: "Embedded PSRAM 4MB", - }.get(self.get_psram_version(), "Unknown Embedded PSRAM") + }.get(self.get_psram_cap(), "Unknown Embedded PSRAM") features += [psram_version] block2_version = { @@ -281,6 +287,15 @@ class ESP32S2ROM(ESP32ROM): def change_baud(self, baud): ESPLoader.change_baud(self, baud) + def check_spi_connection(self, spi_connection): + if not set(spi_connection).issubset(set(range(0, 22)) | set(range(26, 47))): + raise FatalError("SPI Pin numbers must be in the range 0-21, or 26-46.") + if any([v for v in spi_connection if v in [19, 20]]): + print( + "WARNING: GPIO pins 19 and 20 are used by USB-OTG, " + "consider using other pins for SPI flash connection." + ) + class ESP32S2StubLoader(ESP32S2ROM): """Access class for ESP32-S2 stub loader, runs on top of ROM. diff --git a/tools/python/esptool/targets/esp32s3.py b/tools/python/esptool/targets/esp32s3.py index 90961b05..00bcd89c 100644 --- a/tools/python/esptool/targets/esp32s3.py +++ b/tools/python/esptool/targets/esp32s3.py @@ -19,8 +19,6 @@ class ESP32S3ROM(ESP32ROM): CHIP_DETECT_MAGIC_VALUE = [0x9] - FPGA_SLOW_BOOT = False - IROM_MAP_START = 0x42000000 IROM_MAP_END = 0x44000000 DROM_MAP_START = 0x3C000000 @@ -117,6 +115,8 @@ class ESP32S3ROM(ESP32ROM): [0x50000000, 0x50002000, "RTC_DATA"], ] + UF2_FAMILY_ID = 0xC47E5767 + def get_pkg_version(self): num_word = 3 return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 21) & 0x07 @@ -165,10 +165,53 @@ class ESP32S3ROM(ESP32ROM): def get_chip_description(self): major_rev = self.get_major_chip_version() minor_rev = self.get_minor_chip_version() - return f"{self.CHIP_NAME} (revision v{major_rev}.{minor_rev})" + pkg_version = self.get_pkg_version() + + chip_name = { + 0: "ESP32-S3 (QFN56)", + 1: "ESP32-S3-PICO-1 (LGA56)", + }.get(pkg_version, "unknown ESP32-S3") + + return f"{chip_name} (revision v{major_rev}.{minor_rev})" + + def get_flash_cap(self): + num_word = 3 + return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 27) & 0x07 + + def get_flash_vendor(self): + num_word = 4 + vendor_id = (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 0) & 0x07 + return {1: "XMC", 2: "GD", 3: "FM", 4: "TT", 5: "BY"}.get(vendor_id, "") + + def get_psram_cap(self): + num_word = 4 + return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 3) & 0x03 + + def get_psram_vendor(self): + num_word = 4 + vendor_id = (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 7) & 0x03 + return {1: "AP_3v3", 2: "AP_1v8"}.get(vendor_id, "") def get_chip_features(self): - return ["WiFi", "BLE"] + features = ["WiFi", "BLE"] + + flash = { + 0: None, + 1: "Embedded Flash 8MB", + 2: "Embedded Flash 4MB", + }.get(self.get_flash_cap(), "Unknown Embedded Flash") + if flash is not None: + features += [flash + f" ({self.get_flash_vendor()})"] + + psram = { + 0: None, + 1: "Embedded PSRAM 8MB", + 2: "Embedded PSRAM 2MB", + }.get(self.get_psram_cap(), "Unknown Embedded PSRAM") + if psram is not None: + features += [psram + f" ({self.get_psram_vendor()})"] + + return features def get_crystal_freq(self): # ESP32S3 XTAL is fixed to 40MHz @@ -306,6 +349,17 @@ class ESP32S3ROM(ESP32ROM): def change_baud(self, baud): ESPLoader.change_baud(self, baud) + def check_spi_connection(self, spi_connection): + if not set(spi_connection).issubset(set(range(0, 22)) | set(range(26, 49))): + raise FatalError("SPI Pin numbers must be in the range 0-21, or 26-48.") + if spi_connection[3] > 46: # hd_gpio_num must be <= SPI_GPIO_NUM_LIMIT (46) + raise FatalError("SPI HD Pin number must be <= 46.") + if any([v for v in spi_connection if v in [19, 20]]): + print( + "WARNING: GPIO pins 19 and 20 are used by USB-Serial/JTAG and USB-OTG, " + "consider using other pins for SPI flash connection." + ) + class ESP32S3StubLoader(ESP32S3ROM): """Access class for ESP32S3 stub loader, runs on top of ROM. diff --git a/tools/python/esptool/targets/esp32s3beta2.py b/tools/python/esptool/targets/esp32s3beta2.py index b7958bd5..f91bb3cb 100644 --- a/tools/python/esptool/targets/esp32s3beta2.py +++ b/tools/python/esptool/targets/esp32s3beta2.py @@ -14,11 +14,6 @@ class ESP32S3BETA2ROM(ESP32S3ROM): EFUSE_BASE = 0x6001A000 # BLOCK0 read base address - def get_chip_description(self): - major_rev = self.get_major_chip_version() - minor_rev = self.get_minor_chip_version() - return f"{self.CHIP_NAME} (revision v{major_rev}.{minor_rev})" - class ESP32S3BETA2StubLoader(ESP32S3BETA2ROM): """Access class for ESP32S3 stub loader, runs on top of ROM. diff --git a/tools/python/esptool/targets/esp8266.py b/tools/python/esptool/targets/esp8266.py index 8f49c51c..0da8ae7a 100644 --- a/tools/python/esptool/targets/esp8266.py +++ b/tools/python/esptool/targets/esp8266.py @@ -4,7 +4,7 @@ # SPDX-License-Identifier: GPL-2.0-or-later from loader import ESPLoader -from util import FatalError, NotImplementedInROMError +from util import FatalError, NotSupportedError class ESP8266ROM(ESPLoader): @@ -60,6 +60,8 @@ class ESP8266ROM(ESPLoader): [0x40201010, 0x402E1010, "IROM"], ] + UF2_FAMILY_ID = 0x7EAB61ED + def get_efuses(self): # Return the 128 bits of ESP8266 efuse as a single Python integer result = self.read_reg(0x3FF0005C) << 96 @@ -168,9 +170,10 @@ class ESP8266ROM(ESPLoader): return (num_sectors - head_sectors) * sector_size def override_vddsdio(self, new_voltage): - raise NotImplementedInROMError( - "Overriding VDDSDIO setting only applies to ESP32" - ) + raise NotSupportedError(self, "Overriding VDDSDIO") + + def check_spi_connection(self, spi_connection): + raise NotSupportedError(self, "Setting --spi-connection") class ESP8266StubLoader(ESP8266ROM): diff --git a/tools/python/esptool/targets/stub_flasher/stub_flasher_32.json b/tools/python/esptool/targets/stub_flasher/stub_flasher_32.json index 23a283fa..56221e30 100644 --- a/tools/python/esptool/targets/stub_flasher/stub_flasher_32.json +++ b/tools/python/esptool/targets/stub_flasher/stub_flasher_32.json @@ -1,7 +1,8 @@ { - "entry": 1074521560, - "text": "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", + "entry": 1074521580, + "text": "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", "text_start": 1074520064, - "data": "DMD8P9jnC0Br6AtAA+0LQPLoC0CL6AtA8ugLQFHpC0Ae6gtAkOoLQDnqC0CB5wtAtukLQBDqC0B06QtAtOoLQJ7pC0C06gtAWegLQLboC0Dy6AtAUekLQHHoC0Bk6wtAxewLQKTmC0Dn7AtApOYLQKTmC0Ck5gtApOYLQKTmC0Ck5gtApOYLQKTmC0AL6wtApOYLQOXrC0DF7AtA", - "data_start": 1073605544 + "data": "DMD8P+znC0B/6AtAZ+0LQAbpC0Cf6AtABukLQGXpC0CC6gtA9OoLQJ3qC0CV5wtAGuoLQHTqC0CI6QtAGOsLQLDpC0AY6wtAbegLQMroC0AG6QtAZekLQIXoC0DI6wtAKe0LQLjmC0BL7QtAuOYLQLjmC0C45gtAuOYLQLjmC0C45gtAuOYLQLjmC0Bv6wtAuOYLQEnsC0Ap7QtA", + "data_start": 1073605544, + "bss_start": 1073528832 } \ No newline at end of file diff --git a/tools/python/esptool/targets/stub_flasher/stub_flasher_32c2.json b/tools/python/esptool/targets/stub_flasher/stub_flasher_32c2.json index 365c705f..f10ec7b4 100644 --- a/tools/python/esptool/targets/stub_flasher/stub_flasher_32c2.json +++ b/tools/python/esptool/targets/stub_flasher/stub_flasher_32c2.json @@ -1,7 +1,8 @@ { "entry": 1077413304, - "text": "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", + "text": "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", "text_start": 1077411840, - "data": "DEDKP+AIOEAsCThAhAk4QCgKOECUCjhAQgo4QKgHOEDkCThAJAo4QJgJOEBYBzhAzAk4QFgHOEC6CDhA/gg4QCwJOECECThAzAg4QBIIOEBCCDhAyAg4QOwMOEAsCThArAs4QKAMOECkBjhAygw4QKQGOECkBjhApAY4QKQGOECkBjhApAY4QKQGOECkBjhASAs4QKQGOEDICzhAoAw4QA==", - "data_start": 1070295976 + "data": "DEDKP+AIOEAsCThAhAk4QFIKOEC+CjhAbAo4QKgHOEAOCjhATgo4QJgJOEBYBzhAzAk4QFgHOEC6CDhA/gg4QCwJOECECThAzAg4QBIIOEBCCDhAyAg4QBYNOEAsCThA1gs4QMoMOECkBjhA9Aw4QKQGOECkBjhApAY4QKQGOECkBjhApAY4QKQGOECkBjhAcgs4QKQGOEDyCzhAygw4QA==", + "data_start": 1070295976, + "bss_start": 1070219264 } \ No newline at end of file diff --git a/tools/python/esptool/targets/stub_flasher/stub_flasher_32c3.json b/tools/python/esptool/targets/stub_flasher/stub_flasher_32c3.json index 2ecf24c2..439e043d 100644 --- a/tools/python/esptool/targets/stub_flasher/stub_flasher_32c3.json +++ b/tools/python/esptool/targets/stub_flasher/stub_flasher_32c3.json @@ -1,7 +1,8 @@ { "entry": 1077413532, - "text": "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", + "text": "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", "text_start": 1077411840, - "data": "FEDIP3YKOEDGCjhAHgs4QMILOEAuDDhA3As4QEIJOEB+CzhAvgs4QDILOEDyCDhAZgs4QPIIOEBQCjhAlgo4QMYKOEAeCzhAYgo4QKYJOEDWCThAXgo4QIYOOEDGCjhARg04QD4OOEAyCDhAZg44QDIIOEAyCDhAMgg4QDIIOEAyCDhAMgg4QDIIOEAyCDhA4gw4QDIIOEBkDThAPg44QA==", - "data_start": 1070164912 + "data": "FEDIP4wKOEDcCjhANAs4QAIMOEBuDDhAHAw4QD4JOEC+CzhA/gs4QEgLOEDuCDhAfAs4QO4IOEBmCjhArAo4QNwKOEA0CzhAeAo4QKIJOEDsCThAdAo4QMYOOEDcCjhAhg04QH4OOEAuCDhApg44QC4IOEAuCDhALgg4QC4IOEAuCDhALgg4QC4IOEAuCDhAIg04QC4IOECkDThAfg44QA==", + "data_start": 1070164912, + "bss_start": 1070088192 } \ No newline at end of file diff --git a/tools/python/esptool/targets/stub_flasher/stub_flasher_32c6.json b/tools/python/esptool/targets/stub_flasher/stub_flasher_32c6.json index 945df154..760a9731 100644 --- a/tools/python/esptool/targets/stub_flasher/stub_flasher_32c6.json +++ b/tools/python/esptool/targets/stub_flasher/stub_flasher_32c6.json @@ -1,7 +1,8 @@ { "entry": 1082132112, - "text": "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", + "text": "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", "text_start": 1082130432, - "data": "EACEQEIKgECSCoBA6gqAQI4LgED6C4BAqAuAQA4JgEBKC4BAiguAQP4KgEC+CIBAMguAQL4IgEAcCoBAYgqAQJIKgEDqCoBALgqAQHIJgECiCYBAKgqAQFIOgECSCoBAEg2AQAoOgED+B4BAMg6AQP4HgED+B4BA/geAQP4HgED+B4BA/geAQP4HgED+B4BArgyAQP4HgEAwDYBACg6AQA==", - "data_start": 1082469292 + "data": "EACEQD4KgECOCoBA5gqAQLQLgEAgDIBAzguAQAoJgEBwC4BAsAuAQPoKgEC6CIBALguAQLoIgEAYCoBAXgqAQI4KgEDmCoBAKgqAQG4JgECeCYBAJgqAQHgOgECOCoBAOA2AQDAOgED6B4BAWA6AQPoHgED6B4BA+geAQPoHgED6B4BA+geAQPoHgED6B4BA1AyAQPoHgEBWDYBAMA6AQA==", + "data_start": 1082469292, + "bss_start": 1082392576 } \ No newline at end of file diff --git a/tools/python/esptool/targets/stub_flasher/stub_flasher_32c6beta.json b/tools/python/esptool/targets/stub_flasher/stub_flasher_32c6beta.json index 94fd3da0..7fd5c0ec 100644 --- a/tools/python/esptool/targets/stub_flasher/stub_flasher_32c6beta.json +++ b/tools/python/esptool/targets/stub_flasher/stub_flasher_32c6beta.json @@ -1,7 +1,8 @@ { "entry": 1077413318, - "text": "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", + "text": "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", "text_start": 1077411840, - "data": "DEDIP/gIOEBECThAnAk4QEAKOECsCjhAWgo4QMAHOED8CThAPAo4QLAJOEBwBzhA5Ak4QHAHOEDSCDhAFgk4QEQJOECcCThA5Ag4QCoIOEBaCDhA4Ag4QAQNOEBECThAxAs4QLgMOEC8BjhA4gw4QLwGOEC8BjhAvAY4QLwGOEC8BjhAvAY4QLwGOEC8BjhAYAs4QLwGOEDgCzhAuAw4QA==", - "data_start": 1070164904 + "data": "DEDIP/gIOEBECThAnAk4QGoKOEDWCjhAhAo4QMAHOEAmCjhAZgo4QLAJOEBwBzhA5Ak4QHAHOEDSCDhAFgk4QEQJOECcCThA5Ag4QCoIOEBaCDhA4Ag4QC4NOEBECThA7gs4QOIMOEC8BjhADA04QLwGOEC8BjhAvAY4QLwGOEC8BjhAvAY4QLwGOEC8BjhAigs4QLwGOEAKDDhA4gw4QA==", + "data_start": 1070164904, + "bss_start": 1070088192 } \ No newline at end of file diff --git a/tools/python/esptool/targets/stub_flasher/stub_flasher_32h2.json b/tools/python/esptool/targets/stub_flasher/stub_flasher_32h2.json index a69f2e08..c7b56ebd 100644 --- a/tools/python/esptool/targets/stub_flasher/stub_flasher_32h2.json +++ b/tools/python/esptool/targets/stub_flasher/stub_flasher_32h2.json @@ -1,7 +1,8 @@ { "entry": 1082132112, - "text": "QREixCbCBsa39wBgEUc3BINA2Mu39ABgEwQEANxAkYuR57JAIkSSREEBgoCIQBxAE3X1D4KX3bcBEbcHAGBOxoOphwBKyDcJg0AmylLEBs4izLcEAGB9WhMJCQDATBN09A8N4PJAYkQjqDQBQknSRLJJIkoFYYKAiECDJwkAE3X1D4KXfRTjGUT/yb8TBwAMlEGqh2MY5QCFR4XGI6AFAHlVgoAFR2OH5gAJRmONxgB9VYKAQgUTB7ANQYVjlecCiUecwfW3kwbADWMW1QCYwRMFAAyCgJMG0A19VWOV1wCYwRMFsA2CgLc1hEBBEZOFRboGxmE/Y0UFBrc3hECTh8exA6cHCAPWRwgTdfUPkwYWAMIGwYIjktcIMpcjAKcAA9dHCJFnk4cHBGMe9wI3t4NAEwfHsaFnupcDpgcIt/aDQLc3hECTh8exk4bGtWMf5gAjpscII6DXCCOSBwghoPlX4wb1/LJAQQGCgCOm1wgjoOcI3bc3NwBgfEudi/X/NycAYHxLnYv1/4KAQREGxt03tzcAYCOmBwI3BwAImMOYQ33/yFeyQBNF9f8FiUEBgoBBEQbG2T993TcHAEC3NwBgmMM3NwBgHEP9/7JAQQGCgEERIsQ3hINAkwcEAUrAA6kHAQbGJsJjCgkERTc5xb1HEwQEAYFEY9YnAQREvYiTtBQAfTeFPxxENwaAABOXxwCZ4DcGAAG39v8AdY+3NgBg2MKQwphCff9BR5HgBUczCelAupcjKCQBHMSyQCJEkkQCSUEBgoABEQbOIswlNzcEhUBsABMFBP+XAID/54Ag8qqHBUWV57JHk/cHID7GiTc3NwBgHEe3BkAAEwUE/9WPHMeyRZcAgP/ngKDvMzWgAPJAYkQFYYKAQRG3h4NABsaThwcBBUcjgOcAE9fFAJjHBWd9F8zDyMf5jTqVqpWxgYzLI6oHAEE3GcETBVAMskBBAYKAAREizDeEg0CTBwQBJsrER07GBs5KyKqJEwQEAWPzlQCuhKnAAylEACaZE1nJABxIY1XwABxEY175ArU9fd1IQCaGzoWXAID/54Cg4hN19Q8BxZMHQAxcyFxAppdcwFxEhY9cxPJAYkTSREJJskkFYYKAaTVtv0ERBsaXAID/54BA1gNFhQGyQHUVEzUVAEEBgoBBEQbGxTcNxbcHg0CThwcA1EOZzjdnCWATB8cQHEM3Bv3/fRbxjzcGAwDxjtWPHMOyQEEBgoBBEQbGbTcRwQ1FskBBARcDgP9nAIPMQREGxpcAgP/ngEDKcTcBxbJAQQHZv7JAQQGCgEERBsYTBwAMYxrlABMFsA3RPxMFwA2yQEEB6bcTB7AN4xvl/sE3EwXQDfW3QREixCbCBsYqhLMEtQBjF5QAskAiRJJEQQGCgANFBAAFBE0/7bc1cSbLTsf9coVp/XQizUrJUsVWwwbPk4SE+haRk4cJB6aXGAizhOcAKokmhS6ElwCA/+eAgCyThwkHGAgFarqXs4pHQTHkBWd9dZMFhfqTBwcHEwWF+RQIqpczhdcAkwcHB66Xs4XXACrGlwCA/+eAQCkyRcFFlTcBRYViFpH6QGpE2kRKSbpJKkqaSg1hgoCiiWNzigCFaU6G1oVKhZcAgP/ngIDIE3X1DwHtTobWhSaFlwCA/+eAgCROmTMENEFRtxMFMAZVvxMFAAzZtTFx/XIFZ07XUtVW017PBt8i3SbbStla0WLNZstqyW7H/XcWkRMHBwc+lxwIupc+xiOqB/iqiS6Ksoq2iwU1kwcAAhnBtwcCAD6FlwCA/+eAIB2FZ2PlVxMFZH15EwmJ+pMHBAfKlxgIM4nnAEqFlwCA/+eAoBt9exMMO/mTDIv5EwcEB5MHBAcUCGKX5peBRDMM1wCzjNcAUk1jfE0JY/GkA0GomT+ihQgBjTW5NyKGDAFKhZcAgP/ngIAXopmilGP1RAOzh6RBY/F3AzMEmkBj84oAVoQihgwBToWXAID/54DAtxN19Q9V3QLMAUR5XY1NowkBAGKFlwCA/+eAgKd9+QNFMQHmhVE8Y08FAOPijf6FZ5OHBweilxgIupfalyOKp/gFBPG34xWl/ZFH4wX09gVnfXWTBwcHkwWF+hMFhfkUCKqXM4XXAJMHBweul7OF1wAqxpcAgP/ngKANcT0yRcFFZTNRPdU5twcCABnhkwcAAj6FlwCA/+eAoAqFYhaR+lBqVNpUSlm6WSpamloKW/pLakzaTEpNuk0pYYKAt1dBSRlxk4f3hAFFht6i3KbaytjO1tLU1tLa0N7O4szmyurI7sY+zpcAgP/ngMCgcTENwTdnCWATB8cQHEO3BoNAI6L2ALcG/f/9FvWPwWbVjxzDpTEFzbcnC2A3R9hQk4bHwRMHF6qYwhOGB8AjIAYAI6AGAJOGR8KYwpOHB8KYQzcGBABRj5jDI6AGALcHg0A3N4RAk4cHABMHx7ohoCOgBwCRB+Pt5/5FO5FFaAh1OWUzt7eDQJOHx7EhZz6XIyD3CLcHgEA3CYNAk4eHDiMg+QC3OYRA1TYTCQkAk4nJsWMHBRC3BwFgRUcjqucIhUVFRZcAgP/ngAD2twWAQAFGk4UFAEVFlwCA/+eAAPc39wBgHEs3BQIAk+dHABzLlwCA/+eAAPa3FwlgiF+BRbeEg0BxiWEVEzUVAJcAgP/ngICgwWf9FxMHABCFZkFmtwUAAQFFk4QEAbcKg0ANapcAgP/ngICWE4sKASaag6fJCPXfg6vJCIVHI6YJCCMC8QKDxxsACUcjE+ECowLxAgLUTUdjgecIUUdjj+cGKUdjn+cAg8c7AAPHKwCiB9mPEUdjlucAg6eLAJxDPtRxOaFFSBBlNoPHOwADxysAogfZjxFnQQdjdPcEEwWwDZk2EwXADYE2EwXgDi0+vTFBt7cFgEABRpOFhQMVRZcAgP/ngMDnNwcAYFxHEwUAApPnFxBcxzG3yUcjE/ECTbcDxxsA0UZj5+YChUZj5uYAAUwTBPAPhah5FxN39w/JRuPo5v63NoRACgeThga7NpcYQwKHkwYHA5P29g8RRuNp1vwTB/cCE3f3D41GY+vmCLc2hEAKB5OGxr82lxhDAocTB0ACY5jnEALUHUQBRWE8AUVFPOE22TahRUgQfRTBPHX0AUwBRBN19A9hPBN1/A9JPG024x4E6oPHGwBJR2Nj9y4JR+N29+r1F5P39w89R+Ng9+o3N4RAigcTB8fAupecQ4KHBUSd63AQgUUBRZfwf//ngAB0HeHRRWgQjTwBRDGoBUSB75fwf//ngIB4MzSgACmgIUdjhecABUQBTGG3A6yLAAOkywCzZ4wA0gf19+/wv4h98cFsIpz9HH19MwWMQFXcs3eVAZXjwWwzBYxAY+aMAv18MwWMQFXQMYGX8H//54AAdVX5ZpT1tzGBl/B//+eAAHRV8WqU0bdBgZfwf//ngEBzUfkzBJRBwbchR+OJ5/ABTBMEAAwxt0FHzb9BRwVE45zn9oOlywADpYsA1TKxv0FHBUTjkuf2A6cLAZFnY+XnHIOlSwEDpYsA7/D/gzW/QUcFROOS5/SDpwsBEWdjZfcaA6fLAIOlSwEDpYsAM4TnAu/wf4EjrAQAIySKsDG3A8cEAGMOBxADp4sAwRcTBAAMYxP3AMBIAUeTBvAOY0b3AoPHWwADx0sAAUyiB9mPA8drAEIHXY+Dx3sA4gfZj+OB9uYTBBAMqb0zhusAA0aGAQUHsY7ht4PHBADxw9xEY5gHEsBII4AEAH21YUdjlucCg6fLAQOniwGDpksBA6YLAYOlywADpYsAl/B//+eAwGMqjDM0oAAptQFMBUQRtRFHBUTjmufmA6WLAIFFl/B//+eAQGmRtRP39wDjGgfsk9xHABOEiwABTH1d43mc3UhEl/B//+eAwE0YRFRAEED5jmMHpwEcQhNH9/99j9mOFMIFDEEE2b8RR0m9QUcFROOc5+CDp4sAA6dLASMm+QAjJOkA3bODJYkAwReR5YnPAUwTBGAMtbsDJ8kAY2b3BhP3NwDjHgfkAyjJAAFGAUczBehAs4blAGNp9wDjCQbUIyapACMk2QCZszOG6wAQThEHkMIFRum/IUcFROOW59oDJMkAGcATBIAMIyYJACMkCQAzNIAASbsBTBMEIAwRuwFMEwSADDGzAUwTBJAMEbMTByANY4PnDBMHQA3jkOe8A8Q7AIPHKwAiBF2Ml/B//+eAYEwDrMQAQRRjc4QBIozjDgy4wEBilDGAnEhjVfAAnERjW/QK7/BP0XXdyEBihpOFiwGX8H//54BgSAHFkwdADNzI3EDil9zA3ESzh4dB3MSX8H//54BAR4m+CWUTBQVxA6zLAAOkiwCX8H//54BAOLcHAGDYS7cGAAHBFpNXRwESB3WPvYvZj7OHhwMBRbPVhwKX8H//54BgORMFgD6X8H//54DgNBG2g6ZLAQOmCwGDpcsAA6WLAO/wT/79tIPFOwCDxysAE4WLAaIF3Y3BFe/wL9vZvO/wj8o9vwPEOwCDxysAE4yLASIEXYzcREEUzeORR4VLY/+HCJMHkAzcyG20A6cNACLQBUizh+xAPtaDJ4qwY3P0AA1IQsY6xO/wD8YiRzJIN4WDQOKFfBCThgoBEBATBYUCl/B//+eAwDY3t4NAkwgHAYJXA6eIsIOlDQAdjB2PPpyyVyOk6LCqi76VI6C9AJOHCgGdjQHFoWdjl/UAWoXv8M/QI6BtAQnE3ESZw+NPcPdj3wsAkwdwDL23hUu3PYRAt4yDQJONzbqTjAwB6b/jkgug3ETjjweekweADKm3g6eLAOOYB57v8M/YCWUTBQVxl/B//+eAQCLv8E/Ul/B//+eAgCb5sgOkywDjBASc7/BP1hMFgD6X8H//54DgH+/w79EClH2y7/Bv0fZQZlTWVEZZtlkmWpZaBlv2S2ZM1kxGTbZNCWGCgA==", + "text": "QREixCbCBsa39wBgEUc3BINA2Mu39ABgEwQEANxAkYuR57JAIkSSREEBgoCIQBxAE3X1D4KX3bcBEbcHAGBOxoOphwBKyDcJg0AmylLEBs4izLcEAGB9WhMJCQDATBN09A8N4PJAYkQjqDQBQknSRLJJIkoFYYKAiECDJwkAE3X1D4KXfRTjGUT/yb8TBwAMlEGqh2MY5QCFR4XGI6AFAHlVgoAFR2OH5gAJRmONxgB9VYKAQgUTB7ANQYVjlecCiUecwfW3kwbADWMW1QCYwRMFAAyCgJMG0A19VWOV1wCYwRMFsA2CgLc1hEBBEZOFRboGxmE/Y0UFBrc3hECTh8exA6cHCAPWRwgTdfUPkwYWAMIGwYIjktcIMpcjAKcAA9dHCJFnk4cHBGMe9wI3t4NAEwfHsaFnupcDpgcIt/aDQLc3hECTh8exk4bGtWMf5gAjpscII6DXCCOSBwghoPlX4wb1/LJAQQGCgCOm1wgjoOcI3bc3NwBgfEudi/X/NycAYHxLnYv1/4KAQREGxt03tzcAYCOmBwI3BwAImMOYQ33/yFeyQBNF9f8FiUEBgoBBEQbG2T993TcHAEC3NwBgmMM3NwBgHEP9/7JAQQGCgEERIsQ3hINAkwcEAUrAA6kHAQbGJsJjCgkERTc5xb1HEwQEAYFEY9YnAQREvYiTtBQAfTeFPxxENwaAABOXxwCZ4DcGAAG39v8AdY+3NgBg2MKQwphCff9BR5HgBUczCelAupcjKCQBHMSyQCJEkkQCSUEBgoABEQbOIswlNzcEhUBsABMFBP+XAID/54Ag8qqHBUWV57JHk/cHID7GiTc3NwBgHEe3BkAAEwUE/9WPHMeyRZcAgP/ngKDvMzWgAPJAYkQFYYKAQRG3h4NABsaThwcBBUcjgOcAE9fFAJjHBWd9F8zDyMf5jTqVqpWxgYzLI6oHAEE3GcETBVAMskBBAYKAAREizDeEg0CTBwQBJsrER07GBs5KyKqJEwQEAWPzlQCuhKnAAylEACaZE1nJABxIY1XwABxEY175ArU9fd1IQCaGzoWXAID/54Cg4hN19Q8BxZMHQAxcyFxAppdcwFxEhY9cxPJAYkTSREJJskkFYYKAaTVtv0ERBsaXAID/54BA1gNFhQGyQHUVEzUVAEEBgoBBEQbGxTcNxbcHg0CThwcA1EOZzjdnCWATB8cQHEM3Bv3/fRbxjzcGAwDxjtWPHMOyQEEBgoBBEQbGbTcRwQ1FskBBARcDgP9nAIPMQREGxpcAgP/ngEDKcTcBxbJAQQHZv7JAQQGCgEERBsYTBwAMYxrlABMFsA3RPxMFwA2yQEEB6bcTB7AN4xvl/sE3EwXQDfW3QREixCbCBsYqhLMEtQBjF5QAskAiRJJEQQGCgANFBAAFBE0/7bc1cSbLTsf9coVp/XQizUrJUsVWwwbPk4SE+haRk4cJB6aXGAizhOcAKokmhS6ElwCA/+eAgCyThwkHGAgFarqXs4pHQTHkBWd9dZMFhfqTBwcHEwWF+RQIqpczhdcAkwcHB66Xs4XXACrGlwCA/+eAQCkyRcFFlTcBRYViFpH6QGpE2kRKSbpJKkqaSg1hgoCiiWNzigCFaU6G1oVKhZcAgP/ngIDIE3X1DwHtTobWhSaFlwCA/+eAgCROmTMENEFRtxMFMAZVvxMFAAzZtTFx/XIFZ07XUtVW017PBt8i3SbbStla0WLNZstqyW7H/XcWkRMHBwc+lxwIupc+xiOqB/iqiS6Ksoq2iwU1kwcAAhnBtwcCAD6FlwCA/+eAIB2FZ2PlVxMFZH15EwmJ+pMHBAfKlxgIM4nnAEqFlwCA/+eAoBt9exMMO/mTDIv5EwcEB5MHBAcUCGKX5peBRDMM1wCzjNcAUk1jfE0JY/GkA0GomT+ihQgBjTW5NyKGDAFKhZcAgP/ngIAXopmilGP1RAOzh6RBY/F3AzMEmkBj84oAVoQihgwBToWXAID/54DAtxN19Q9V3QLMAUR5XY1NowkBAGKFlwCA/+eAgKd9+QNFMQHmhVE8Y08FAOPijf6FZ5OHBweilxgIupfalyOKp/gFBPG34xWl/ZFH4wX09gVnfXWTBwcHkwWF+hMFhfkUCKqXM4XXAJMHBweul7OF1wAqxpcAgP/ngKANcT0yRcFFZTNRPdU5twcCABnhkwcAAj6FlwCA/+eAoAqFYhaR+lBqVNpUSlm6WSpamloKW/pLakzaTEpNuk0pYYKAt1dBSRlxk4f3hAFFht6i3KbaytjO1tLU1tLa0N7O4szmyurI7sY+zpcAgP/ngMCgcTENwTdnCWATB8cQHEO3BoNAI6L2ALcG/f/9FvWPwWbVjxzDpTEFzbcnC2A3R9hQk4bHwRMHF6qYwhOGB8AjIAYAI6AGAJOGR8KYwpOHB8KYQzcGBABRj5jDI6AGALcHg0A3N4RAk4cHABMHx7ohoCOgBwCRB+Pt5/5FO5FFaAh1OWUzt7eDQJOHx7EhZz6XIyD3CLcHgEA3CYNAk4eHDiMg+QC3OYRA1TYTCQkAk4nJsWMFBRC3BwFgRUcjqucIhUVFRZcAgP/ngAD2twWAQAFGk4UFAEVFlwCA/+eAAPe39wBgEUeYyzcFAgCXAID/54BA9rcXCWCIX4FFt4SDQHGJYRUTNRUAlwCA/+eAwKDBZ/0XEwcAEIVmQWa3BQABAUWThAQBtwqDQA1qlwCA/+eAwJYTiwoBJpqDp8kI9d+Dq8kIhUcjpgkIIwLxAoPHGwAJRyMT4QKjAvECAtRNR2OB5whRR2OP5wYpR2Of5wCDxzsAA8crAKIH2Y8RR2OW5wCDp4sAnEM+1EUxoUVIEHU2g8c7AAPHKwCiB9mPEWdBB2N09wQTBbANqTYTBcANkTYTBeAOPT6NOUG3twWAQAFGk4WFAxVFlwCA/+eAAOg3BwBgXEcTBQACk+cXEFzHMbfJRyMT8QJNtwPHGwDRRmPn5gKFRmPm5gABTBME8A+FqHkXE3f3D8lG4+jm/rc2hEAKB5OGBrs2lxhDAoeTBgcDk/b2DxFG42nW/BMH9wITd/cPjUZj6+YItzaEQAoHk4bGvzaXGEMChxMHQAJjmOcQAtQdRAFFcTwBRVU88TbpNqFFSBB9FNE8dfQBTAFEE3X0D3E8E3X8D1k8fTbjHgTqg8cbAElHY2j3MAlH43b36vUXk/f3Dz1H42D36jc3hECKBxMHx8C6l5xDgocFRJ3rcBCBRQFFl/B//+eAQHQd4dFFaBCdPAFEMagFRIHvl/B//+eAwHgzNKAAKaAhR2OF5wAFRAFMYbcDrIsAA6TLALNnjADSB/X37/D/iH3xwWwinP0cfX0zBYxAVdyzd5UBlePBbDMFjEBj5owC/XwzBYxAVdAxgZfwf//ngEB1VflmlPW3MYGX8H//54BAdFXxapTRt0GBl/B//+eAgHNR+TMElEHBtyFH44nn8AFMEwQADDG3QUfNv0FHBUTjnOf2g6XLAAOliwDlMrG/QUcFROOS5/YDpwsBkWdj6uceg6VLAQOliwDv8D+ENb9BRwVE45Ln9IOnCwERZ2Nq9xwDp8sAg6VLAQOliwAzhOcC7/C/gSOsBAAjJIqwMbcDxwQAYwMHFAOniwDBFxMEAAxjE/cAwEgBR5MG8A5jRvcCg8dbAAPHSwABTKIH2Y8Dx2sAQgddj4PHewDiB9mP44H25hMEEAypvTOG6wADRoYBBQexjuG3g8cEAP3H3ERjnQcUwEgjgAQAfbVhR2OW5wKDp8sBA6eLAYOmSwEDpgsBg6XLAAOliwCX8H//54AAZCqMMzSgACm1AUwFRBG1EUcFROOa5+a3lwBgtEtld30XBWb5jtGOA6WLALTL9EOBRfmO0Y70w/RL+Y7RjvTLtEN1j1GPuMOX8H//54DgZim9E/f3AOMVB+qT3EcAE4SLAAFMfV3jdJzbSESX8H//54BgSxhEVEAQQPmOYwenARxCE0f3/32P2Y4UwgUMQQTZvxFHpbVBRwVE45fn3oOniwADp0sBIyb5ACMk6QB1u4MliQDBF5Hlic8BTBMEYAyJuwMnyQBjZvcGE/c3AOMZB+IDKMkAAUYBRzMF6ECzhuUAY2n3AOMEBtIjJqkAIyTZADG7M4brABBOEQeQwgVG6b8hRwVE45Hn2AMkyQAZwBMEgAwjJgkAIyQJADM0gAClswFMEwQgDO2xAUwTBIAMzbEBTBMEkAzpuRMHIA1jg+cMEwdADeOb57gDxDsAg8crACIEXYyX8H//54AASgOsxABBFGNzhAEijOMJDLbAQGKUMYCcSGNV8ACcRGNb9Arv8O/Odd3IQGKGk4WLAZfwf//ngABGAcWTB0AM3MjcQOKX3MDcRLOHh0HcxJfwf//ngOBEJbYJZRMFBXEDrMsAA6SLAJfwf//ngOA1twcAYNhLtwYAAcEWk1dHARIHdY+9i9mPs4eHAwFFs9WHApfwf//ngAA3EwWAPpfwf//ngIAy6byDpksBA6YLAYOlywADpYsA7/Dv+9G0g8U7AIPHKwAThYsBogXdjcEV7/DP2HW07/AvyD2/A8Q7AIPHKwATjIsBIgRdjNxEQRTN45FHhUtj/4cIkweQDNzIQbQDpw0AItAFSLOH7EA+1oMnirBjc/QADUhCxjrE7/CvwyJHMkg3hYNA4oV8EJOGCgEQEBMFhQKX8H//54BgNDe3g0CTCAcBglcDp4iwg6UNAB2MHY8+nLJXI6TosKqLvpUjoL0Ak4cKAZ2NAcWhZ2OX9QBahe/wb84joG0BCcTcRJnD409w92PfCwCTB3AMvbeFS7c9hEC3jINAk43NupOMDAHpv+OdC5zcROOKB5yTB4AMqbeDp4sA45MHnO/wb9YJZRMFBXGX8H//54DgH+/w79GX8H//54AgJFWyA6TLAOMPBJjv8O/TEwWAPpfwf//ngIAd7/CPzwKUUbLv8A/P9lBmVNZURlm2WSZalloGW/ZLZkzWTEZNtk0JYYKAAAA=", "text_start": 1082130432, - "data": "EACDQEIKgECSCoBA6gqAQI4LgED6C4BAqAuAQA4JgEBKC4BAiguAQP4KgEC+CIBAMguAQL4IgEAcCoBAYgqAQJIKgEDqCoBALgqAQHIJgECiCYBAKgqAQFIOgECSCoBAEg2AQAoOgED+B4BAMg6AQP4HgED+B4BA/geAQP4HgED+B4BA/geAQP4HgED+B4BArgyAQP4HgEAwDYBACg6AQA==", - "data_start": 1082403756 + "data": "EACDQD4KgECOCoBA5gqAQLQLgEAgDIBAzguAQAoJgEBwC4BAsAuAQPoKgEC6CIBALguAQLoIgEAYCoBAXgqAQI4KgEDmCoBAKgqAQG4JgECeCYBAJgqAQHgOgECOCoBAOA2AQDAOgED6B4BAWA6AQPoHgED6B4BA+geAQPoHgED6B4BA+geAQPoHgED6B4BA1AyAQPoHgEBWDYBAMA6AQA==", + "data_start": 1082403756, + "bss_start": 1082327040 } \ No newline at end of file diff --git a/tools/python/esptool/targets/stub_flasher/stub_flasher_32h2beta1.json b/tools/python/esptool/targets/stub_flasher/stub_flasher_32h2beta1.json index 6d4ec72b..03e110c5 100644 --- a/tools/python/esptool/targets/stub_flasher/stub_flasher_32h2beta1.json +++ b/tools/python/esptool/targets/stub_flasher/stub_flasher_32h2beta1.json @@ -1,7 +1,8 @@ { "entry": 1077413318, - "text": "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", + "text": "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", "text_start": 1077411840, - "data": "DEDIP/gIOEBECThAnAk4QEAKOECsCjhAWgo4QMAHOED8CThAPAo4QLAJOEBwBzhA5Ak4QHAHOEDSCDhAFgk4QEQJOECcCThA5Ag4QCoIOEBaCDhA4Ag4QAQNOEBECThAxAs4QLgMOEC8BjhA4gw4QLwGOEC8BjhAvAY4QLwGOEC8BjhAvAY4QLwGOEC8BjhAYAs4QLwGOEDgCzhAuAw4QA==", - "data_start": 1070164904 + "data": "DEDIP/gIOEBECThAnAk4QGoKOEDWCjhAhAo4QMAHOEAmCjhAZgo4QLAJOEBwBzhA5Ak4QHAHOEDSCDhAFgk4QEQJOECcCThA5Ag4QCoIOEBaCDhA4Ag4QC4NOEBECThA7gs4QOIMOEC8BjhADA04QLwGOEC8BjhAvAY4QLwGOEC8BjhAvAY4QLwGOEC8BjhAigs4QLwGOEAKDDhA4gw4QA==", + "data_start": 1070164904, + "bss_start": 1070088192 } \ No newline at end of file diff --git a/tools/python/esptool/targets/stub_flasher/stub_flasher_32h2beta2.json b/tools/python/esptool/targets/stub_flasher/stub_flasher_32h2beta2.json index cd438aba..ce3afe7a 100644 --- a/tools/python/esptool/targets/stub_flasher/stub_flasher_32h2beta2.json +++ b/tools/python/esptool/targets/stub_flasher/stub_flasher_32h2beta2.json @@ -1,7 +1,8 @@ { "entry": 1077413318, - "text": "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", + "text": "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", "text_start": 1077411840, - "data": "DEDIP/gIOEBECThAnAk4QEAKOECsCjhAWgo4QMAHOED8CThAPAo4QLAJOEBwBzhA5Ak4QHAHOEDSCDhAFgk4QEQJOECcCThA5Ag4QCoIOEBaCDhA4Ag4QAQNOEBECThAxAs4QLgMOEC8BjhA4gw4QLwGOEC8BjhAvAY4QLwGOEC8BjhAvAY4QLwGOEC8BjhAYAs4QLwGOEDgCzhAuAw4QA==", - "data_start": 1070164904 + "data": "DEDIP/gIOEBECThAnAk4QGoKOEDWCjhAhAo4QMAHOEAmCjhAZgo4QLAJOEBwBzhA5Ak4QHAHOEDSCDhAFgk4QEQJOECcCThA5Ag4QCoIOEBaCDhA4Ag4QC4NOEBECThA7gs4QOIMOEC8BjhADA04QLwGOEC8BjhAvAY4QLwGOEC8BjhAvAY4QLwGOEC8BjhAigs4QLwGOEAKDDhA4gw4QA==", + "data_start": 1070164904, + "bss_start": 1070088192 } \ No newline at end of file diff --git a/tools/python/esptool/targets/stub_flasher/stub_flasher_32p4.json b/tools/python/esptool/targets/stub_flasher/stub_flasher_32p4.json new file mode 100644 index 00000000..274c6261 --- /dev/null +++ b/tools/python/esptool/targets/stub_flasher/stub_flasher_32p4.json @@ -0,0 +1,8 @@ +{ + "entry": 1341195718, + "text": "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", + "text_start": 1341194240, + "data": "DAD1T+4I8U86CfFPkgnxT2gK8U/UCvFPggrxT7YH8U8kCvFPZArxT6YJ8U9mB/FP2gnxT2YH8U/ICPFPDAnxTzoJ8U+SCfFP2gjxTyAI8U9QCPFP1gjxTywN8U86CfFP7AvxT+AM8U+yBvFPCg3xT7IG8U+yBvFPsgbxT7IG8U+yBvFPsgbxT7IG8U+yBvFPiAvxT7IG8U8IDPFP4AzxTw==", + "data_start": 1341533096, + "bss_start": 1341456384 +} \ No newline at end of file diff --git a/tools/python/esptool/targets/stub_flasher/stub_flasher_32s2.json b/tools/python/esptool/targets/stub_flasher/stub_flasher_32s2.json index cdb47ab4..68de6138 100644 --- a/tools/python/esptool/targets/stub_flasher/stub_flasher_32s2.json +++ b/tools/python/esptool/targets/stub_flasher/stub_flasher_32s2.json @@ -1,7 +1,8 @@ { - "entry": 1073907696, - "text": "CAAAYBwAAGBIAP0/EAAAYDZBACH7/8AgADgCQfr/wCAAKAQgIJSc4kH4/0YEAAw4MIgBwCAAqAiIBKCgdOAIAAsiZgLohvT/IfH/wCAAOQId8AAA7Cv+P2Sr/T+EgAAAQEAAAKTr/T/wK/4/NkEAsfn/IKB0EBEg5QEBlhoGgfb/kqEBkJkRmpjAIAC4CZHz/6CgdJqIwCAAkhgAkJD0G8nAwPTAIADCWACam8AgAKJJAMAgAJIYAIHq/5CQ9ICA9IeZR4Hl/5KhAZCZEZqYwCAAyAmh5f+x4/+HnBfGAQB86Ica3sYIAMAgAIkKwCAAuQlGAgDAIAC5CsAgAIkJkdf/mogMCcAgAJJYAB3wAABUIEA/VDBAPzZBAJH9/8AgAIgJgIAkVkj/kfr/wCAAiAmAgCRWSP8d8AAAACwgQD8AIEA/AAAACDZBABARIKX8/yH6/wwIwCAAgmIAkfr/gfj/wCAAkmgAwCAAmAhWef/AIACIAnzygCIwICAEHfAAAAAAQDZBABARIOX7/xZq/4Hs/5H7/8AgAJJoAMAgAJgIVnn/HfAAAFiA/T////8ABCBAPzZBACH8/zhCFoMGEBEgZfj/FvoFDPgMBDeoDZgigJkQgqABkEiDQEB0EBEgJfr/EBEgJfP/iCIMG0CYEZCrAcwUgKsBse3/sJkQsez/wCAAkmsAkc7/wCAAomkAwCAAqAlWev8cCQwaQJqDkDPAmog5QokiHfAAAHDi+j8IIEA/hGIBQKRiAUA2YQAQESBl7f8x+f+9Aa0Dgfr/4AgATQoMEuzqiAGSogCQiBCJARARIOXx/5Hy/6CiAcAgAIgJoIggwCAAiQm4Aa0Dge7/4AgAoCSDHfAAAP8PAAA2QQCBxf8MGZJIADCcQZkokfv/ORgpODAwtJoiKjMwPEEMAilYOUgQESAl+P8tCowaIqDFHfAAAMxxAUA2QQBBtv9YNFAzYxZjBFgUWlNQXEFGAQAQESDl7P+IRKYYBIgkh6XvEBEgJeX/Fmr/qBTNA70CgfH/4AgAoKB0jEpSoMRSZAVYFDpVWRRYNDBVwFk0HfAA+Pz/P0QA/T9MAP0/ADIBQOwxAUAwMwFANmEAfMitAoeTLTH3/8YFAKgDDBwQsSCB9//gCACBK/+iAQCICOAIAKgDgfP/4AgA5hrcxgoAAABmAyYMA80BDCsyYQCB7v/gCACYAYHo/zeZDagIZhoIMeb/wCAAokMAmQgd8EAA/T8AAP0/jDEBQDZBACH8/4Hc/8gCqAix+v+B+//gCAAMCIkCHfBgLwFANkEAgf7/4AgAggoYDAmCyP4MEoApkx3w+Cv+P/Qr/j8YAEw/jABMP//z//82QQAQESDl/P8WWgSh+P+ICrzYgff/mAi8abH2/3zMwCAAiAuQkBTAiBCQiCDAIACJC4gKsfH/DDpgqhHAIACYC6CIEKHu/6CZEJCIIMAgAIkLHfAoKwFANkEAEBEgZff/vBqR0f+ICRuoqQmR0P8MCoqZIkkAgsjBDBmAqYOggHTMiqKvQKoiIJiTjPkQESAl8v/GAQCtAoHv/+AIAB3wNkEAoqDAEBEg5fr/HfAAADZBAIKgwK0Ch5IRoqDbEBEgZfn/oqDcRgQAAAAAgqDbh5IIEBEgJfj/oqDdEBEgpff/HfA2QQA6MsYCAKICACLCARARIKX7/zeS8B3wAAAAbFIAQIxyAUCMUgBADFMAQDYhIaLREIH6/+AIAEYLAAAADBRARBFAQ2PNBL0BrQKB9f/gCACgoHT8Ws0EELEgotEQgfH/4AgASiJAM8BWA/0iogsQIrAgoiCy0RCB7P/gCACtAhwLEBEgpff/LQOGAAAioGMd8AAAQCsBQDZBABARICXl/4y6gYj/iAiMSBARICXi/wwKgfj/4AgAHfAAAIQyAUC08QBAkDIBQMDxAEA2QQAQESDl4f+smjFc/4ziqAOB9//gCACiogDGBgAAAKKiAIH0/+AIAKgDgfP/4AgARgUAAAAsCoyCgfD/4AgAhgEAAIHs/+AIAB3w8CsBQDZBIWKhB8BmERpmWQYMBWLREK0FUmYaEBEgZfn/DBhAiBFHuAJGRACtBoG1/+AIAIYzAACSpB1Qc8DgmREamUB3Y4kJzQe9ASCiIIGu/+AIAJKkHeCZERqZoKB0iAmMigwIgmYWfQiGFQCSpB3gmREamYkJEBEgpeL/vQetARARICXm/xARIKXh/80HELEgYKYggZ3/4AgAkqQd4JkRGpmICXAigHBVgDe1tJKhB8CZERqZmAmAdcCXtwJG3f+G5/8MCIJGbKKkGxCqoIHM/+AIAFYK/7KiC6IGbBC7sBARIOWbAPfqEvZHD7KiDRC7sHq7oksAG3eG8f9867eawWZHCIImGje4Aoe1nCKiCxAisGC2IK0CgX3/4AgAEBEgJdj/rQIcCxARIKXb/xARICXX/wwaEBEgpef/HfAAAP0/T0hBSfwr/j9sgAJASDwBQDyDAkAIAAhgEIACQAwAAGA4QEA///8AACiBQD+MgAAAEEAAAAAs/j8QLP4/UAD9P1QA/T9cLP4/FAAAYPD//wD8K/4/WAD9P3CA/T9c8gBAiNgAQNDxAECk8QBA1DIBQFgyAUCg5ABABHABQAB1AUCASQFA6DUBQOw7AUCAAAFAmCABQOxwAUBscQFADHEBQIQpAUB4dgFA4HcBQJR2AUAAMABAaAABQDbBACHR/wwKKaGB5v/gCAAQESClvP8W6gQx+P5B9/7AIAAoA1H3/ikEwCAAKAVh8f6ioGQpBmHz/mAiEGKkAGAiIMAgACkFgdj/4AgASAR8wkAiEAwkQCIgwCAAKQOGAQBJAksixgEAIbf/Mbj/DAQ3Mu0QESAlw/8MS6LBKBARIKXG/yKhARARIOXB/1H2/ZAiESolwCAAWQIxrf8h3v0yYgAQESBls/8WOgYhov7Bov6oAgwrgaT+4AgADJw8CwwKgbr/4AgAsaP/DAwMmoG4/+AIAKKiAIE3/+AIALGe/6gCQqABgbP/4AgAqAKBLv/gCACoAoGw/+AIADGY/8AgACgDQCIgwCAAKQMGCgAAsZT/zQoMWoGm/+AIADGR/0KhAcAgACgDLApAIiDAIAApA4Eg/+AIAIGh/+AIACGK/8AgACgCzLocwzAiECLC+AwTIKODDAuBmv/gCADxg/8MHQwcsqAB4qEAQN0RAMwRgLsBoqAAgZP/4AgAIX7/YQ7+KlVy1ivGFgAAAADAIAAyBAAwMHQW8wSiogDAIAAiRACBAv/gCACionHAqhGBfv/gCACBhf/gCABBbf986MAgADgEoq//gDMQEKoBwCAAOQSBfv/gCACBfv/gCACtAoF9/+AIAEFV/sAgACgFFrL5DATAIAA4BQwSwCAASQUiQRwiAwEMKEmBIkEdglEPHDRHEiMcREcSJGaSJiIDA0IDAoAiEUAiIGZCFygjwCAAKAIpgcYCAAAcIoYAAAAMwiJRDxARICWm/7KgCKLBHBARIKWp/0IDAyIDAoBEESBEICFF/yAg9EeyGqKgwBARIGWk/6Kg7hARIOWj/xARIKWi/wbY/yIDARxIJzg39iIbBuMAIsIvICB0tkICRiYAgTf/gCKgKAKgAgAAACLC/iAgdBwoJ7gCRtkAgTH/gCKgKAKgAgCCwjCAgHS2WMSG0wAsSQwIIqDAlxQChtEAiYEMck0IrQQQESDlnP+tBBARIGWc/xARICWb/xARIKWa/wyLosEcCyIQESAlnv9WMv2GLwAMElYUMMLBEL0ErQSBLv/gCABWGi+yoAyiwRAQESClm/8GmgAAAAwSVrQtgSf/4AgABisAJoQGDBKGsgAAAEgjKDMghCCAgLRWuP4QESClbv8qRJwahvf/AKCsQYEc/+AIAFYa/SLS8CCkwMwiBocAAKCA9FYY/oYEAKCg9YnBgRT/4AgAiMFWyvqAIsAMGACIESCkwCc44YYDAKCsQYEL/+AIAFb6+CLS8CCkwFai/kZ2AAAMCCKgwCaEAoaUAAwILQjGkgAmtPWGaAAMEia0AoaMALgzqCNCoAAQESBlkv+gJIPGhwAMGWa0XUhDIKkRDAgioMJHugJGhQC4U6gjkmEOEBEgZWj/mOEMAqCSg4YNAAwZZrQxSEMgqREMCCKgwke6AkZ6ACgzuFOoIyBEgpnhEBEgZWX/IVv9DAiY4YliItIrSSKgmIMtCcZtAJFV/QwIogkAIqDGh5oCRmwAiCNCxPAioMBHmAEoWQwIkqDvRgIAiqOiChgbiKCZMEco8kIDBYIDBIBEEYBEIIIDBgCIEUCIIEIDB4BEAYBEIECZwEKgwQwIkCSTxlgAQT39IqDGkgQAjQkWWRWYNAwIIqDIhxkCBlIAKFSSRABGTQAciQwIDBKXFAIGTQD4c+hj2FPIQ7gzqCMMBIGx/uAIAI0KoCSDBkYAAAAMEiZEAsZAAKgjDAuBqf7gCAAGHwBAoDQMCCKgwIcaAsY8AEC0QYuTTQp8/AYOAACoOZnhucHJ0YGY/uAIAJjhuMEoKYgZqAnI0YCCECYCDcAgANgKICww0CIQIIggwCAAiQobRJLJELc0xEaV/2ZEAsaT/wwIIqDAhiYADBImtALGIQAhfP6IU0gjiQIhe/5JAgwCBh0AsXf+DAjYCwwaQsTwnQgtCNAqg0CakyCZECKgxoeZYMFx/o0J6AwioMlHPlNA8BQioMBWrwQtCYYCAAAqk5hpSyKZCJ0KIP7AKo1HMu0Wyd35DIkLRnX/AAwSZoQXIWH+iAKMGIKgyAwESQIhXf5JAgwSgCSDDAhGAQAADAgioP8goHSCYQwQESClaP+IwYCgdBARIOVn/xARIKVm/1YCuiIDARwkJzQe9jIChuT+IsL9ICB0DPQntAIG4f5BSv5AIqAoAqACAEKg0kcSX0Kg1EeSAgYhAMbZ/gAASDM4IxARIGVV/40KVmq1oqJxwKoRicGBRP7gCAAhPP6RPf7AIAAoAojBILQ1wCIRkCIQILsgQLuCrQgwu8KBSv7gCACio+iBOP7gCABGxf4AANhTyEO4M6gjEBEgpXL/hsD+sgMDIgMCgLsRILsgssvwosMYEBEgJT7/xrn+AAAiAwNCAwKAIhFAIiCBOP7gCABBqfwiwvCINIAiYxZSrIgUioKAjEGGAgCJwRARIGUp/4IhDJIkBKYZBJgkl6jpEBEgZSH/Fmr/qBTNArLDGIEo/uAIAIw6MqDEOVQ4FCozORQ4NCAjwCk0gSL+4AgAhpz+AAAiAwOCAwJCwxiAIhE4NoAiICLC8FbDCfZSAoYlACKgyUYqADEA/oGH/OgDKZHgiMCJQYgnrQmHsgEMOpnhqdHpwRARIKUg/6jRgff96MGpAaH2/d0IvQTCwSTywRCJwYEJ/uAIALgnzQqokZjhoLvAuSegIsC4A6pEqEGIwaq7DAq5A8Cpg4C7wKDQdMya4tuArQ3gqYMW6gGtCInBmeHJ0RARICUs/4jBmOHI0YkDRgEAAAAMHJ0MjLI4NoxzwD8xwDPAlrP11owAIqDHKVaGZ/4AVqyZKDYWUpkioMjG+v8oI1aimBARIGVS/6KiccCqEYHQ/eAIABARIGU5/4Hi/eAIAEZa/gAoMxYylhARIOVP/6Kj6IHH/eAIABARICU3/+ACAAZS/gAQESBlNv8d8AAANkEAnQKCoMAoA4eZD8wyDBKGBwAMAikDfOKGDwAmEgcmIhiGAwAAAIKg24ApI4eZKgwiKQN88kYIAAAAIqDcJ5kKDBIpAy0IBgQAAACCoN188oeZBgwSKQMioNsd8AAA", + "entry": 1073907716, + "text": "CAAAYBwAAGBIAP0/EAAAYDZBACH7/8AgADgCQfr/wCAAKAQgIJSc4kH4/0YEAAw4MIgBwCAAqAiIBKCgdOAIAAsiZgLohvT/IfH/wCAAOQId8AAA7Cv+P2Sr/T+EgAAAQEAAAKTr/T/wK/4/NkEAsfn/IKB0EBEgJQgBlhoGgfb/kqEBkJkRmpjAIAC4CZHz/6CgdJqIwCAAkhgAkJD0G8nAwPTAIADCWACam8AgAKJJAMAgAJIYAIHq/5CQ9ICA9IeZR4Hl/5KhAZCZEZqYwCAAyAmh5f+x4/+HnBfGAQB86Ica3sYIAMAgAIkKwCAAuQlGAgDAIAC5CsAgAIkJkdf/mogMCcAgAJJYAB3wAABUIEA/VDBAPzZBAJH9/8AgAIgJgIAkVkj/kfr/wCAAiAmAgCRWSP8d8AAAACwgQD8AIEA/AAAACDZBABARIKX8/yH6/wwIwCAAgmIAkfr/gfj/wCAAkmgAwCAAmAhWef/AIACIAnzygCIwICAEHfAAAAAAQDZBABARIOX7/xZq/4Hs/5H7/8AgAJJoAMAgAJgIVnn/HfAAAFiA/T////8ABCBAPzZBACH8/zhCFoMGEBEgZfj/FvoFDPgMBDeoDZgigJkQgqABkEiDQEB0EBEgJfr/EBEgJfP/iCIMG0CYEZCrAcwUgKsBse3/sJkQsez/wCAAkmsAkc7/wCAAomkAwCAAqAlWev8cCQwaQJqDkDPAmog5QokiHfAAAHDi+j8IIEA/hGIBQKRiAUA2YQAQESBl7f8x+f+9Aa0Dgfr/4AgATQoMEuzqiAGSogCQiBCJARARIOXx/5Hy/6CiAcAgAIgJoIggwCAAiQm4Aa0Dge7/4AgAoCSDHfAAAP8PAAA2QQCBxf8MGZJIADCcQZkokfv/ORgpODAwtJoiKjMwPEEMAilYOUgQESAl+P8tCowaIqDFHfAAAMxxAUA2QQBBtv9YNFAzYxZjBFgUWlNQXEFGAQAQESDl7P+IRKYYBIgkh6XvEBEgJeX/Fmr/qBTNA70CgfH/4AgAoKB0jEpSoMRSZAVYFDpVWRRYNDBVwFk0HfAA+Pz/P0QA/T9MAP0/ADIBQOwxAUAwMwFANmEAfMitAoeTLTH3/8YFAKgDDBwQsSCB9//gCACBK/+iAQCICOAIAKgDgfP/4AgA5hrcxgoAAABmAyYMA80BDCsyYQCB7v/gCACYAYHo/zeZDagIZhoIMeb/wCAAokMAmQgd8EAA/T8AAP0/jDEBQDZBACH8/4Hc/8gCqAix+v+B+//gCAAMCIkCHfBgLwFANkEAgf7/4AgAggoYDAmCyP4MEoApkx3w+Cv+P/Qr/j8YAEw/jABMP//z//82QQAQESDl/P8WWgSh+P+ICrzYgff/mAi8abH2/3zMwCAAiAuQkBTAiBCQiCDAIACJC4gKsfH/DDpgqhHAIACYC6CIEKHu/6CZEJCIIMAgAIkLHfAoKwFANkEAEBEgZff/vBqR0f+ICRuoqQmR0P8MCoqZIkkAgsjBDBmAqYOggHTMiqKvQKoiIJiTjPkQESAl8v/GAQCtAoHv/+AIAB3wNkEAoqDAEBEg5fr/HfAAADZBAIKgwK0Ch5IRoqDbEBEgZfn/oqDcRgQAAAAAgqDbh5IIEBEgJfj/oqDdEBEgpff/HfA2QQA6MsYCAKICACLCARARIKX7/zeS8B3wAAAAbFIAQIxyAUCMUgBADFMAQDYhIaLREIH6/+AIAEYLAAAADBRARBFAQ2PNBL0BrQKB9f/gCACgoHT8Ws0EELEgotEQgfH/4AgASiJAM8BWA/0iogsQIrAgoiCy0RCB7P/gCACtAhwLEBEgpff/LQOGAAAioGMd8AAAQCsBQDZBABARICXl/4y6gYj/iAiMSBARICXi/wwKgfj/4AgAHfAAAIQyAUC08QBAkDIBQMDxAEA2QQAQESDl4f+smjFc/4ziqAOB9//gCACiogDGBgAAAKKiAIH0/+AIAKgDgfP/4AgARgUAAAAsCoyCgfD/4AgAhgEAAIHs/+AIAB3w8CsBQDZBIWKhB8BmERpmWQYMBWLREK0FUmYaEBEgZfn/DBhAiBFHuAJGRACtBoG1/+AIAIYzAACSpB1Qc8DgmREamUB3Y4kJzQe9ASCiIIGu/+AIAJKkHeCZERqZoKB0iAmMigwIgmYWfQiGFQCSpB3gmREamYkJEBEgpeL/vQetARARICXm/xARIKXh/80HELEgYKYggZ3/4AgAkqQd4JkRGpmICXAigHBVgDe1tJKhB8CZERqZmAmAdcCXtwJG3f+G5/8MCIJGbKKkGxCqoIHM/+AIAFYK/7KiC6IGbBC7sBARICWiAPfqEvZHD7KiDRC7sHq7oksAG3eG8f9867eawWZHCIImGje4Aoe1nCKiCxAisGC2IK0CgX3/4AgAEBEgJdj/rQIcCxARIKXb/xARICXX/wwaEBEgpef/HfAAAP0/T0hBSfwr/j9sgAJASDwBQDyDAkAIAAhgEIACQAwAAGA4QEA///8AACiBQD+MgAAAEEAAAAAs/j8QLP4/fJBAP/+P//+AkEA/hJBAP3iQQD9QAP0/VAD9P1ws/j8UAABg8P//APwr/j9YAP0/cID9P1zyAECI2ABA0PEAQKTxAEDUMgFAWDIBQKDkAEAEcAFAAHUBQIBJAUDoNQFA7DsBQIAAAUCYIAFA7HABQGxxAUAMcQFAhCkBQHh2AUDgdwFAlHYBQAAwAEBoAAFANsEAIcz/DAopoYHm/+AIABARIGW7/xbqBDHz/kHy/sAgACgDUfL+KQTAIAAoBWHs/qKgZCkGYe7+YCIQYqQAYCIgwCAAKQWB2P/gCABIBHzCQCIQDCRAIiDAIAApA4YBAEkCSyLGAQAhsv8xs/8MBDcy7RARIOXB/wxLosEoEBEgZcX/IqEBEBEgpcD/QfH9kCIRKiTAIABJAjGo/yHZ/TJiABARICWy/xY6BiGd/sGd/qgCDCuBn/7gCAAMnDwLDAqBuv/gCACxnv8MDAyagbj/4AgAoqIAgTL/4AgAsZn/qAJSoAGBs//gCACoAoEp/+AIAKgCgbD/4AgAMZP/wCAAKANQIiDAIAApAwYKAACxj//NCgxagab/4AgAMYz/UqEBwCAAKAMsClAiIMAgACkDgRv/4AgAgaH/4AgAIYX/wCAAKALMuhzDMCIQIsL4DBMgo4MMC4Ga/+AIAPF+/wwdDByyoAHioQBA3REAzBGAuwGioACBk//gCAAhef9RCf4qRGLVK8YWAAAAAMAgADIHADAwdBbzBKKiAMAgACJHAIH9/uAIAKKiccCqEYF+/+AIAIGF/+AIAHFo/3zowCAAOAeir/+AMxAQqgHAIAA5B4F+/+AIAIF+/+AIAK0CgX3/4AgAcVD+wCAAKAQWsvkMB8AgADgEDBLAIAB5BCJBHCIDAQwoeYEiQR2CUQ8cN3cSIxxHdxIkZpImIgMDcgMCgCIRcCIgZkIXKCPAIAAoAimBxgIAABwihgAAAAzCIlEPEBEg5aT/sqAIosEcEBEgZaj/cgMDIgMCgHcRIHcgIUD/ICD0d7IaoqDAEBEgJaP/oqDuEBEgpaL/EBEgZaH/Btj/IgMBHEgnODf2IhsG9wAiwi8gIHS2QgJGJgCBMv+AIqAoAqACAAAAIsL+ICB0HCgnuAJG7QCBLP+AIqAoAqACAILCMICAdLZYxIbnACxJDAgioMCXFwKG5QCJgQxyfQitBxARIKWb/60HEBEgJZv/EBEg5Zn/EBEgZZn/DIuiwRwLIhARIOWc/1Yy/YYvAAwSVhc1wsEQvQetB4Eu/+AIAFYaNLKgDKLBEBARIGWa/wauAAAADBJWtzKBJ//gCAAGKwAmhwYMEobGAAAAeCMoMyCHIICAtFa4/hARIGVt/yp3nBqG9/8AoKxBgRz/4AgAVhr9ItLwIKfAzCIGmwAAoID0Vhj+hgQAoKD1icGBFP/gCACIwVbK+oAiwAwYAIgRIKfAJzjhhgMAoKxBgQv/4AgAVvr4ItLwIKfAVqL+RooAAAwIIqDAJocChqgADAgtCMamACa39YZ8AAwSJrcChqAAuDOoI3KgABARICWR/6Ang8abAAwZZrddeEMgqREMCCKgwne6AkaZALhTqCOSYQ4QESAlZ/+Y4QwCoJKDhg0ADBlmtzF4QyCpEQwIIqDCd7oCRo4AKDO4U6gjIHeCmeEQESAlZP8hVv0MCJjhiWIi0it5IqCYgy0JxoEAkVD9DAiiCQAioMaHmgJGgACII3LH8CKgwHeYAShZDAiSoO9GAgCKo6IKGBuIoJkwdyjycgMFggMEgHcRgHcgggMGAIgRcIggcgMHgHcBgHcgcJnAcqDBDAiQJ5PGbABxOP0ioMaSBwCNCRZZGpg3DAgioMiHGQIGZgAoV5JHAEZhAByJDAgMEpcXAgZhAPhz6GPYU8hDuDOoIwwHgbH+4AgAjQqgJ4MGWgAMEiZHAkZVAJGX/oGX/sAgAHgJQCIRgHcQIHcgqCPAIAB5CZGS/gwLwCAAeAmAdxAgdyDAIAB5CZGO/sAgAHgJgHcQIHcgwCAAeQmRiv7AIAB4CYB3ECAnIMAgACkJgZX+4AgABh8AcKA0DAgioMCHGgLGPABwtEGLk30KfPwGDgAAqDmZ4bnBydGBhP7gCACY4bjBKCmIGagJyNGAghAmAg3AIADYCiAsMNAiECCIIMAgAIkKG3eSyRC3N8RGgf9mRwLGf/8MCCKgwIYmAAwSJrcCxiEAIWj+iFN4I4kCIWf+eQIMAgYdALFj/gwI2AsMGnLH8J0ILQjQKoNwmpMgmRAioMaHmWDBXf6NCegMIqDJdz5TcPAUIqDAVq8ELQmGAgAAKpOYaUsimQidCiD+wCqNdzLtFsnY+QyJC0Zh/wAMEmaHFyFN/ogCjBiCoMgMB3kCIUn+eQIMEoAngwwIRgEAAAwIIqD/IKB0gmEMEBEgZWL/iMGAoHQQESClYf8QESBlYP9WArUiAwEcJyc3HvYyAobQ/iLC/SAgdAz3J7cCBs3+cTb+cCKgKAKgAgByoNJ3El9yoNR3kgIGIQDGxf4AAHgzOCMQESAlT/+NClZqsKKiccCqEYnBgTD+4AgAISj+kSn+wCAAKAKIwSC0NcAiEZAiECC7IHC7gq0IMLvCgTb+4AgAoqPogST+4AgARrH+AADYU8hDuDOoIxARIGVs/4as/rIDAyIDAoC7ESC7ILLL8KLDGBARIOU3/8al/gAAIgMDcgMCgCIRcCIggST+4AgAcZD8IsLwiDeAImMWUqeIF4qCgIxBhgIAicEQESAlI/+CIQySJwSmGQSYJ5eo6RARICUb/xZq/6gXzQKywxiBFP7gCACMOjKgxDlXOBcqMzkXODcgI8ApN4EO/uAIAIaI/gAAIgMDggMCcsMYgCIRODWAIiAiwvBWwwn2UgKGJQAioMlGKgAx7P2BbvzoAymR4IjAiUGIJq0Jh7IBDDqZ4anR6cEQESBlGv+o0YHj/ejBqQGh4v3dCL0HwsEk8sEQicGB9f3gCAC4Js0KqJGY4aC7wLkmoCLAuAOqd6hBiMGquwwKuQPAqYOAu8Cg0HTMmuLbgK0N4KmDFuoBrQiJwZnhydEQESDlJf+IwZjhyNGJA0YBAAAADBydDIyyODWMc8A/McAzwJaz9daMACKgxylVhlP+AFaslCg1FlKUIqDIxvr/KCNWopMQESAlTP+ionHAqhGBvP3gCAAQESAlM/+Bzv3gCABGRv4AKDMWMpEQESClSf+io+iBs/3gCAAQESDlMP/gAgAGPv4AEBEgJTD/HfAAADZBAJ0CgqDAKAOHmQ/MMgwShgcADAIpA3zihg8AJhIHJiIYhgMAAACCoNuAKSOHmSoMIikDfPJGCAAAACKg3CeZCgwSKQMtCAYEAAAAgqDdfPKHmQYMEikDIqDbHfAAAA==", "text_start": 1073905664, - "data": "WAD9PzeLAkDJiwJAjpACQFKMAkDqiwJAUowCQLGMAkB6jQJA7Y0CQJWNAkDBigJAE40CQGyNAkDUjAJAEI4CQP6MAkAQjgJAt4sCQBaMAkBSjAJAsYwCQM+LAkADiwJA044CQEaQAkDWiQJAbZACQNaJAkDWiQJA1okCQNaJAkDWiQJA1okCQNaJAkDWiQJAcI4CQNaJAkBljwJARpACQA==", - "data_start": 1073622012 + "data": "WAD9P0uLAkDdiwJA8pACQGaMAkD+iwJAZowCQMWMAkDejQJAUY4CQPmNAkDVigJAd40CQNCNAkDojAJAdI4CQBCNAkB0jgJAy4sCQCqMAkBmjAJAxYwCQOOLAkAXiwJAN48CQKqQAkDqiQJA0ZACQOqJAkDqiQJA6okCQOqJAkDqiQJA6okCQOqJAkDqiQJA1I4CQOqJAkDJjwJAqpACQA==", + "data_start": 1073622012, + "bss_start": 1073545216 } \ No newline at end of file diff --git a/tools/python/esptool/targets/stub_flasher/stub_flasher_32s3.json b/tools/python/esptool/targets/stub_flasher/stub_flasher_32s3.json index a501e2f2..278a033f 100644 --- a/tools/python/esptool/targets/stub_flasher/stub_flasher_32s3.json +++ b/tools/python/esptool/targets/stub_flasher/stub_flasher_32s3.json @@ -1,7 +1,8 @@ { - "entry": 1077381696, - "text": "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", + "entry": 1077381712, + "text": "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", "text_start": 1077379072, - "data": "WADKP8mNN0C/jjdAiJM3QEuPN0DfjjdAS483QKqPN0B3kDdA6ZA3QJKQN0BVjTdAC5A3QGmQN0DNjzdAC5E3QPaPN0ALkTdArY43QAyPN0BLjzdAqo83QMWON0CXjTdA0JE3QE6TN0BujDdAbpM3QG6MN0BujDdAbow3QG6MN0BujDdAbow3QG6MN0BujDdAapE3QG6MN0BlkjdATpM3QAQInwAAAAAAAAAYAQQIBQAAAAAAAAAIAQQIBgAAAAAAAAAAAQQIIQAAAAAAIAAAEQQI3AAAAAAAIAAAEQQIDAAAAAAAIAAAAQQIEgAAAAAAIAAAESAoDAAQAQAA", - "data_start": 1070279668 + "data": "WADKPy6ON0ADjzdAF5Q3QI2PN0AjjzdAjY83QO2PN0AKkTdAfJE3QCWRN0C5jTdAoJA3QPyQN0AQkDdAoJE3QDiQN0CgkTdA8Y43QE6PN0CNjzdA7Y83QAmPN0D6jTdAYJI3QN2TN0DQjDdA/ZM3QNCMN0DQjDdA0Iw3QNCMN0DQjDdA0Iw3QNCMN0DQjDdA+pE3QNCMN0D1kjdA3ZM3QAQInwAAAAAAAAAYAQQIBQAAAAAAAAAIAQQIBgAAAAAAAAAAAQQIIQAAAAAAIAAAEQQI3AAAAAAAIAAAEQQIDAAAAAAAIAAAAQQIEgAAAAAAIAAAESAoDAAQAQAA", + "data_start": 1070279672, + "bss_start": 1070202880 } \ No newline at end of file diff --git a/tools/python/esptool/targets/stub_flasher/stub_flasher_32s3beta2.json b/tools/python/esptool/targets/stub_flasher/stub_flasher_32s3beta2.json index 45328015..da770f7b 100644 --- a/tools/python/esptool/targets/stub_flasher/stub_flasher_32s3beta2.json +++ b/tools/python/esptool/targets/stub_flasher/stub_flasher_32s3beta2.json @@ -1,7 +1,8 @@ { - "entry": 1077381188, - "text": "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", + "entry": 1077380596, + "text": "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", "text_start": 1077379072, - "data": "WADKP7uLN0BPjDdAHJE3QNuMN0BvjDdA24w3QDqNN0AHjjdAeY43QCKON0BFizdAm403QPmNN0BdjTdAnI43QIaNN0CcjjdAPYw3QJyMN0DbjDdAOo03QFWMN0CHizdAYI83QOKQN0BeijdAApE3QF6KN0BeijdAXoo3QF6KN0BeijdAXoo3QF6KN0BeijdA+443QF6KN0D1jzdA4pA3QA==", - "data_start": 1070279668 + "data": "DADKPxeIN0CriDdAw403QDeJN0DLiDdAN4k3QJaJN0C2ijdAKIs3QNGKN0ChhzdASIo3QKiKN0C5iTdATIs3QOGJN0BMizdAmYg3QPiIN0A3iTdAlok3QLGIN0DjhzdABIw3QIWNN0DAhjdAp403QMCGN0DAhjdAwIY3QMCGN0DAhjdAwIY3QMCGN0DAhjdAqYs3QMCGN0CZjDdAhY03QA==", + "data_start": 1070279592, + "bss_start": 1070202880 } \ No newline at end of file diff --git a/tools/python/esptool/targets/stub_flasher/stub_flasher_8266.json b/tools/python/esptool/targets/stub_flasher/stub_flasher_8266.json index 95e6e9e5..f68ffef9 100644 --- a/tools/python/esptool/targets/stub_flasher/stub_flasher_8266.json +++ b/tools/python/esptool/targets/stub_flasher/stub_flasher_8266.json @@ -3,5 +3,6 @@ "text": "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", "text_start": 1074843648, "data": "CIH+PwUFBAACAwcAAwMLANTXEEAL2BBAOdgQQNbYEECF5xBAOtkQQJDZEEDc2RBAhecQQKLaEEAf2xBA4NsQQIXnEECF5xBAeNwQQIXnEEBV3xBAHOAQQFfgEECF5xBAhecQQPPgEECF5xBA2+EQQIHiEEDA4xBAf+QQQFDlEECF5xBAhecQQIXnEECF5xBAfuYQQIXnEEB05xBAsN0QQKnYEEDC5RBAydoQQBvaEECF5xBACOcQQE/nEECF5xBAhecQQIXnEECF5xBAhecQQIXnEECF5xBAhecQQELaEEB/2hBA2uUQQAEAAAACAAAAAwAAAAQAAAAFAAAABwAAAAkAAAANAAAAEQAAABkAAAAhAAAAMQAAAEEAAABhAAAAgQAAAMEAAAABAQAAgQEAAAECAAABAwAAAQQAAAEGAAABCAAAAQwAAAEQAAABGAAAASAAAAEwAAABQAAAAWAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAgAAAAIAAAADAAAAAwAAAAQAAAAEAAAABQAAAAUAAAAGAAAABgAAAAcAAAAHAAAACAAAAAgAAAAJAAAACQAAAAoAAAAKAAAACwAAAAsAAAAMAAAADAAAAA0AAAANAAAAAAAAAAAAAAADAAAABAAAAAUAAAAGAAAABwAAAAgAAAAJAAAACgAAAAsAAAANAAAADwAAABEAAAATAAAAFwAAABsAAAAfAAAAIwAAACsAAAAzAAAAOwAAAEMAAABTAAAAYwAAAHMAAACDAAAAowAAAMMAAADjAAAAAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAEAAAABAAAAAgAAAAIAAAACAAAAAgAAAAMAAAADAAAAAwAAAAMAAAAEAAAABAAAAAQAAAAEAAAABQAAAAUAAAAFAAAABQAAAAAAAAAAAAAAAAAAABAREgAIBwkGCgULBAwDDQIOAQ8AAQEAAAEAAAAEAAAA", - "data_start": 1073720488 + "data_start": 1073720488, + "bss_start": 1073643776 } \ No newline at end of file diff --git a/tools/python/esptool/uf2_writer.py b/tools/python/esptool/uf2_writer.py new file mode 100644 index 00000000..adc1ac44 --- /dev/null +++ b/tools/python/esptool/uf2_writer.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python +# +# SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: GPL-2.0-or-later +# Code was originally licensed under Apache 2.0 before the release of ESP-IDF v5.2 + +import hashlib +import os +import struct +from typing import List + +from util import div_roundup + + +class UF2Writer(object): + # The UF2 format is described here: https://github.com/microsoft/uf2 + UF2_BLOCK_SIZE = 512 + # max value of CHUNK_SIZE reduced by optional parts. Currently, MD5_PART only. + UF2_DATA_SIZE = 476 + UF2_MD5_PART_SIZE = 24 + UF2_FIRST_MAGIC = 0x0A324655 + UF2_SECOND_MAGIC = 0x9E5D5157 + UF2_FINAL_MAGIC = 0x0AB16F30 + UF2_FLAG_FAMILYID_PRESENT = 0x00002000 + UF2_FLAG_MD5_PRESENT = 0x00004000 + + def __init__( + self, + chip_id: int, + output_file: os.PathLike, + chunk_size: int, + md5_enabled: bool = True, + ) -> None: + if not md5_enabled: + self.UF2_MD5_PART_SIZE = 0 + self.UF2_FLAG_MD5_PRESENT = 0x00000000 + self.md5_enabled = md5_enabled + self.chip_id = chip_id + self.CHUNK_SIZE = ( + self.UF2_DATA_SIZE - self.UF2_MD5_PART_SIZE + if chunk_size is None + else chunk_size + ) + self.f = open(output_file, "wb") + + def __enter__(self) -> "UF2Writer": + return self + + def __exit__(self, exc_type: str, exc_val: int, exc_tb: List) -> None: + if self.f: + self.f.close() + + @staticmethod + def _to_uint32(num: int) -> bytes: + return struct.pack(" None: + assert len_chunk > 0 + assert len_chunk <= self.CHUNK_SIZE + assert block_no < blocks + block = struct.pack( + " None: + blocks = div_roundup(len(image), self.CHUNK_SIZE) + chunks = [ + image[i : i + self.CHUNK_SIZE] + for i in range(0, len(image), self.CHUNK_SIZE) + ] + for i, chunk in enumerate(chunks): + len_chunk = len(chunk) + self._write_block(addr, chunk, len_chunk, i, blocks) + addr += len_chunk diff --git a/tools/python/esptool/util.py b/tools/python/esptool/util.py index e390e104..fb4a5719 100644 --- a/tools/python/esptool/util.py +++ b/tools/python/esptool/util.py @@ -34,6 +34,8 @@ def flash_size_bytes(size): """Given a flash size of the type passed in args.flash_size (ie 512KB or 1MB) then return the size in bytes. """ + if size is None: + return None if "MB" in size: return int(size[: size.index("MB")]) * 1024 * 1024 elif "KB" in size: @@ -66,7 +68,7 @@ def print_overwrite(message, last_line=False): If output is not a TTY (for example redirected a pipe), no overwriting happens and this function is the same as print(). """ - if sys.stdout.isatty(): + if hasattr(sys.stdout, "isatty") and sys.stdout.isatty(): print("\r%s" % message, end="\n" if last_line else "") else: print(message) @@ -165,7 +167,7 @@ class NotSupportedError(FatalError): def __init__(self, esp, function_name): FatalError.__init__( self, - "Function %s is not supported for %s." % (function_name, esp.CHIP_NAME), + f"{function_name} is not supported by {esp.CHIP_NAME}.", )