diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index b64f119..51a67e2 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -122,7 +122,10 @@ jobs:
- uses: actions/setup-python@v7
with:
- python-version: "3.9"
+ python-version: "3.13"
+
+ - name: Install esptool
+ run: pip install "esptool>=5,<6"
- name: Install PlatformIO Core
run: pip install --upgrade platformio
@@ -148,44 +151,44 @@ jobs:
- name: Merge for web flashing
run: |
if [ "${{ matrix.target.chip }}" == "esp32" ]; then
- python installer/bin/esptool/esptool.py --chip esp32 merge_bin \
+ esptool --chip esp32 merge-bin \
-o installer/web_factory.bin \
- --flash_mode dio \
- --flash_freq 40m \
- --flash_size 4MB \
+ --flash-mode dio \
+ --flash-freq 40m \
+ --flash-size 4MB \
0x1000 installer/firmware/bootloader.bin \
0x8000 installer/firmware/partitions.bin \
0xe000 installer/firmware/boot_app0.bin \
0x10000 installer/firmware/firmware.bin \
0x3D0000 installer/firmware/spiffs.bin
elif [ "${{ matrix.target.chip }}" == "esp32s2" ]; then
- python installer/bin/esptool/esptool.py --chip esp32s2 merge_bin \
+ esptool --chip esp32s2 merge-bin \
-o installer/web_factory.bin \
- --flash_mode dio \
- --flash_freq 40m \
- --flash_size 4MB \
+ --flash-mode dio \
+ --flash-freq 40m \
+ --flash-size 4MB \
0x1000 installer/firmware/bootloader.bin \
0x8000 installer/firmware/partitions.bin \
0xe000 installer/firmware/boot_app0.bin \
0x10000 installer/firmware/firmware.bin \
0x3D0000 installer/firmware/spiffs.bin
elif [ "${{ matrix.target.chip }}" == "esp32s3" ]; then
- python installer/bin/esptool/esptool.py --chip esp32s3 merge_bin \
+ esptool --chip esp32s3 merge-bin \
-o installer/web_factory.bin \
- --flash_mode dio \
- --flash_freq 40m \
- --flash_size 8MB \
+ --flash-mode dio \
+ --flash-freq 40m \
+ --flash-size 8MB \
0x0000 installer/firmware/bootloader.bin \
0x8000 installer/firmware/partitions.bin \
0xe000 installer/firmware/boot_app0.bin \
0x10000 installer/firmware/firmware.bin \
0x3D0000 installer/firmware/spiffs.bin
elif [ "${{ matrix.target.chip }}" == "esp32c3" ]; then
- python installer/bin/esptool/esptool.py --chip esp32c3 merge_bin \
+ esptool --chip esp32c3 merge-bin \
-o installer/web_factory.bin \
- --flash_mode dio \
- --flash_freq 40m \
- --flash_size 4MB \
+ --flash-mode dio \
+ --flash-freq 40m \
+ --flash-size 4MB \
0x1000 installer/firmware/bootloader.bin \
0x8000 installer/firmware/partitions.bin \
0xe000 installer/firmware/boot_app0.bin \
diff --git a/installer/bin/esptool/esptool.py b/installer/bin/esptool/esptool.py
deleted file mode 100644
index 60e5bd3..0000000
--- a/installer/bin/esptool/esptool.py
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/usr/bin/env python
-#
-# SPDX-FileCopyrightText: 2014-2022 Fredrik Ahlberg, Angus Gratton,
-# Espressif Systems (Shanghai) CO LTD, other contributors as noted.
-#
-# SPDX-License-Identifier: GPL-2.0-or-later
-
-# This executable script is a thin wrapper around the main functionality
-# in the esptool Python package
-
-# When updating this script, please also update espefuse.py and espsecure.py
-
-import contextlib
-import os
-import sys
-
-if os.name != "nt":
- # Linux/macOS: remove current script directory to avoid importing this file
- # as a module; we want to import the installed esptool module instead
- with contextlib.suppress(ValueError):
- if sys.path[0].endswith("/bin"):
- sys.path.pop(0)
- sys.path.remove(os.path.dirname(sys.executable))
-
- # Linux/macOS: delete imported module entry to force Python to load
- # the module from scratch; this enables importing esptool module in
- # other Python scripts
- with contextlib.suppress(KeyError):
- del sys.modules["esptool"]
-
-import esptool
-
-if __name__ == "__main__":
- esptool._main()
diff --git a/installer/bin/esptool/esptool/__init__.py b/installer/bin/esptool/esptool/__init__.py
deleted file mode 100644
index 24272f2..0000000
--- a/installer/bin/esptool/esptool/__init__.py
+++ /dev/null
@@ -1,1055 +0,0 @@
-# SPDX-FileCopyrightText: 2014-2022 Fredrik Ahlberg, Angus Gratton,
-# Espressif Systems (Shanghai) CO LTD, other contributors as noted.
-#
-# SPDX-License-Identifier: GPL-2.0-or-later
-
-__all__ = [
- "chip_id",
- "detect_chip",
- "dump_mem",
- "elf2image",
- "erase_flash",
- "erase_region",
- "flash_id",
- "get_security_info",
- "image_info",
- "load_ram",
- "make_image",
- "merge_bin",
- "read_flash",
- "read_flash_status",
- "read_mac",
- "read_mem",
- "run",
- "verify_flash",
- "version",
- "write_flash",
- "write_flash_status",
- "write_mem",
-]
-
-__version__ = "4.5.1"
-
-import argparse
-import inspect
-import os
-import shlex
-import sys
-import time
-import traceback
-
-from esptool.cmds import (
- chip_id,
- detect_chip,
- detect_flash_size,
- dump_mem,
- elf2image,
- erase_flash,
- erase_region,
- flash_id,
- get_security_info,
- image_info,
- load_ram,
- make_image,
- merge_bin,
- read_flash,
- read_flash_status,
- read_mac,
- read_mem,
- run,
- verify_flash,
- version,
- write_flash,
- write_flash_status,
- write_mem,
-)
-from esptool.config import load_config_file
-from esptool.loader import DEFAULT_CONNECT_ATTEMPTS, ESPLoader, list_ports
-from esptool.targets import CHIP_DEFS, CHIP_LIST, ESP32ROM
-from esptool.util import (
- FatalError,
- NotImplementedInROMError,
- flash_size_bytes,
- strip_chip_name,
-)
-
-import serial
-
-
-def main(argv=None, esp=None):
- """
- Main function for esptool
-
- argv - Optional override for default arguments parsing (that uses sys.argv),
- can be a list of custom arguments as strings. Arguments and their values
- need to be added as individual items to the list
- e.g. "-b 115200" thus becomes ['-b', '115200'].
-
- esp - Optional override of the connected device previously
- returned by get_default_connected_device()
- """
-
- external_esp = esp is not None
-
- parser = argparse.ArgumentParser(
- description="esptool.py v%s - Espressif chips ROM Bootloader Utility"
- % __version__,
- prog="esptool",
- )
-
- parser.add_argument(
- "--chip",
- "-c",
- help="Target chip type",
- type=strip_chip_name,
- choices=["auto"] + CHIP_LIST,
- default=os.environ.get("ESPTOOL_CHIP", "auto"),
- )
-
- parser.add_argument(
- "--port",
- "-p",
- help="Serial port device",
- default=os.environ.get("ESPTOOL_PORT", None),
- )
-
- parser.add_argument(
- "--baud",
- "-b",
- help="Serial port baud rate used when flashing/reading",
- type=arg_auto_int,
- default=os.environ.get("ESPTOOL_BAUD", ESPLoader.ESP_ROM_BAUD),
- )
-
- parser.add_argument(
- "--before",
- help="What to do before connecting to the chip",
- choices=["default_reset", "usb_reset", "no_reset", "no_reset_no_sync"],
- default=os.environ.get("ESPTOOL_BEFORE", "default_reset"),
- )
-
- parser.add_argument(
- "--after",
- "-a",
- help="What to do after esptool.py is finished",
- choices=["hard_reset", "soft_reset", "no_reset", "no_reset_stub"],
- default=os.environ.get("ESPTOOL_AFTER", "hard_reset"),
- )
-
- parser.add_argument(
- "--no-stub",
- help="Disable launching the flasher stub, only talk to ROM bootloader. "
- "Some features will not be available.",
- action="store_true",
- )
-
- parser.add_argument(
- "--trace",
- "-t",
- help="Enable trace-level output of esptool.py interactions.",
- action="store_true",
- )
-
- parser.add_argument(
- "--override-vddsdio",
- help="Override ESP32 VDDSDIO internal voltage regulator (use with care)",
- choices=ESP32ROM.OVERRIDE_VDDSDIO_CHOICES,
- nargs="?",
- )
-
- parser.add_argument(
- "--connect-attempts",
- help=(
- "Number of attempts to connect, negative or 0 for infinite. "
- "Default: %d." % DEFAULT_CONNECT_ATTEMPTS
- ),
- type=int,
- default=os.environ.get("ESPTOOL_CONNECT_ATTEMPTS", DEFAULT_CONNECT_ATTEMPTS),
- )
-
- subparsers = parser.add_subparsers(
- dest="operation", help="Run esptool.py {command} -h for additional help"
- )
-
- def add_spi_connection_arg(parent):
- parent.add_argument(
- "--spi-connection",
- "-sc",
- help="ESP32-only argument. 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).",
- 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_dump_mem = subparsers.add_parser(
- "dump_mem", help="Dump arbitrary memory to disk"
- )
- parser_dump_mem.add_argument("address", help="Base address", type=arg_auto_int)
- parser_dump_mem.add_argument(
- "size", help="Size of region to dump", type=arg_auto_int
- )
- parser_dump_mem.add_argument("filename", help="Name of binary dump")
-
- parser_read_mem = subparsers.add_parser(
- "read_mem", help="Read arbitrary memory location"
- )
- parser_read_mem.add_argument("address", help="Address to read", type=arg_auto_int)
-
- parser_write_mem = subparsers.add_parser(
- "write_mem", help="Read-modify-write to arbitrary memory location"
- )
- parser_write_mem.add_argument("address", help="Address to write", type=arg_auto_int)
- parser_write_mem.add_argument("value", help="Value", type=arg_auto_int)
- parser_write_mem.add_argument(
- "mask",
- help="Mask of bits to write",
- type=arg_auto_int,
- nargs="?",
- default="0xFFFFFFFF",
- )
-
- def add_spi_flash_subparsers(parent, allow_keep, auto_detect):
- """Add common parser arguments for SPI flash properties"""
- extra_keep_args = ["keep"] if allow_keep else []
-
- if auto_detect and allow_keep:
- extra_fs_message = ", detect, or keep"
- flash_sizes = ["detect", "keep"]
- elif auto_detect:
- extra_fs_message = ", or detect"
- flash_sizes = ["detect"]
- elif allow_keep:
- extra_fs_message = ", or keep"
- flash_sizes = ["keep"]
- else:
- extra_fs_message = ""
- flash_sizes = []
-
- parent.add_argument(
- "--flash_freq",
- "-ff",
- help="SPI Flash frequency",
- choices=extra_keep_args
- + [
- "80m",
- "60m",
- "48m",
- "40m",
- "30m",
- "26m",
- "24m",
- "20m",
- "16m",
- "15m",
- "12m",
- ],
- default=os.environ.get("ESPTOOL_FF", "keep" if allow_keep else None),
- )
- parent.add_argument(
- "--flash_mode",
- "-fm",
- help="SPI Flash mode",
- choices=extra_keep_args + ["qio", "qout", "dio", "dout"],
- default=os.environ.get("ESPTOOL_FM", "keep" if allow_keep else "qio"),
- )
- parent.add_argument(
- "--flash_size",
- "-fs",
- help="SPI Flash size in MegaBytes "
- "(1MB, 2MB, 4MB, 8MB, 16MB, 32MB, 64MB, 128MB) "
- "plus ESP8266-only (256KB, 512KB, 2MB-c1, 4MB-c1)" + extra_fs_message,
- choices=flash_sizes
- + [
- "256KB",
- "512KB",
- "1MB",
- "2MB",
- "2MB-c1",
- "4MB",
- "4MB-c1",
- "8MB",
- "16MB",
- "32MB",
- "64MB",
- "128MB",
- ],
- default=os.environ.get("ESPTOOL_FS", "keep" if allow_keep else "1MB"),
- )
- add_spi_connection_arg(parent)
-
- parser_write_flash = subparsers.add_parser(
- "write_flash", help="Write a binary blob to flash"
- )
-
- parser_write_flash.add_argument(
- "addr_filename",
- metavar="
",
- help="Address followed by binary filename, separated by space",
- action=AddrFilenamePairAction,
- )
- parser_write_flash.add_argument(
- "--erase-all",
- "-e",
- help="Erase all regions of flash (not just write areas) before programming",
- action="store_true",
- )
-
- add_spi_flash_subparsers(parser_write_flash, allow_keep=True, auto_detect=True)
- parser_write_flash.add_argument(
- "--no-progress", "-p", help="Suppress progress output", action="store_true"
- )
- parser_write_flash.add_argument(
- "--verify",
- help="Verify just-written data on flash "
- "(mostly superfluous, data is read back during flashing)",
- action="store_true",
- )
- parser_write_flash.add_argument(
- "--encrypt",
- help="Apply flash encryption when writing data "
- "(required correct efuse settings)",
- action="store_true",
- )
- # In order to not break backward compatibility,
- # our list of encrypted files to flash is a new parameter
- parser_write_flash.add_argument(
- "--encrypt-files",
- metavar=" ",
- help="Files to be encrypted on the flash. "
- "Address followed by binary filename, separated by space.",
- action=AddrFilenamePairAction,
- )
- parser_write_flash.add_argument(
- "--ignore-flash-encryption-efuse-setting",
- help="Ignore flash encryption efuse settings ",
- action="store_true",
- )
- parser_write_flash.add_argument(
- "--force",
- help="Force write, skip security and compatibility checks. Use with caution!",
- action="store_true",
- )
-
- compress_args = parser_write_flash.add_mutually_exclusive_group(required=False)
- compress_args.add_argument(
- "--compress",
- "-z",
- help="Compress data in transfer (default unless --no-stub is specified)",
- action="store_true",
- default=None,
- )
- compress_args.add_argument(
- "--no-compress",
- "-u",
- help="Disable data compression during transfer "
- "(default if --no-stub is specified)",
- action="store_true",
- )
-
- subparsers.add_parser("run", help="Run application code in flash")
-
- parser_image_info = subparsers.add_parser(
- "image_info", help="Dump headers from an application image"
- )
- parser_image_info.add_argument("filename", help="Image file to parse")
- parser_image_info.add_argument(
- "--version",
- "-v",
- help="Output format version (1 - legacy, 2 - extended)",
- choices=["1", "2"],
- default="1",
- )
-
- parser_make_image = subparsers.add_parser(
- "make_image", help="Create an application image from binary files"
- )
- parser_make_image.add_argument("output", help="Output image file")
- parser_make_image.add_argument(
- "--segfile", "-f", action="append", help="Segment input file"
- )
- parser_make_image.add_argument(
- "--segaddr",
- "-a",
- action="append",
- help="Segment base address",
- type=arg_auto_int,
- )
- parser_make_image.add_argument(
- "--entrypoint",
- "-e",
- help="Address of entry point",
- type=arg_auto_int,
- default=0,
- )
-
- parser_elf2image = subparsers.add_parser(
- "elf2image", help="Create an application image from ELF file"
- )
- parser_elf2image.add_argument("input", help="Input ELF file")
- parser_elf2image.add_argument(
- "--output",
- "-o",
- help="Output filename prefix (for version 1 image), "
- "or filename (for version 2 single image)",
- type=str,
- )
- parser_elf2image.add_argument(
- "--version",
- "-e",
- help="Output image version",
- choices=["1", "2", "3"],
- default="1",
- )
- parser_elf2image.add_argument(
- # it kept for compatibility
- # Minimum chip revision (deprecated, consider using --min-rev-full)
- "--min-rev",
- "-r",
- help=argparse.SUPPRESS,
- type=int,
- choices=range(256),
- metavar="{0, ... 255}",
- default=0,
- )
- parser_elf2image.add_argument(
- "--min-rev-full",
- help="Minimal chip revision (in format: major * 100 + minor)",
- type=int,
- choices=range(65536),
- metavar="{0, ... 65535}",
- default=0,
- )
- parser_elf2image.add_argument(
- "--max-rev-full",
- help="Maximal chip revision (in format: major * 100 + minor)",
- type=int,
- choices=range(65536),
- metavar="{0, ... 65535}",
- default=65535,
- )
- parser_elf2image.add_argument(
- "--secure-pad",
- action="store_true",
- help="Pad image so once signed it will end on a 64KB boundary. "
- "For Secure Boot v1 images only.",
- )
- parser_elf2image.add_argument(
- "--secure-pad-v2",
- action="store_true",
- help="Pad image to 64KB, so once signed its signature sector will"
- "start at the next 64K block. For Secure Boot v2 images only.",
- )
- parser_elf2image.add_argument(
- "--elf-sha256-offset",
- help="If set, insert SHA256 hash (32 bytes) of the input ELF file "
- "at specified offset in the binary.",
- type=arg_auto_int,
- default=None,
- )
- parser_elf2image.add_argument(
- "--dont-append-digest",
- dest="append_digest",
- help="Don't append a SHA256 digest of the entire image after the checksum. "
- "This argument is not supported and ignored for ESP8266.",
- action="store_false",
- default=True,
- )
- parser_elf2image.add_argument(
- "--use_segments",
- help="If set, ELF segments will be used instead of ELF sections "
- "to genereate the image.",
- action="store_true",
- )
- parser_elf2image.add_argument(
- "--flash-mmu-page-size",
- help="Change flash MMU page size.",
- choices=["64KB", "32KB", "16KB", "8KB"],
- )
- parser_elf2image.add_argument(
- "--pad-to-size",
- help="The block size with which the final binary image after padding "
- "must be aligned to. Value 0xFF is used for padding, similar to erase_flash",
- default=None,
- )
-
- add_spi_flash_subparsers(parser_elf2image, allow_keep=False, auto_detect=False)
-
- subparsers.add_parser("read_mac", help="Read MAC address from OTP ROM")
-
- subparsers.add_parser("chip_id", help="Read Chip ID from OTP ROM")
-
- parser_flash_id = subparsers.add_parser(
- "flash_id", help="Read SPI flash manufacturer and device ID"
- )
- add_spi_connection_arg(parser_flash_id)
-
- parser_read_status = subparsers.add_parser(
- "read_flash_status", help="Read SPI flash status register"
- )
-
- add_spi_connection_arg(parser_read_status)
- parser_read_status.add_argument(
- "--bytes",
- help="Number of bytes to read (1-3)",
- type=int,
- choices=[1, 2, 3],
- default=2,
- )
-
- parser_write_status = subparsers.add_parser(
- "write_flash_status", help="Write SPI flash status register"
- )
-
- add_spi_connection_arg(parser_write_status)
- parser_write_status.add_argument(
- "--non-volatile",
- help="Write non-volatile bits (use with caution)",
- action="store_true",
- )
- parser_write_status.add_argument(
- "--bytes",
- help="Number of status bytes to write (1-3)",
- type=int,
- choices=[1, 2, 3],
- default=2,
- )
- parser_write_status.add_argument("value", help="New value", type=arg_auto_int)
-
- parser_read_flash = subparsers.add_parser(
- "read_flash", help="Read SPI flash content"
- )
- add_spi_connection_arg(parser_read_flash)
- parser_read_flash.add_argument("address", help="Start address", type=arg_auto_int)
- parser_read_flash.add_argument(
- "size", help="Size of region to dump", type=arg_auto_int
- )
- parser_read_flash.add_argument("filename", help="Name of binary dump")
- parser_read_flash.add_argument(
- "--no-progress", "-p", help="Suppress progress output", action="store_true"
- )
-
- parser_verify_flash = subparsers.add_parser(
- "verify_flash", help="Verify a binary blob against flash"
- )
- parser_verify_flash.add_argument(
- "addr_filename",
- help="Address and binary file to verify there, separated by space",
- action=AddrFilenamePairAction,
- )
- parser_verify_flash.add_argument(
- "--diff", "-d", help="Show differences", choices=["no", "yes"], default="no"
- )
- add_spi_flash_subparsers(parser_verify_flash, allow_keep=True, auto_detect=True)
-
- parser_erase_flash = subparsers.add_parser(
- "erase_flash", help="Perform Chip Erase on SPI flash"
- )
- parser_erase_flash.add_argument(
- "--force",
- help="Erase flash even if security features are enabled. Use with caution!",
- action="store_true",
- )
- add_spi_connection_arg(parser_erase_flash)
-
- parser_erase_region = subparsers.add_parser(
- "erase_region", help="Erase a region of the flash"
- )
- parser_erase_region.add_argument(
- "--force",
- help="Erase region even if security features are enabled. Use with caution!",
- action="store_true",
- )
- add_spi_connection_arg(parser_erase_region)
- parser_erase_region.add_argument(
- "address", help="Start address (must be multiple of 4096)", type=arg_auto_int
- )
- parser_erase_region.add_argument(
- "size",
- help="Size of region to erase (must be multiple of 4096)",
- type=arg_auto_int,
- )
-
- parser_merge_bin = subparsers.add_parser(
- "merge_bin",
- help="Merge multiple raw binary files into a single file for later flashing",
- )
-
- parser_merge_bin.add_argument(
- "--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
- add_spi_flash_subparsers(parser_merge_bin, allow_keep=True, auto_detect=False)
-
- parser_merge_bin.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(
- "--fill-flash-size",
- help="If set, the final binary file will be padded with FF "
- "bytes up to this flash size.",
- choices=[
- "256KB",
- "512KB",
- "1MB",
- "2MB",
- "4MB",
- "8MB",
- "16MB",
- "32MB",
- "64MB",
- "128MB",
- ],
- )
- parser_merge_bin.add_argument(
- "addr_filename",
- metavar=" ",
- help="Address followed by binary filename, separated by space",
- action=AddrFilenamePairAction,
- )
-
- subparsers.add_parser("get_security_info", help="Get some security-related data")
-
- subparsers.add_parser("version", help="Print esptool version")
-
- # internal sanity check - every operation matches a module function of the same name
- for operation in subparsers.choices.keys():
- assert operation in globals(), "%s should be a module function" % operation
-
- argv = expand_file_arguments(argv or sys.argv[1:])
-
- args = parser.parse_args(argv)
- print("esptool.py v%s" % __version__)
- load_config_file(verbose=True)
-
- # operation function can take 1 arg (args), 2 args (esp, arg)
- # or be a member function of the ESPLoader class.
-
- if args.operation is None:
- parser.print_help()
- sys.exit(1)
-
- # Forbid the usage of both --encrypt, which means encrypt all the given files,
- # and --encrypt-files, which represents the list of files to encrypt.
- # The reason is that allowing both at the same time increases the chances of
- # having contradictory lists (e.g. one file not available in one of list).
- if (
- args.operation == "write_flash"
- and args.encrypt
- and args.encrypt_files is not None
- ):
- raise FatalError(
- "Options --encrypt and --encrypt-files "
- "must not be specified at the same time."
- )
-
- operation_func = globals()[args.operation]
- operation_args = inspect.getfullargspec(operation_func).args
-
- if (
- operation_args[0] == "esp"
- ): # operation function takes an ESPLoader connection object
- if args.before != "no_reset_no_sync":
- initial_baud = min(
- ESPLoader.ESP_ROM_BAUD, args.baud
- ) # don't sync faster than the default baud rate
- else:
- initial_baud = args.baud
-
- if args.port is None:
- ser_list = get_port_list()
- print("Found %d serial ports" % len(ser_list))
- else:
- ser_list = [args.port]
- esp = esp or get_default_connected_device(
- ser_list,
- port=args.port,
- connect_attempts=args.connect_attempts,
- initial_baud=initial_baud,
- chip=args.chip,
- trace=args.trace,
- before=args.before,
- )
-
- if esp is None:
- raise FatalError(
- "Could not connect to an Espressif device "
- "on any of the %d available serial ports." % len(ser_list)
- )
-
- if esp.secure_download_mode:
- print("Chip is %s in Secure Download Mode" % esp.CHIP_NAME)
- else:
- print("Chip is %s" % (esp.get_chip_description()))
- print("Features: %s" % ", ".join(esp.get_chip_features()))
- print("Crystal is %dMHz" % esp.get_crystal_freq())
- read_mac(esp, args)
-
- if not args.no_stub:
- if esp.secure_download_mode:
- print(
- "WARNING: Stub loader is not supported in Secure Download Mode, "
- "setting --no-stub"
- )
- args.no_stub = True
- elif not esp.IS_STUB and esp.stub_is_disabled:
- print(
- "WARNING: Stub loader has been disabled for compatibility, "
- "setting --no-stub"
- )
- args.no_stub = True
- else:
- esp = esp.run_stub()
-
- if args.override_vddsdio:
- esp.override_vddsdio(args.override_vddsdio)
-
- if args.baud > initial_baud:
- try:
- esp.change_baud(args.baud)
- except NotImplementedInROMError:
- print(
- "WARNING: ROM doesn't support changing baud rate. "
- "Keeping initial baud rate %d" % initial_baud
- )
-
- # override 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)
- elif args.no_stub:
- print("Enabling default SPI flash mode...")
- # ROM loader doesn't enable flash unless we explicitly do it
- esp.flash_spi_attach(0)
-
- # XMC chip startup sequence
- XMC_VENDOR_ID = 0x20
-
- def is_xmc_chip_strict():
- id = esp.flash_id()
- rdid = ((id & 0xFF) << 16) | ((id >> 16) & 0xFF) | (id & 0xFF00)
-
- vendor_id = (rdid >> 16) & 0xFF
- mfid = (rdid >> 8) & 0xFF
- cpid = rdid & 0xFF
-
- if vendor_id != XMC_VENDOR_ID:
- return False
-
- matched = False
- if mfid == 0x40:
- if cpid >= 0x13 and cpid <= 0x20:
- matched = True
- elif mfid == 0x41:
- if cpid >= 0x17 and cpid <= 0x20:
- matched = True
- elif mfid == 0x50:
- if cpid >= 0x15 and cpid <= 0x16:
- matched = True
- return matched
-
- def flash_xmc_startup():
- # If the RDID value is a valid XMC one, may skip the flow
- fast_check = True
- if fast_check and is_xmc_chip_strict():
- return # Successful XMC flash chip boot-up detected by RDID, skipping.
-
- sfdp_mfid_addr = 0x10
- mf_id = esp.read_spiflash_sfdp(sfdp_mfid_addr, 8)
- if mf_id != XMC_VENDOR_ID: # Non-XMC chip detected by SFDP Read, skipping.
- return
-
- print(
- "WARNING: XMC flash chip boot-up failure detected! "
- "Running XMC25QHxxC startup flow"
- )
- esp.run_spiflash_command(0xB9) # Enter DPD
- esp.run_spiflash_command(0x79) # Enter UDPD
- esp.run_spiflash_command(0xFF) # Exit UDPD
- time.sleep(0.002) # Delay tXUDPD
- esp.run_spiflash_command(0xAB) # Release Power-Down
- time.sleep(0.00002)
- # Check for success
- if not is_xmc_chip_strict():
- print("WARNING: XMC flash boot-up fix failed.")
- print("XMC flash chip boot-up fix successful!")
-
- # Check flash chip connection
- if not esp.secure_download_mode:
- try:
- flash_id = esp.flash_id()
- if flash_id in (0xFFFFFF, 0x000000):
- print(
- "WARNING: Failed to communicate with the flash chip, "
- "read/write operations will fail. "
- "Try checking the chip connections or removing "
- "any other hardware connected to IOs."
- )
- except FatalError as e:
- raise FatalError(f"Unable to verify flash chip connection ({e}).")
-
- # Check if XMC SPI flash chip booted-up successfully, fix if not
- if not esp.secure_download_mode:
- try:
- flash_xmc_startup()
- except FatalError as e:
- esp.trace(f"Unable to perform XMC flash chip startup sequence ({e}).")
-
- if hasattr(args, "flash_size"):
- print("Configuring flash size...")
- detect_flash_size(esp, args)
- if args.flash_size != "keep": # TODO: should set this even with 'keep'
- esp.flash_set_parameters(flash_size_bytes(args.flash_size))
- # Check if stub supports chosen flash size
- if esp.IS_STUB and args.flash_size in ("32MB", "64MB", "128MB"):
- print(
- "WARNING: Flasher stub doesn't fully support flash size larger "
- "than 16MB, in case of failure use --no-stub."
- )
-
- if esp.IS_STUB and hasattr(args, "address") and hasattr(args, "size"):
- if 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."
- )
-
- try:
- operation_func(esp, args)
- finally:
- try: # Clean up AddrFilenamePairAction files
- for address, argfile in args.addr_filename:
- argfile.close()
- except AttributeError:
- pass
-
- # Handle post-operation behaviour (reset or other)
- if operation_func == load_ram:
- # the ESP is now running the loaded image, so let it run
- print("Exiting immediately.")
- elif args.after == "hard_reset":
- esp.hard_reset()
- elif args.after == "soft_reset":
- print("Soft resetting...")
- # flash_finish will trigger a soft reset
- esp.soft_reset(False)
- elif args.after == "no_reset_stub":
- print("Staying in flasher stub.")
- else: # args.after == 'no_reset'
- print("Staying in bootloader.")
- if esp.IS_STUB:
- esp.soft_reset(True) # exit stub back to ROM loader
-
- if not external_esp:
- esp._port.close()
-
- else:
- operation_func(args)
-
-
-def arg_auto_int(x):
- return int(x, 0)
-
-
-def get_port_list():
- if list_ports is None:
- raise FatalError(
- "Listing all serial ports is currently not available. "
- "Please try to specify the port when running esptool.py or update "
- "the pyserial package to the latest version"
- )
- return sorted(ports.device for ports in list_ports.comports())
-
-
-def expand_file_arguments(argv):
- """
- Any argument starting with "@" gets replaced with all values read from a text file.
- Text file arguments can be split by newline or by space.
- Values are added "as-is", as if they were specified in this order
- on the command line.
- """
- new_args = []
- expanded = False
- for arg in argv:
- if arg.startswith("@"):
- expanded = True
- with open(arg[1:], "r") as f:
- for line in f.readlines():
- new_args += shlex.split(line)
- else:
- new_args.append(arg)
- if expanded:
- print("esptool %s" % (" ".join(new_args[1:])))
- return new_args
- return argv
-
-
-def get_default_connected_device(
- serial_list,
- port,
- connect_attempts,
- initial_baud,
- chip="auto",
- trace=False,
- before="default_reset",
-):
- _esp = None
- for each_port in reversed(serial_list):
- print("Serial port %s" % each_port)
- try:
- if chip == "auto":
- _esp = detect_chip(
- each_port, initial_baud, before, trace, connect_attempts
- )
- else:
- chip_class = CHIP_DEFS[chip]
- _esp = chip_class(each_port, initial_baud, trace)
- _esp.connect(before, connect_attempts)
- break
- except (FatalError, OSError) as err:
- if port is not None:
- raise
- print("%s failed to connect: %s" % (each_port, err))
- if _esp and _esp._port:
- _esp._port.close()
- _esp = None
- return _esp
-
-
-class SpiConnectionAction(argparse.Action):
- """
- Custom action to parse 'spi connection' override.
- Values are SPI, HSPI, or a sequence of 5 pin numbers separated by commas.
- """
-
- def __call__(self, parser, namespace, value, option_string=None):
- if value.upper() == "SPI":
- value = 0
- elif value.upper() == "HSPI":
- value = 1
- 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,
- )
- 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,
- )
- 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,
- )
- setattr(namespace, self.dest, value)
-
-
-class AddrFilenamePairAction(argparse.Action):
- """Custom parser class for the address/filename pairs passed as arguments"""
-
- def __init__(self, option_strings, dest, nargs="+", **kwargs):
- super(AddrFilenamePairAction, self).__init__(
- option_strings, dest, nargs, **kwargs
- )
-
- def __call__(self, parser, namespace, values, option_string=None):
- # validate pair arguments
- pairs = []
- for i in range(0, len(values), 2):
- try:
- address = int(values[i], 0)
- except ValueError:
- raise argparse.ArgumentError(
- self, 'Address "%s" must be a number' % values[i]
- )
- try:
- argfile = open(values[i + 1], "rb")
- except IOError as e:
- raise argparse.ArgumentError(self, e)
- except IndexError:
- raise argparse.ArgumentError(
- self,
- "Must be pairs of an address "
- "and the binary filename to write there",
- )
- pairs.append((address, argfile))
-
- # Sort the addresses and check for overlapping
- end = 0
- for address, argfile in sorted(pairs, key=lambda x: x[0]):
- argfile.seek(0, 2) # seek to end
- size = argfile.tell()
- argfile.seek(0)
- sector_start = address & ~(ESPLoader.FLASH_SECTOR_SIZE - 1)
- sector_end = (
- (address + size + ESPLoader.FLASH_SECTOR_SIZE - 1)
- & ~(ESPLoader.FLASH_SECTOR_SIZE - 1)
- ) - 1
- if sector_start < end:
- message = "Detected overlap at address: 0x%x for file: %s" % (
- address,
- argfile.name,
- )
- raise argparse.ArgumentError(self, message)
- end = sector_end
- setattr(namespace, self.dest, pairs)
-
-
-def _main():
- try:
- main()
- except FatalError as e:
- print(f"\nA fatal error occurred: {e}")
- sys.exit(2)
- except serial.serialutil.SerialException as e:
- print(f"\nA serial exception error occurred: {e}")
- print(
- "Note: This error originates from pySerial. "
- "It is likely not a problem with esptool, "
- "but with the hardware connection or drivers."
- )
- print(
- "For troubleshooting steps visit: "
- "https://docs.espressif.com/projects/esptool/en/latest/troubleshooting.html"
- )
- sys.exit(1)
- except StopIteration:
- print(traceback.format_exc())
- print("A fatal error occurred: The chip stopped responding.")
- sys.exit(2)
-
-
-if __name__ == "__main__":
- _main()
diff --git a/installer/bin/esptool/esptool/__main__.py b/installer/bin/esptool/esptool/__main__.py
deleted file mode 100644
index 11e3bce..0000000
--- a/installer/bin/esptool/esptool/__main__.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# SPDX-FileCopyrightText: 2014-2022 Fredrik Ahlberg, Angus Gratton,
-# Espressif Systems (Shanghai) CO LTD, other contributors as noted.
-#
-# SPDX-License-Identifier: GPL-2.0-or-later
-
-import esptool
-
-if __name__ == "__main__":
- esptool._main()
diff --git a/installer/bin/esptool/esptool/bin_image.py b/installer/bin/esptool/esptool/bin_image.py
deleted file mode 100644
index b001a1e..0000000
--- a/installer/bin/esptool/esptool/bin_image.py
+++ /dev/null
@@ -1,1239 +0,0 @@
-# SPDX-FileCopyrightText: 2014-2022 Fredrik Ahlberg, Angus Gratton,
-# Espressif Systems (Shanghai) CO LTD, other contributors as noted.
-#
-# SPDX-License-Identifier: GPL-2.0-or-later
-
-import binascii
-import copy
-import hashlib
-import io
-import os
-import re
-import struct
-
-from .loader import ESPLoader
-from .targets import (
- ESP32C2ROM,
- ESP32C3ROM,
- ESP32C6BETAROM,
- ESP32C6ROM,
- ESP32H2BETA1ROM,
- ESP32H2BETA2ROM,
- ESP32H2ROM,
- ESP32ROM,
- ESP32S2ROM,
- ESP32S3BETA2ROM,
- ESP32S3ROM,
- ESP8266ROM,
-)
-from .util import FatalError, byte, pad_to
-
-
-def align_file_position(f, size):
- """Align the position in the file to the next block of specified size"""
- align = (size - 1) - (f.tell() % size)
- f.seek(align, 1)
-
-
-def LoadFirmwareImage(chip, image_file):
- """
- Load a firmware image. Can be for any supported SoC.
-
- ESP8266 images will be examined to determine if they are original ROM firmware
- images (ESP8266ROMFirmwareImage) or "v2" OTA bootloader images.
-
- Returns a BaseFirmwareImage subclass, either ESP8266ROMFirmwareImage (v1)
- or ESP8266V2FirmwareImage (v2).
- """
-
- def select_image_class(f, chip):
- chip = re.sub(r"[-()]", "", chip.lower())
- if chip != "esp8266":
- return {
- "esp32": ESP32FirmwareImage,
- "esp32s2": ESP32S2FirmwareImage,
- "esp32s3beta2": ESP32S3BETA2FirmwareImage,
- "esp32s3": ESP32S3FirmwareImage,
- "esp32c3": ESP32C3FirmwareImage,
- "esp32c6beta": ESP32C6BETAFirmwareImage,
- "esp32h2beta1": ESP32H2BETA1FirmwareImage,
- "esp32h2beta2": ESP32H2BETA2FirmwareImage,
- "esp32c2": ESP32C2FirmwareImage,
- "esp32c6": ESP32C6FirmwareImage,
- "esp32h2": ESP32H2FirmwareImage,
- }[chip](f)
- else: # Otherwise, ESP8266 so look at magic to determine the image type
- magic = ord(f.read(1))
- f.seek(0)
- if magic == ESPLoader.ESP_IMAGE_MAGIC:
- return ESP8266ROMFirmwareImage(f)
- elif magic == ESP8266V2FirmwareImage.IMAGE_V2_MAGIC:
- return ESP8266V2FirmwareImage(f)
- else:
- raise FatalError("Invalid image magic number: %d" % magic)
-
- if isinstance(image_file, str):
- with open(image_file, "rb") as f:
- return select_image_class(f, chip)
- return select_image_class(image_file, chip)
-
-
-class ImageSegment(object):
- """Wrapper class for a segment in an ESP image
- (very similar to a section in an ELFImage also)"""
-
- def __init__(self, addr, data, file_offs=None):
- self.addr = addr
- self.data = data
- self.file_offs = file_offs
- self.include_in_checksum = True
- if self.addr != 0:
- self.pad_to_alignment(
- 4
- ) # pad all "real" ImageSegments 4 byte aligned length
-
- def copy_with_new_addr(self, new_addr):
- """Return a new ImageSegment with same data, but mapped at
- a new address."""
- return ImageSegment(new_addr, self.data, 0)
-
- def split_image(self, split_len):
- """Return a new ImageSegment which splits "split_len" bytes
- from the beginning of the data. Remaining bytes are kept in
- this segment object (and the start address is adjusted to match.)"""
- result = copy.copy(self)
- result.data = self.data[:split_len]
- self.data = self.data[split_len:]
- self.addr += split_len
- self.file_offs = None
- result.file_offs = None
- return result
-
- def __repr__(self):
- r = "len 0x%05x load 0x%08x" % (len(self.data), self.addr)
- if self.file_offs is not None:
- r += " file_offs 0x%08x" % (self.file_offs)
- return r
-
- def get_memory_type(self, image):
- """
- Return a list describing the memory type(s) that is covered by this
- segment's start address.
- """
- return [
- map_range[2]
- for map_range in image.ROM_LOADER.MEMORY_MAP
- if map_range[0] <= self.addr < map_range[1]
- ]
-
- def pad_to_alignment(self, alignment):
- self.data = pad_to(self.data, alignment, b"\x00")
-
-
-class ELFSection(ImageSegment):
- """Wrapper class for a section in an ELF image, has a section
- name as well as the common properties of an ImageSegment."""
-
- def __init__(self, name, addr, data):
- super(ELFSection, self).__init__(addr, data)
- self.name = name.decode("utf-8")
-
- def __repr__(self):
- return "%s %s" % (self.name, super(ELFSection, self).__repr__())
-
-
-class BaseFirmwareImage(object):
- SEG_HEADER_LEN = 8
- SHA256_DIGEST_LEN = 32
-
- """ Base class with common firmware image functions """
-
- def __init__(self):
- self.segments = []
- self.entrypoint = 0
- self.elf_sha256 = None
- self.elf_sha256_offset = 0
- self.pad_to_size = 0
-
- def load_common_header(self, load_file, expected_magic):
- (
- magic,
- segments,
- self.flash_mode,
- self.flash_size_freq,
- self.entrypoint,
- ) = struct.unpack(" 16:
- raise FatalError(
- "Invalid segment count %d (max 16). "
- "Usually this indicates a linker script problem." % len(self.segments)
- )
-
- def load_segment(self, f, is_irom_segment=False):
- """Load the next segment from the image file"""
- file_offs = f.tell()
- (offset, size) = struct.unpack(" 0x40200000 or offset < 0x3FFE0000 or size > 65536:
- print("WARNING: Suspicious segment 0x%x, length %d" % (offset, size))
-
- def maybe_patch_segment_data(self, f, segment_data):
- """
- If SHA256 digest of the ELF file needs to be inserted into this segment, do so.
- Returns segment data.
- """
- segment_len = len(segment_data)
- file_pos = f.tell() # file_pos is position in the .bin file
- if (
- self.elf_sha256_offset >= file_pos
- and self.elf_sha256_offset < file_pos + segment_len
- ):
- # SHA256 digest needs to be patched into this binary segment,
- # calculate offset of the digest inside the binary segment.
- patch_offset = self.elf_sha256_offset - file_pos
- # Sanity checks
- if (
- patch_offset < self.SEG_HEADER_LEN
- or patch_offset + self.SHA256_DIGEST_LEN > segment_len
- ):
- raise FatalError(
- "Cannot place SHA256 digest on segment boundary"
- "(elf_sha256_offset=%d, file_pos=%d, segment_size=%d)"
- % (self.elf_sha256_offset, file_pos, segment_len)
- )
- # offset relative to the data part
- patch_offset -= self.SEG_HEADER_LEN
- if (
- segment_data[patch_offset : patch_offset + self.SHA256_DIGEST_LEN]
- != b"\x00" * self.SHA256_DIGEST_LEN
- ):
- raise FatalError(
- "Contents of segment at SHA256 digest offset 0x%x are not all zero."
- " Refusing to overwrite." % self.elf_sha256_offset
- )
- assert len(self.elf_sha256) == self.SHA256_DIGEST_LEN
- segment_data = (
- segment_data[0:patch_offset]
- + self.elf_sha256
- + segment_data[patch_offset + self.SHA256_DIGEST_LEN :]
- )
- return segment_data
-
- def save_segment(self, f, segment, checksum=None):
- """
- Save the next segment to the image file,
- return next checksum value if provided
- """
- segment_data = self.maybe_patch_segment_data(f, segment.data)
- f.write(struct.pack(" 0:
- if len(irom_segments) != 1:
- raise FatalError(
- "Found %d segments that could be irom0. Bad ELF file?"
- % len(irom_segments)
- )
- return irom_segments[0]
- return None
-
- def get_non_irom_segments(self):
- irom_segment = self.get_irom_segment()
- return [s for s in self.segments if s != irom_segment]
-
- def merge_adjacent_segments(self):
- if not self.segments:
- return # nothing to merge
-
- segments = []
- # The easiest way to merge the sections is the browse them backward.
- for i in range(len(self.segments) - 1, 0, -1):
- # elem is the previous section, the one `next_elem` may need to be
- # merged in
- elem = self.segments[i - 1]
- next_elem = self.segments[i]
- if all(
- (
- elem.get_memory_type(self) == next_elem.get_memory_type(self),
- elem.include_in_checksum == next_elem.include_in_checksum,
- next_elem.addr == elem.addr + len(elem.data),
- )
- ):
- # Merge any segment that ends where the next one starts,
- # without spanning memory types
- #
- # (don't 'pad' any gaps here as they may be excluded from the image
- # due to 'noinit' or other reasons.)
- elem.data += next_elem.data
- else:
- # The section next_elem cannot be merged into the previous one,
- # which means it needs to be part of the final segments.
- # As we are browsing the list backward, the elements need to be
- # inserted at the beginning of the final list.
- segments.insert(0, next_elem)
-
- # The first segment will always be here as it cannot be merged into any
- # "previous" section.
- segments.insert(0, self.segments[0])
-
- # note: we could sort segments here as well, but the ordering of segments is
- # sometimes important for other reasons (like embedded ELF SHA-256),
- # so we assume that the linker script will have produced any adjacent sections
- # in linear order in the ELF, anyhow.
- self.segments = segments
-
- def set_mmu_page_size(self, size):
- """
- If supported, this should be overridden by the chip-specific class.
- Gets called in elf2image.
- """
- print(
- "WARNING: Changing MMU page size is not supported on {}! "
- "Defaulting to 64KB.".format(self.ROM_LOADER.CHIP_NAME)
- )
-
-
-class ESP8266ROMFirmwareImage(BaseFirmwareImage):
- """'Version 1' firmware image, segments loaded directly by the ROM bootloader."""
-
- ROM_LOADER = ESP8266ROM
-
- def __init__(self, load_file=None):
- super(ESP8266ROMFirmwareImage, self).__init__()
- self.flash_mode = 0
- self.flash_size_freq = 0
- self.version = 1
-
- if load_file is not None:
- segments = self.load_common_header(load_file, ESPLoader.ESP_IMAGE_MAGIC)
-
- for _ in range(segments):
- self.load_segment(load_file)
- self.checksum = self.read_checksum(load_file)
-
- self.verify()
-
- def default_output_name(self, input_file):
- """Derive a default output name from the ELF name."""
- return input_file + "-"
-
- def save(self, basename):
- """Save a set of V1 images for flashing. Parameter is a base filename."""
- # IROM data goes in its own plain binary file
- irom_segment = self.get_irom_segment()
- if irom_segment is not None:
- with open(
- "%s0x%05x.bin"
- % (basename, irom_segment.addr - ESP8266ROM.IROM_MAP_START),
- "wb",
- ) as f:
- f.write(irom_segment.data)
-
- # everything but IROM goes at 0x00000 in an image file
- normal_segments = self.get_non_irom_segments()
- with open("%s0x00000.bin" % basename, "wb") as f:
- self.write_common_header(f, normal_segments)
- checksum = ESPLoader.ESP_CHECKSUM_MAGIC
- for segment in normal_segments:
- checksum = self.save_segment(f, segment, checksum)
- self.append_checksum(f, checksum)
-
-
-ESP8266ROM.BOOTLOADER_IMAGE = ESP8266ROMFirmwareImage
-
-
-class ESP8266V2FirmwareImage(BaseFirmwareImage):
- """'Version 2' firmware image, segments loaded by software bootloader stub
- (ie Espressif bootloader or rboot)
- """
-
- ROM_LOADER = ESP8266ROM
- # First byte of the "v2" application image
- IMAGE_V2_MAGIC = 0xEA
-
- # First 'segment' value in a "v2" application image,
- # appears to be a constant version value?
- IMAGE_V2_SEGMENT = 4
-
- def __init__(self, load_file=None):
- super(ESP8266V2FirmwareImage, self).__init__()
- self.version = 2
- if load_file is not None:
- segments = self.load_common_header(load_file, self.IMAGE_V2_MAGIC)
- if segments != self.IMAGE_V2_SEGMENT:
- # segment count is not really segment count here,
- # but we expect to see '4'
- print(
- 'Warning: V2 header has unexpected "segment" count %d (usually 4)'
- % segments
- )
-
- # irom segment comes before the second header
- #
- # the file is saved in the image with a zero load address
- # in the header, so we need to calculate a load address
- irom_segment = self.load_segment(load_file, True)
- # for actual mapped addr, add ESP8266ROM.IROM_MAP_START + flashing_addr + 8
- irom_segment.addr = 0
- irom_segment.include_in_checksum = False
-
- first_flash_mode = self.flash_mode
- first_flash_size_freq = self.flash_size_freq
- first_entrypoint = self.entrypoint
- # load the second header
-
- segments = self.load_common_header(load_file, ESPLoader.ESP_IMAGE_MAGIC)
-
- if first_flash_mode != self.flash_mode:
- print(
- "WARNING: Flash mode value in first header (0x%02x) disagrees "
- "with second (0x%02x). Using second value."
- % (first_flash_mode, self.flash_mode)
- )
- if first_flash_size_freq != self.flash_size_freq:
- print(
- "WARNING: Flash size/freq value in first header (0x%02x) disagrees "
- "with second (0x%02x). Using second value."
- % (first_flash_size_freq, self.flash_size_freq)
- )
- if first_entrypoint != self.entrypoint:
- print(
- "WARNING: Entrypoint address in first header (0x%08x) disagrees "
- "with second header (0x%08x). Using second value."
- % (first_entrypoint, self.entrypoint)
- )
-
- # load all the usual segments
- for _ in range(segments):
- self.load_segment(load_file)
- self.checksum = self.read_checksum(load_file)
-
- self.verify()
-
- def default_output_name(self, input_file):
- """Derive a default output name from the ELF name."""
- irom_segment = self.get_irom_segment()
- if irom_segment is not None:
- irom_offs = irom_segment.addr - ESP8266ROM.IROM_MAP_START
- else:
- irom_offs = 0
- return "%s-0x%05x.bin" % (
- os.path.splitext(input_file)[0],
- irom_offs & ~(ESPLoader.FLASH_SECTOR_SIZE - 1),
- )
-
- def save(self, filename):
- with open(filename, "wb") as f:
- # Save first header for irom0 segment
- f.write(
- struct.pack(
- b" 0:
- last_addr = flash_segments[0].addr
- for segment in flash_segments[1:]:
- if segment.addr // self.IROM_ALIGN == last_addr // self.IROM_ALIGN:
- raise FatalError(
- "Segment loaded at 0x%08x lands in same 64KB flash mapping "
- "as segment loaded at 0x%08x. Can't generate binary. "
- "Suggest changing linker script or ELF to merge sections."
- % (segment.addr, last_addr)
- )
- last_addr = segment.addr
-
- def get_alignment_data_needed(segment):
- # Actual alignment (in data bytes) required for a segment header:
- # positioned so that after we write the next 8 byte header,
- # file_offs % IROM_ALIGN == segment.addr % IROM_ALIGN
- #
- # (this is because the segment's vaddr may not be IROM_ALIGNed,
- # more likely is aligned IROM_ALIGN+0x18
- # to account for the binary file header
- align_past = (segment.addr % self.IROM_ALIGN) - self.SEG_HEADER_LEN
- pad_len = (self.IROM_ALIGN - (f.tell() % self.IROM_ALIGN)) + align_past
- if pad_len == 0 or pad_len == self.IROM_ALIGN:
- return 0 # already aligned
-
- # subtract SEG_HEADER_LEN a second time,
- # as the padding block has a header as well
- pad_len -= self.SEG_HEADER_LEN
- if pad_len < 0:
- 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)
- 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
-
- if self.secure_pad:
- # pad the image so that after signing it will end on a a 64KB boundary.
- # This ensures all mapped flash content will be verified.
- if not self.append_digest:
- raise FatalError(
- "secure_pad only applies if a SHA-256 digest "
- "is also appended to the image"
- )
- align_past = (f.tell() + self.SEG_HEADER_LEN) % self.IROM_ALIGN
- # 16 byte aligned checksum
- # (force the alignment to simplify calculations)
- checksum_space = 16
- if self.secure_pad == "1":
- # after checksum: SHA-256 digest +
- # (to be added by signing process) version,
- # signature + 12 trailing bytes due to alignment
- space_after_checksum = 32 + 4 + 64 + 12
- elif self.secure_pad == "2": # Secure Boot V2
- # after checksum: SHA-256 digest +
- # signature sector,
- # but we place signature sector after the 64KB boundary
- space_after_checksum = 32
- pad_len = (
- self.IROM_ALIGN - align_past - checksum_space - space_after_checksum
- ) % self.IROM_ALIGN
- pad_segment = ImageSegment(0, b"\x00" * pad_len, f.tell())
-
- checksum = self.save_segment(f, pad_segment, checksum)
- total_segments += 1
-
- # done writing segments
- self.append_checksum(f, checksum)
- image_length = f.tell()
-
- if self.secure_pad:
- assert ((image_length + space_after_checksum) % self.IROM_ALIGN) == 0
-
- # 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.append_digest:
- # calculate the SHA256 of the whole file and append it
- f.seek(0)
- digest = hashlib.sha256()
- digest.update(f.read(image_length))
- f.write(digest.digest())
-
- if self.pad_to_size:
- image_length = f.tell()
- if image_length % self.pad_to_size != 0:
- pad_by = self.pad_to_size - (image_length % self.pad_to_size)
- f.write(b"\xff" * pad_by)
-
- 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)
-
- fields = list(
- struct.unpack(self.EXTENDED_HEADER_STRUCT_FMT, load_file.read(16))
- )
-
- self.wp_pin = fields[0]
-
- # SPI pin drive stengths are two per byte
- self.clk_drv, self.q_drv = split_byte(fields[1])
- self.d_drv, self.cs_drv = split_byte(fields[2])
- self.hd_drv, self.wp_drv = split_byte(fields[3])
-
- self.chip_id = fields[4]
- if self.chip_id != self.ROM_LOADER.IMAGE_CHIP_ID:
- print(
- (
- "Unexpected chip id in image. Expected %d but value was %d. "
- "Is this image for a different chip model?"
- )
- % (self.ROM_LOADER.IMAGE_CHIP_ID, self.chip_id)
- )
-
- self.min_rev = fields[5]
- self.min_rev_full = fields[6]
- self.max_rev_full = fields[7]
-
- # reserved fields in the middle should all be zero
- if any(f for f in fields[8:-1] if f != 0):
- print(
- "Warning: some reserved header fields have non-zero values. "
- "This image may be from a newer esptool.py?"
- )
-
- append_digest = fields[-1] # last byte is append_digest
- if append_digest in [0, 1]:
- self.append_digest = append_digest == 1
- else:
- raise RuntimeError(
- "Invalid value for append_digest field (0x%02x). Should be 0 or 1.",
- append_digest,
- )
-
- def save_extended_header(self, save_file):
- def join_byte(ln, hn):
- return (ln & 0x0F) + ((hn & 0x0F) << 4)
-
- append_digest = 1 if self.append_digest else 0
-
- fields = [
- self.wp_pin,
- join_byte(self.clk_drv, self.q_drv),
- join_byte(self.d_drv, self.cs_drv),
- join_byte(self.hd_drv, self.wp_drv),
- self.ROM_LOADER.IMAGE_CHIP_ID,
- self.min_rev,
- self.min_rev_full,
- self.max_rev_full,
- ]
- fields += [0] * 4 # padding
- fields += [append_digest]
-
- packed = struct.pack(self.EXTENDED_HEADER_STRUCT_FMT, *fields)
- save_file.write(packed)
-
-
-class ESP8266V3FirmwareImage(ESP32FirmwareImage):
- """ESP8266 V3 firmware image is very similar to ESP32 image"""
-
- EXTENDED_HEADER_STRUCT_FMT = "B" * 16
-
- def is_flash_addr(self, addr):
- return addr > ESP8266ROM.IROM_MAP_START
-
- def save(self, filename):
- total_segments = 0
- with io.BytesIO() as f: # write file to memory first
- self.write_common_header(f, self.segments)
-
- checksum = ESPLoader.ESP_CHECKSUM_MAGIC
-
- # split segments into flash-mapped vs ram-loaded,
- # and take copies so we can mutate them
- flash_segments = [
- copy.deepcopy(s)
- for s in sorted(self.segments, key=lambda s: s.addr)
- if self.is_flash_addr(s.addr) and len(s.data)
- ]
- ram_segments = [
- copy.deepcopy(s)
- for s in sorted(self.segments, key=lambda s: s.addr)
- if not self.is_flash_addr(s.addr) and len(s.data)
- ]
-
- # check for multiple ELF sections that are mapped in the same
- # flash mapping region. This is usually a sign of a broken linker script,
- # but if you have a legitimate use case then let us know
- if len(flash_segments) > 0:
- last_addr = flash_segments[0].addr
- for segment in flash_segments[1:]:
- if segment.addr // self.IROM_ALIGN == last_addr // self.IROM_ALIGN:
- raise FatalError(
- "Segment loaded at 0x%08x lands in same 64KB flash mapping "
- "as segment loaded at 0x%08x. Can't generate binary. "
- "Suggest changing linker script or ELF to merge sections."
- % (segment.addr, last_addr)
- )
- last_addr = segment.addr
-
- # 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]
- # remove 8 bytes empty data for insert segment header
- if segment.name == ".flash.rodata":
- segment.data = segment.data[8:]
- # write the flash segment
- checksum = self.save_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
-
- # done writing segments
- self.append_checksum(f, checksum)
- image_length = f.tell()
-
- # 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.append_digest:
- # calculate the SHA256 of the whole file and append it
- f.seek(0)
- digest = hashlib.sha256()
- digest.update(f.read(image_length))
- f.write(digest.digest())
-
- with open(filename, "wb") as real_file:
- real_file.write(f.getvalue())
-
- def load_extended_header(self, load_file):
- def split_byte(n):
- return (n & 0x0F, (n >> 4) & 0x0F)
-
- fields = list(
- struct.unpack(self.EXTENDED_HEADER_STRUCT_FMT, load_file.read(16))
- )
-
- self.wp_pin = fields[0]
-
- # SPI pin drive stengths are two per byte
- self.clk_drv, self.q_drv = split_byte(fields[1])
- self.d_drv, self.cs_drv = split_byte(fields[2])
- self.hd_drv, self.wp_drv = split_byte(fields[3])
-
- if fields[15] in [0, 1]:
- self.append_digest = fields[15] == 1
- else:
- raise RuntimeError(
- "Invalid value for append_digest field (0x%02x). Should be 0 or 1.",
- fields[15],
- )
-
- # remaining fields in the middle should all be zero
- if any(f for f in fields[4:15] if f != 0):
- print(
- "Warning: some reserved header fields have non-zero values. "
- "This image may be from a newer esptool.py?"
- )
-
-
-ESP32ROM.BOOTLOADER_IMAGE = ESP32FirmwareImage
-
-
-class ESP32S2FirmwareImage(ESP32FirmwareImage):
- """ESP32S2 Firmware Image almost exactly the same as ESP32FirmwareImage"""
-
- ROM_LOADER = ESP32S2ROM
-
-
-ESP32S2ROM.BOOTLOADER_IMAGE = ESP32S2FirmwareImage
-
-
-class ESP32S3BETA2FirmwareImage(ESP32FirmwareImage):
- """ESP32S3 Firmware Image almost exactly the same as ESP32FirmwareImage"""
-
- ROM_LOADER = ESP32S3BETA2ROM
-
-
-ESP32S3BETA2ROM.BOOTLOADER_IMAGE = ESP32S3BETA2FirmwareImage
-
-
-class ESP32S3FirmwareImage(ESP32FirmwareImage):
- """ESP32S3 Firmware Image almost exactly the same as ESP32FirmwareImage"""
-
- ROM_LOADER = ESP32S3ROM
-
-
-ESP32S3ROM.BOOTLOADER_IMAGE = ESP32S3FirmwareImage
-
-
-class ESP32C3FirmwareImage(ESP32FirmwareImage):
- """ESP32C3 Firmware Image almost exactly the same as ESP32FirmwareImage"""
-
- ROM_LOADER = ESP32C3ROM
-
-
-ESP32C3ROM.BOOTLOADER_IMAGE = ESP32C3FirmwareImage
-
-
-class ESP32C6BETAFirmwareImage(ESP32FirmwareImage):
- """ESP32C6 Firmware Image almost exactly the same as ESP32FirmwareImage"""
-
- ROM_LOADER = ESP32C6BETAROM
-
-
-ESP32C6BETAROM.BOOTLOADER_IMAGE = ESP32C6BETAFirmwareImage
-
-
-class ESP32H2BETA1FirmwareImage(ESP32FirmwareImage):
- """ESP32H2 Firmware Image almost exactly the same as ESP32FirmwareImage"""
-
- ROM_LOADER = ESP32H2BETA1ROM
-
-
-ESP32H2BETA1ROM.BOOTLOADER_IMAGE = ESP32H2BETA1FirmwareImage
-
-
-class ESP32H2BETA2FirmwareImage(ESP32FirmwareImage):
- """ESP32H2 Firmware Image almost exactly the same as ESP32FirmwareImage"""
-
- ROM_LOADER = ESP32H2BETA2ROM
-
-
-ESP32H2BETA2ROM.BOOTLOADER_IMAGE = ESP32H2BETA2FirmwareImage
-
-
-class ESP32C2FirmwareImage(ESP32FirmwareImage):
- """ESP32C2 Firmware Image almost exactly the same as ESP32FirmwareImage"""
-
- ROM_LOADER = ESP32C2ROM
-
- def set_mmu_page_size(self, size):
- if size not in [16384, 32768, 65536]:
- raise FatalError(
- "{} bytes is not a valid ESP32-C2 page size, "
- "select from 64KB, 32KB, 16KB.".format(size)
- )
- self.IROM_ALIGN = size
-
-
-ESP32C2ROM.BOOTLOADER_IMAGE = ESP32C2FirmwareImage
-
-
-class ESP32C6FirmwareImage(ESP32FirmwareImage):
- """ESP32C6 Firmware Image almost exactly the same as ESP32FirmwareImage"""
-
- ROM_LOADER = ESP32C6ROM
-
- def set_mmu_page_size(self, size):
- if size not in [8192, 16384, 32768, 65536]:
- raise FatalError(
- "{} bytes is not a valid ESP32-C6 page size, "
- "select from 64KB, 32KB, 16KB, 8KB.".format(size)
- )
- self.IROM_ALIGN = size
-
-
-ESP32C6ROM.BOOTLOADER_IMAGE = ESP32C6FirmwareImage
-
-
-class ESP32H2FirmwareImage(ESP32C6FirmwareImage):
- """ESP32H2 Firmware Image almost exactly the same as ESP32FirmwareImage"""
-
- ROM_LOADER = ESP32H2ROM
-
-
-ESP32H2ROM.BOOTLOADER_IMAGE = ESP32H2FirmwareImage
-
-
-class ELFFile(object):
- SEC_TYPE_PROGBITS = 0x01
- SEC_TYPE_STRTAB = 0x03
- SEC_TYPE_INITARRAY = 0x0E
- SEC_TYPE_FINIARRAY = 0x0F
-
- PROG_SEC_TYPES = (SEC_TYPE_PROGBITS, SEC_TYPE_INITARRAY, SEC_TYPE_FINIARRAY)
-
- LEN_SEC_HEADER = 0x28
-
- SEG_TYPE_LOAD = 0x01
- LEN_SEG_HEADER = 0x20
-
- def __init__(self, name):
- # Load sections from the ELF file
- self.name = name
- with open(self.name, "rb") as f:
- self._read_elf_file(f)
-
- def get_section(self, section_name):
- for s in self.sections:
- if s.name == section_name:
- return s
- raise ValueError("No section %s in ELF file" % section_name)
-
- def _read_elf_file(self, f):
- # read the ELF file header
- LEN_FILE_HEADER = 0x34
- try:
- (
- ident,
- _type,
- machine,
- _version,
- self.entrypoint,
- _phoff,
- shoff,
- _flags,
- _ehsize,
- _phentsize,
- _phnum,
- shentsize,
- shnum,
- shstrndx,
- ) = struct.unpack("<16sHHLLLLLHHHHHH", f.read(LEN_FILE_HEADER))
- except struct.error as e:
- raise FatalError(
- "Failed to read a valid ELF header from %s: %s" % (self.name, e)
- )
-
- if byte(ident, 0) != 0x7F or ident[1:4] != b"ELF":
- raise FatalError("%s has invalid ELF magic header" % self.name)
- if machine not in [0x5E, 0xF3]:
- raise FatalError(
- "%s does not appear to be an Xtensa or an RISCV ELF file. "
- "e_machine=%04x" % (self.name, machine)
- )
- if shentsize != self.LEN_SEC_HEADER:
- raise FatalError(
- "%s has unexpected section header entry size 0x%x (not 0x%x)"
- % (self.name, shentsize, self.LEN_SEC_HEADER)
- )
- if shnum == 0:
- raise FatalError("%s has 0 section headers" % (self.name))
- self._read_sections(f, shoff, shnum, shstrndx)
- self._read_segments(f, _phoff, _phnum, shstrndx)
-
- def _read_sections(self, f, section_header_offs, section_header_count, shstrndx):
- f.seek(section_header_offs)
- len_bytes = section_header_count * self.LEN_SEC_HEADER
- section_header = f.read(len_bytes)
- if len(section_header) == 0:
- raise FatalError(
- "No section header found at offset %04x in ELF file."
- % section_header_offs
- )
- if len(section_header) != (len_bytes):
- raise FatalError(
- "Only read 0x%x bytes from section header (expected 0x%x.) "
- "Truncated ELF file?" % (len(section_header), len_bytes)
- )
-
- # walk through the section header and extract all sections
- section_header_offsets = range(0, len(section_header), self.LEN_SEC_HEADER)
-
- def read_section_header(offs):
- name_offs, sec_type, _flags, lma, sec_offs, size = struct.unpack_from(
- " 0
- ]
- self.sections = prog_sections
-
- def _read_segments(self, f, segment_header_offs, segment_header_count, shstrndx):
- f.seek(segment_header_offs)
- len_bytes = segment_header_count * self.LEN_SEG_HEADER
- segment_header = f.read(len_bytes)
- if len(segment_header) == 0:
- raise FatalError(
- "No segment header found at offset %04x in ELF file."
- % segment_header_offs
- )
- if len(segment_header) != (len_bytes):
- raise FatalError(
- "Only read 0x%x bytes from segment header (expected 0x%x.) "
- "Truncated ELF file?" % (len(segment_header), len_bytes)
- )
-
- # walk through the segment header and extract all segments
- segment_header_offsets = range(0, len(segment_header), self.LEN_SEG_HEADER)
-
- def read_segment_header(offs):
- (
- seg_type,
- seg_offs,
- _vaddr,
- lma,
- size,
- _memsize,
- _flags,
- _align,
- ) = struct.unpack_from(" 0
- ]
- self.segments = prog_segments
-
- def sha256(self):
- # return SHA256 hash of the input ELF file
- sha256 = hashlib.sha256()
- with open(self.name, "rb") as f:
- sha256.update(f.read())
- return sha256.digest()
diff --git a/installer/bin/esptool/esptool/cmds.py b/installer/bin/esptool/esptool/cmds.py
deleted file mode 100644
index a299058..0000000
--- a/installer/bin/esptool/esptool/cmds.py
+++ /dev/null
@@ -1,1198 +0,0 @@
-# SPDX-FileCopyrightText: 2014-2022 Fredrik Ahlberg, Angus Gratton,
-# Espressif Systems (Shanghai) CO LTD, other contributors as noted.
-#
-# SPDX-License-Identifier: GPL-2.0-or-later
-
-import hashlib
-import io
-import os
-import struct
-import sys
-import time
-import zlib
-
-from .bin_image import ELFFile, ImageSegment, LoadFirmwareImage
-from .bin_image import (
- ESP8266ROMFirmwareImage,
- ESP8266V2FirmwareImage,
- ESP8266V3FirmwareImage,
-)
-from .loader import (
- DEFAULT_CONNECT_ATTEMPTS,
- DEFAULT_TIMEOUT,
- ERASE_WRITE_TIMEOUT_PER_MB,
- ESPLoader,
- timeout_per_mb,
-)
-from .targets import CHIP_DEFS, CHIP_LIST, ROM_LIST
-from .util import (
- FatalError,
- NotImplementedInROMError,
- NotSupportedError,
- UnsupportedCommandError,
-)
-from .util import (
- div_roundup,
- flash_size_bytes,
- hexify,
- pad_to,
- print_overwrite,
-)
-
-DETECTED_FLASH_SIZES = {
- 0x12: "256KB",
- 0x13: "512KB",
- 0x14: "1MB",
- 0x15: "2MB",
- 0x16: "4MB",
- 0x17: "8MB",
- 0x18: "16MB",
- 0x19: "32MB",
- 0x1A: "64MB",
- 0x1B: "128MB",
- 0x1C: "256MB",
- 0x20: "64MB",
- 0x21: "128MB",
- 0x22: "256MB",
- 0x32: "256KB",
- 0x33: "512KB",
- 0x34: "1MB",
- 0x35: "2MB",
- 0x36: "4MB",
- 0x37: "8MB",
- 0x38: "16MB",
- 0x39: "32MB",
- 0x3A: "64MB",
-}
-
-FLASH_MODES = {"qio": 0, "qout": 1, "dio": 2, "dout": 3}
-
-
-def detect_chip(
- port=ESPLoader.DEFAULT_PORT,
- baud=ESPLoader.ESP_ROM_BAUD,
- connect_mode="default_reset",
- trace_enabled=False,
- connect_attempts=DEFAULT_CONNECT_ATTEMPTS,
-):
- """Use serial access to detect the chip type.
-
- First, get_security_info command is sent to detect the ID of the chip
- (supported only by ESP32-C3 and later, works even in the Secure Download Mode).
- If this fails, we reconnect and fall-back to reading the magic number.
- It's mapped at a specific ROM address and has a different value on each chip model.
- This way we use one memory read and compare it to the magic number for each chip.
-
- This routine automatically performs ESPLoader.connect() (passing
- connect_mode parameter) as part of querying the chip.
- """
- inst = None
- detect_port = ESPLoader(port, baud, trace_enabled=trace_enabled)
- if detect_port.serial_port.startswith("rfc2217:"):
- detect_port.USES_RFC2217 = True
- detect_port.connect(connect_mode, connect_attempts, detecting=True)
- try:
- 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")
- ]:
- # cmd not supported on ESP8266 and ESP32 + ESP32-S2 doesn't return chip_id
- if chip_id == cls.IMAGE_CHIP_ID:
- inst = cls(detect_port._port, baud, trace_enabled=trace_enabled)
- try:
- inst.read_reg(
- ESPLoader.CHIP_DETECT_MAGIC_REG_ADDR
- ) # Dummy read to check Secure Download mode
- except UnsupportedCommandError:
- inst.secure_download_mode = True
- inst._post_connect()
- break
- else:
- err_msg = f"Unexpected chip ID value {chip_id}."
- except (UnsupportedCommandError, struct.error, FatalError) as e:
- # UnsupportedCommmanddError: ESP8266/ESP32 ROM
- # struct.error: ESP32-S2
- # FatalError: ESP8266/ESP32 STUB
- print(" Unsupported detection protocol, switching and trying again...")
- try:
- # ESP32/ESP8266 are reset after an unsupported command, need to reconnect
- # (not needed on ESP32-S2)
- if not isinstance(e, struct.error):
- detect_port.connect(
- connect_mode, connect_attempts, detecting=True, warnings=False
- )
- print("Detecting chip type...", end="")
- sys.stdout.flush()
- chip_magic_value = detect_port.read_reg(
- ESPLoader.CHIP_DETECT_MAGIC_REG_ADDR
- )
-
- for cls in ROM_LIST:
- if chip_magic_value in cls.CHIP_DETECT_MAGIC_VALUE:
- inst = cls(detect_port._port, baud, trace_enabled=trace_enabled)
- inst._post_connect()
- inst.check_chip_id()
- break
- else:
- err_msg = f"Unexpected chip magic value {chip_magic_value:#010x}."
- except UnsupportedCommandError:
- raise FatalError(
- "Unsupported Command Error received. "
- "Probably this means Secure Download Mode is enabled, "
- "autodetection will not work. Need to manually specify the chip."
- )
- finally:
- if inst is not None:
- print(" %s" % inst.CHIP_NAME, end="")
- if detect_port.sync_stub_detected:
- inst = inst.STUB_CLASS(inst)
- inst.sync_stub_detected = True
- print("") # end line
- return inst
- raise FatalError(
- f"{err_msg} Failed to autodetect chip type."
- "\nProbably it is unsupported by this version of esptool."
- )
-
-
-# "Operation" commands, executable at command line. One function each
-#
-# Each function takes either two args (, ) or a single
-# argument.
-
-
-def load_ram(esp, args):
- image = LoadFirmwareImage(esp.CHIP_NAME, args.filename)
-
- print("RAM boot...")
- for seg in image.segments:
- size = len(seg.data)
- print("Downloading %d bytes at %08x..." % (size, seg.addr), end=" ")
- sys.stdout.flush()
- esp.mem_begin(
- size, div_roundup(size, esp.ESP_RAM_BLOCK), esp.ESP_RAM_BLOCK, seg.addr
- )
-
- seq = 0
- while len(seg.data) > 0:
- esp.mem_block(seg.data[0 : esp.ESP_RAM_BLOCK], seq)
- seg.data = seg.data[esp.ESP_RAM_BLOCK :]
- seq += 1
- print("done!")
-
- print("All segments done, executing at %08x" % image.entrypoint)
- esp.mem_finish(image.entrypoint)
-
-
-def read_mem(esp, args):
- print("0x%08x = 0x%08x" % (args.address, esp.read_reg(args.address)))
-
-
-def write_mem(esp, args):
- esp.write_reg(args.address, args.value, args.mask, 0)
- print("Wrote %08x, mask %08x to %08x" % (args.value, args.mask, args.address))
-
-
-def dump_mem(esp, args):
- with open(args.filename, "wb") as f:
- for i in range(args.size // 4):
- d = esp.read_reg(args.address + (i * 4))
- f.write(struct.pack(b"> 16
- args.flash_size = DETECTED_FLASH_SIZES.get(size_id)
- if args.flash_size is None:
- print(
- "Warning: Could not auto-detect Flash size (FlashID=0x%x, SizeID=0x%x),"
- " defaulting to 4MB" % (flash_id, size_id)
- )
- args.flash_size = "4MB"
- else:
- print("Auto-detected Flash size:", args.flash_size)
-
-
-def _update_image_flash_params(esp, address, args, image):
- """
- Modify the flash mode & size bytes if this looks like an executable bootloader image
- """
- if len(image) < 8:
- return image # not long enough to be a bootloader image
-
- # unpack the (potential) image header
- magic, _, flash_mode, flash_size_freq = struct.unpack("BBBB", image[:4])
- if address != esp.BOOTLOADER_FLASH_OFFSET:
- return image # not flashing bootloader offset, so don't modify this
-
- if (args.flash_mode, args.flash_freq, args.flash_size) == ("keep",) * 3:
- return image # all settings are 'keep', not modifying anything
-
- # easy check if this is an image: does it start with a magic byte?
- if magic != esp.ESP_IMAGE_MAGIC:
- print(
- "Warning: Image file at 0x%x doesn't look like an image file, "
- "so not changing any flash settings." % address
- )
- return image
-
- # make sure this really is an image, and not just data that
- # starts with esp.ESP_IMAGE_MAGIC (mostly a problem for encrypted
- # images that happen to start with a magic byte
- try:
- test_image = esp.BOOTLOADER_IMAGE(io.BytesIO(image))
- test_image.verify()
- except Exception:
- print(
- "Warning: Image file at 0x%x is not a valid %s image, "
- "so not changing any flash settings." % (address, esp.CHIP_NAME)
- )
- return image
-
- # After the 8-byte header comes the extended header for chips others than ESP8266.
- # The 15th byte of the extended header indicates if the image is protected by
- # a SHA256 checksum. In that case we should not modify the header because
- # the checksum check would fail.
- sha_implies_keep = args.chip != "esp8266" and image[8 + 15] == 1
-
- def print_keep_warning(arg_to_keep, arg_used):
- print(
- "Warning: Image file at {addr} is protected with a hash checksum, "
- "so not changing the flash {arg} setting. "
- "Use the --flash_{arg}=keep option instead of --flash_{arg}={arg_orig} "
- "in order to remove this warning, or use the --dont-append-digest option "
- "for the elf2image command in order to generate an image file "
- "without a hash checksum".format(
- addr=hex(address), arg=arg_to_keep, arg_orig=arg_used
- )
- )
-
- if args.flash_mode != "keep":
- new_flash_mode = FLASH_MODES[args.flash_mode]
- if flash_mode != new_flash_mode and sha_implies_keep:
- print_keep_warning("mode", args.flash_mode)
- else:
- flash_mode = new_flash_mode
-
- flash_freq = flash_size_freq & 0x0F
- if args.flash_freq != "keep":
- new_flash_freq = esp.parse_flash_freq_arg(args.flash_freq)
- if flash_freq != new_flash_freq and sha_implies_keep:
- print_keep_warning("frequency", args.flash_freq)
- else:
- flash_freq = new_flash_freq
-
- flash_size = flash_size_freq & 0xF0
- if args.flash_size != "keep":
- new_flash_size = esp.parse_flash_size_arg(args.flash_size)
- if flash_size != new_flash_size and sha_implies_keep:
- print_keep_warning("size", args.flash_size)
- else:
- flash_size = new_flash_size
-
- flash_params = struct.pack(b"BB", flash_mode, flash_size + flash_freq)
- if flash_params != image[2:4]:
- print("Flash params set to 0x%04x" % struct.unpack(">H", flash_params))
- image = image[0:2] + flash_params + image[4:]
- return image
-
-
-def write_flash(esp, args):
- # set args.compress based on default behaviour:
- # -> if either --compress or --no-compress is set, honour that
- # -> otherwise, set --compress unless --no-stub is set
- if args.compress is None and not args.no_compress:
- args.compress = not args.no_stub
-
- if not args.force and esp.CHIP_NAME != "ESP8266" and not esp.secure_download_mode:
- # Check if secure boot is active
- if esp.get_secure_boot_enabled():
- for address, _ in args.addr_filename:
- if address < 0x8000:
- raise FatalError(
- "Secure Boot detected, writing to flash regions < 0x8000 "
- "is disabled to protect the bootloader. "
- "Use --force to override, "
- "please use with caution, otherwise it may brick your device!"
- )
- # Check if chip_id and min_rev in image are valid for the target in use
- for _, argfile in args.addr_filename:
- try:
- image = LoadFirmwareImage(esp.CHIP_NAME, argfile)
- except (FatalError, struct.error, RuntimeError):
- continue
- finally:
- argfile.seek(0) # LoadFirmwareImage changes the file handle position
- if image.chip_id != esp.IMAGE_CHIP_ID:
- raise FatalError(
- f"{argfile.name} is not an {esp.CHIP_NAME} image. "
- "Use --force to flash anyway."
- )
-
- # this logic below decides which min_rev to use, min_rev or min/max_rev_full
- if image.max_rev_full == 0: # image does not have max/min_rev_full fields
- use_rev_full_fields = False
- elif image.max_rev_full == 65535: # image has default value of max_rev_full
- use_rev_full_fields = True
- if (
- image.min_rev_full == 0 and image.min_rev != 0
- ): # min_rev_full is not set, min_rev is used
- use_rev_full_fields = False
- else: # max_rev_full set to a version
- use_rev_full_fields = True
-
- if use_rev_full_fields:
- rev = esp.get_chip_revision()
- if rev < image.min_rev_full or rev > image.max_rev_full:
- error_str = f"{argfile.name} requires chip revision in range "
- error_str += (
- f"[v{image.min_rev_full // 100}.{image.min_rev_full % 100} - "
- )
- if image.max_rev_full == 65535:
- error_str += "max rev not set] "
- else:
- error_str += (
- f"v{image.max_rev_full // 100}.{image.max_rev_full % 100}] "
- )
- error_str += f"(this chip is revision v{rev // 100}.{rev % 100})"
- raise FatalError(f"{error_str}. Use --force to flash anyway.")
- else:
- # In IDF, image.min_rev is set based on Kconfig option.
- # For C3 chip, image.min_rev is the Minor revision
- # while for the rest chips it is the Major revision.
- if esp.CHIP_NAME == "ESP32-C3":
- rev = esp.get_minor_chip_version()
- else:
- rev = esp.get_major_chip_version()
- if rev < image.min_rev:
- raise FatalError(
- f"{argfile.name} requires chip revision "
- f"{image.min_rev} or higher (this chip is revision {rev}). "
- "Use --force to flash anyway."
- )
-
- # In case we have encrypted files to write,
- # we first do few sanity checks before actual flash
- if args.encrypt or args.encrypt_files is not None:
- do_write = True
-
- if not esp.secure_download_mode:
- if esp.get_encrypted_download_disabled():
- raise FatalError(
- "This chip has encrypt functionality "
- "in UART download mode disabled. "
- "This is the Flash Encryption configuration for Production mode "
- "instead of Development mode."
- )
-
- crypt_cfg_efuse = esp.get_flash_crypt_config()
-
- if crypt_cfg_efuse is not None and crypt_cfg_efuse != 0xF:
- print("Unexpected FLASH_CRYPT_CONFIG value: 0x%x" % (crypt_cfg_efuse))
- do_write = False
-
- enc_key_valid = esp.is_flash_encryption_key_valid()
-
- if not enc_key_valid:
- print("Flash encryption key is not programmed")
- do_write = False
-
- # Determine which files list contain the ones to encrypt
- files_to_encrypt = args.addr_filename if args.encrypt else args.encrypt_files
-
- for address, argfile in files_to_encrypt:
- if address % esp.FLASH_ENCRYPTED_WRITE_ALIGN:
- print(
- "File %s address 0x%x is not %d byte aligned, can't flash encrypted"
- % (argfile.name, address, esp.FLASH_ENCRYPTED_WRITE_ALIGN)
- )
- do_write = False
-
- if not do_write and not args.ignore_flash_encryption_efuse_setting:
- raise FatalError(
- "Can't perform encrypted flash write, "
- "consult Flash Encryption documentation for more information"
- )
- else:
- if not args.force and esp.CHIP_NAME != "ESP8266":
- # ESP32 does not support `get_security_info()` and `secure_download_mode`
- if (
- esp.CHIP_NAME != "ESP32"
- and esp.secure_download_mode
- and bin(esp.get_security_info()["flash_crypt_cnt"]).count("1") & 1 != 0
- ):
- raise FatalError(
- "WARNING: Detected flash encryption and "
- "secure download mode enabled.\n"
- "Flashing plaintext binary may brick your device! "
- "Use --force to override the warning."
- )
-
- if (
- not esp.secure_download_mode
- and esp.get_encrypted_download_disabled()
- and esp.get_flash_encryption_enabled()
- ):
- raise FatalError(
- "WARNING: Detected flash encryption enabled and "
- "download manual encrypt disabled.\n"
- "Flashing plaintext binary may brick your device! "
- "Use --force to override the warning."
- )
-
- # verify file sizes fit in flash
- if args.flash_size != "keep": # TODO: check this even with 'keep'
- flash_end = flash_size_bytes(args.flash_size)
- for address, argfile in args.addr_filename:
- argfile.seek(0, os.SEEK_END)
- if address + argfile.tell() > flash_end:
- raise FatalError(
- "File %s (length %d) at offset %d "
- "will not fit in %d bytes of flash. "
- "Use --flash_size argument, or change flashing address."
- % (argfile.name, argfile.tell(), address, flash_end)
- )
- argfile.seek(0)
-
- if args.erase_all:
- erase_flash(esp, args)
- else:
- for address, argfile in args.addr_filename:
- argfile.seek(0, os.SEEK_END)
- write_end = address + argfile.tell()
- argfile.seek(0)
- bytes_over = address % esp.FLASH_SECTOR_SIZE
- if bytes_over != 0:
- print(
- "WARNING: Flash address {:#010x} is not aligned "
- "to a {:#x} byte flash sector. "
- "{:#x} bytes before this address will be erased.".format(
- address, esp.FLASH_SECTOR_SIZE, bytes_over
- )
- )
- # Print the address range of to-be-erased flash memory region
- print(
- "Flash will be erased from {:#010x} to {:#010x}...".format(
- address - bytes_over,
- div_roundup(write_end, esp.FLASH_SECTOR_SIZE)
- * esp.FLASH_SECTOR_SIZE
- - 1,
- )
- )
-
- """ Create a list describing all the files we have to flash.
- Each entry holds an "encrypt" flag marking whether the file needs encryption or not.
- This list needs to be sorted.
-
- First, append to each entry of our addr_filename list the flag args.encrypt
- E.g., if addr_filename is [(0x1000, "partition.bin"), (0x8000, "bootloader")],
- all_files will be [
- (0x1000, "partition.bin", args.encrypt),
- (0x8000, "bootloader", args.encrypt)
- ],
- where, of course, args.encrypt is either True or False
- """
- all_files = [
- (offs, filename, args.encrypt) for (offs, filename) in args.addr_filename
- ]
-
- """
- Now do the same with encrypt_files list, if defined.
- In this case, the flag is True
- """
- if args.encrypt_files is not None:
- encrypted_files_flag = [
- (offs, filename, True) for (offs, filename) in args.encrypt_files
- ]
-
- # Concatenate both lists and sort them.
- # As both list are already sorted, we could simply do a merge instead,
- # but for the sake of simplicity and because the lists are very small,
- # let's use sorted.
- all_files = sorted(all_files + encrypted_files_flag, key=lambda x: x[0])
-
- for address, argfile, encrypted in all_files:
- compress = args.compress
-
- # Check whether we can compress the current file before flashing
- if compress and encrypted:
- print("\nWARNING: - compress and encrypt options are mutually exclusive ")
- print("Will flash %s uncompressed" % argfile.name)
- compress = False
-
- if args.no_stub:
- print("Erasing flash...")
- image = pad_to(
- argfile.read(), esp.FLASH_ENCRYPTED_WRITE_ALIGN if encrypted else 4
- )
- if len(image) == 0:
- print("WARNING: File %s is empty" % argfile.name)
- continue
- image = _update_image_flash_params(esp, address, args, image)
- calcmd5 = hashlib.md5(image).hexdigest()
- uncsize = len(image)
- if compress:
- uncimage = image
- image = zlib.compress(uncimage, 9)
- # Decompress the compressed binary a block at a time,
- # to dynamically calculate the timeout based on the real write size
- decompress = zlib.decompressobj()
- blocks = esp.flash_defl_begin(uncsize, len(image), address)
- else:
- blocks = esp.flash_begin(uncsize, address, begin_rom_encrypted=encrypted)
- argfile.seek(0) # in case we need it again
- seq = 0
- bytes_sent = 0 # bytes sent on wire
- bytes_written = 0 # bytes written to flash
- t = time.time()
-
- timeout = DEFAULT_TIMEOUT
-
- while len(image) > 0:
- print_overwrite(
- "Writing at 0x%08x... (%d %%)"
- % (address + bytes_written, 100 * (seq + 1) // blocks)
- )
- sys.stdout.flush()
- block = image[0 : esp.FLASH_WRITE_SIZE]
- if compress:
- # feeding each compressed block into the decompressor lets us
- # see block-by-block how much will be written
- block_uncompressed = len(decompress.decompress(block))
- bytes_written += block_uncompressed
- block_timeout = max(
- DEFAULT_TIMEOUT,
- timeout_per_mb(ERASE_WRITE_TIMEOUT_PER_MB, block_uncompressed),
- )
- if not esp.IS_STUB:
- timeout = (
- block_timeout # ROM code writes block to flash before ACKing
- )
- esp.flash_defl_block(block, seq, timeout=timeout)
- if esp.IS_STUB:
- # Stub ACKs when block is received,
- # then writes to flash while receiving the block after it
- timeout = block_timeout
- else:
- # Pad the last block
- block = block + b"\xff" * (esp.FLASH_WRITE_SIZE - len(block))
- if encrypted:
- esp.flash_encrypt_block(block, seq)
- else:
- esp.flash_block(block, seq)
- bytes_written += len(block)
- bytes_sent += len(block)
- image = image[esp.FLASH_WRITE_SIZE :]
- seq += 1
-
- if esp.IS_STUB:
- # Stub only writes each block to flash after 'ack'ing the receive,
- # so do a final dummy operation which will not be 'ack'ed
- # until the last block has actually been written out to flash
- esp.read_reg(ESPLoader.CHIP_DETECT_MAGIC_REG_ADDR, timeout=timeout)
-
- t = time.time() - t
- speed_msg = ""
- if compress:
- if t > 0.0:
- speed_msg = " (effective %.1f kbit/s)" % (uncsize / t * 8 / 1000)
- print_overwrite(
- "Wrote %d bytes (%d compressed) at 0x%08x in %.1f seconds%s..."
- % (uncsize, bytes_sent, address, t, speed_msg),
- last_line=True,
- )
- else:
- if t > 0.0:
- speed_msg = " (%.1f kbit/s)" % (bytes_written / t * 8 / 1000)
- print_overwrite(
- "Wrote %d bytes at 0x%08x in %.1f seconds%s..."
- % (bytes_written, address, t, speed_msg),
- last_line=True,
- )
-
- if not encrypted and not esp.secure_download_mode:
- try:
- res = esp.flash_md5sum(address, uncsize)
- if res != calcmd5:
- print("File md5: %s" % calcmd5)
- print("Flash md5: %s" % res)
- print(
- "MD5 of 0xFF is %s"
- % (hashlib.md5(b"\xFF" * uncsize).hexdigest())
- )
- raise FatalError("MD5 of file does not match data in flash!")
- else:
- print("Hash of data verified.")
- except NotImplementedInROMError:
- pass
-
- print("\nLeaving...")
-
- if esp.IS_STUB:
- # skip sending flash_finish to ROM loader here,
- # as it causes the loader to exit and run user code
- esp.flash_begin(0, 0)
-
- # Get the "encrypted" flag for the last file flashed
- # Note: all_files list contains triplets like:
- # (address: Integer, filename: String, encrypted: Boolean)
- last_file_encrypted = all_files[-1][2]
-
- # Check whether the last file flashed was compressed or not
- if args.compress and not last_file_encrypted:
- esp.flash_defl_finish(False)
- else:
- esp.flash_finish(False)
-
- if args.verify:
- print("Verifying just-written flash...")
- print(
- "(This option is deprecated, "
- "flash contents are now always read back after flashing.)"
- )
- # If some encrypted files have been flashed,
- # print a warning saying that we won't check them
- if args.encrypt or args.encrypt_files is not None:
- print("WARNING: - cannot verify encrypted files, they will be ignored")
- # Call verify_flash function only if there is at least
- # one non-encrypted file flashed
- if not args.encrypt:
- verify_flash(esp, args)
-
-
-def image_info(args):
- def v2():
- def get_key_from_value(dict, val):
- """Get key from value in dictionary"""
- for key, value in dict.items():
- if value == val:
- return key
- return None
-
- print()
- title = "{} image header".format(args.chip.upper())
- print(title)
- print("=" * len(title))
- print("Image version: {}".format(image.version))
- print(
- "Entry point: {:#8x}".format(image.entrypoint)
- if image.entrypoint != 0
- else "Entry point not set"
- )
-
- print("Segments: {}".format(len(image.segments)))
-
- # Flash size
- flash_s_bits = image.flash_size_freq & 0xF0 # high four bits
- flash_s = get_key_from_value(image.ROM_LOADER.FLASH_SIZES, flash_s_bits)
- print(
- "Flash size: {}".format(flash_s)
- if flash_s is not None
- else "WARNING: Invalid flash size ({:#02x})".format(flash_s_bits)
- )
-
- # Flash frequency
- flash_fr_bits = image.flash_size_freq & 0x0F # low four bits
- flash_fr = get_key_from_value(image.ROM_LOADER.FLASH_FREQUENCY, flash_fr_bits)
- print(
- "Flash freq: {}".format(flash_fr)
- if flash_fr is not None
- else "WARNING: Invalid flash frequency ({:#02x})".format(flash_fr_bits)
- )
-
- # Flash mode
- flash_mode = get_key_from_value(FLASH_MODES, image.flash_mode)
- print(
- "Flash mode: {}".format(flash_mode.upper())
- if flash_mode is not None
- else "WARNING: Invalid flash mode ({})".format(image.flash_mode)
- )
-
- # Extended header (ESP32 and later only)
- if args.chip != "esp8266":
- print()
- title = "{} extended image header".format(args.chip.upper())
- print(title)
- print("=" * len(title))
- print("WP pin: {:#02x}".format(image.wp_pin))
- print(
- "Flash pins drive settings: "
- "clk_drv: {:#02x}, q_drv: {:#02x}, d_drv: {:#02x}, "
- "cs0_drv: {:#02x}, hd_drv: {:#02x}, wp_drv: {:#02x}".format(
- image.clk_drv,
- image.q_drv,
- image.d_drv,
- image.cs_drv,
- image.hd_drv,
- image.wp_drv,
- )
- )
- print("Chip ID: {}".format(image.chip_id))
- print(
- "Minimal chip revision: "
- f"v{image.min_rev_full // 100}.{image.min_rev_full % 100}, "
- f"(legacy min_rev = {image.min_rev})"
- )
- print(
- "Maximal chip revision: "
- f"v{image.max_rev_full // 100}.{image.max_rev_full % 100}"
- )
- print()
-
- # Segments overview
- title = "Segments information"
- print(title)
- print("=" * len(title))
- headers_str = "{:>7} {:>7} {:>10} {:>10} {:10}"
- print(
- headers_str.format(
- "Segment", "Length", "Load addr", "File offs", "Memory types"
- )
- )
- print(
- "{} {} {} {} {}".format("-" * 7, "-" * 7, "-" * 10, "-" * 10, "-" * 12)
- )
- format_str = "{:7} {:#07x} {:#010x} {:#010x} {}"
- app_desc = None
- for idx, seg in enumerate(image.segments, start=1):
- segs = seg.get_memory_type(image)
- seg_name = ", ".join(segs)
- if "DROM" in segs: # The DROM segment starts with the esp_app_desc_t struct
- app_desc = seg.data[:256]
- print(
- format_str.format(idx, len(seg.data), seg.addr, seg.file_offs, seg_name)
- )
- print()
-
- # Footer
- title = f"{args.chip.upper()} image footer"
- print(title)
- print("=" * len(title))
- calc_checksum = image.calculate_checksum()
- print(
- "Checksum: {:#02x} ({})".format(
- image.checksum,
- "valid"
- if image.checksum == calc_checksum
- else "invalid - calculated {:02x}".format(calc_checksum),
- )
- )
- try:
- digest_msg = "Not appended"
- if image.append_digest:
- is_valid = image.stored_digest == image.calc_digest
- digest_msg = "{} ({})".format(
- hexify(image.calc_digest, uppercase=False),
- "valid" if is_valid else "invalid",
- )
- print("Validation hash: {}".format(digest_msg))
- except AttributeError:
- pass # ESP8266 image has no append_digest field
-
- if app_desc:
- APP_DESC_STRUCT_FMT = " 1 else ""))
-
- image.verify()
-
- if args.output is None:
- args.output = image.default_output_name(args.input)
- image.save(args.output)
-
- print("Successfully created {} image.".format(args.chip))
-
-
-def read_mac(esp, args):
- mac = esp.read_mac()
-
- def print_mac(label, mac):
- print("%s: %s" % (label, ":".join(map(lambda x: "%02x" % x, mac))))
-
- print_mac("MAC", mac)
-
-
-def chip_id(esp, args):
- try:
- chipid = esp.chip_id()
- print("Chip ID: 0x%08x" % chipid)
- except NotSupportedError:
- print("Warning: %s has no Chip ID. Reading MAC instead." % esp.CHIP_NAME)
- read_mac(esp, args)
-
-
-def erase_flash(esp, args):
- if not args.force and esp.CHIP_NAME != "ESP8266" and not esp.secure_download_mode:
- if esp.get_flash_encryption_enabled() or esp.get_secure_boot_enabled():
- raise FatalError(
- "Active security features detected, "
- "erasing flash is disabled as a safety measure. "
- "Use --force to override, "
- "please use with caution, otherwise it may brick your device!"
- )
- print("Erasing flash (this may take a while)...")
- t = time.time()
- esp.erase_flash()
- print("Chip erase completed successfully in %.1fs" % (time.time() - t))
-
-
-def erase_region(esp, args):
- if not args.force and esp.CHIP_NAME != "ESP8266" and not esp.secure_download_mode:
- if esp.get_flash_encryption_enabled() or esp.get_secure_boot_enabled():
- raise FatalError(
- "Active security features detected, "
- "erasing flash is disabled as a safety measure. "
- "Use --force to override, "
- "please use with caution, otherwise it may brick your device!"
- )
- print("Erasing region (may be slow depending on size)...")
- t = time.time()
- esp.erase_region(args.address, args.size)
- print("Erase completed successfully in %.1f seconds." % (time.time() - t))
-
-
-def run(esp, args):
- esp.run()
-
-
-def flash_id(esp, args):
- flash_id = esp.flash_id()
- print("Manufacturer: %02x" % (flash_id & 0xFF))
- flid_lowbyte = (flash_id >> 16) & 0xFF
- print("Device: %02x%02x" % ((flash_id >> 8) & 0xFF, flid_lowbyte))
- print(
- "Detected flash size: %s" % (DETECTED_FLASH_SIZES.get(flid_lowbyte, "Unknown"))
- )
- flash_type = esp.flash_type()
- flash_type_dict = {0: "quad (4 data lines)", 1: "octal (8 data lines)"}
- flash_type_str = flash_type_dict.get(flash_type)
- if flash_type_str:
- print(f"Flash type set in eFuse: {flash_type_str}")
-
-
-def read_flash(esp, args):
- if args.no_progress:
- flash_progress = None
- else:
-
- def flash_progress(progress, length):
- msg = "%d (%d %%)" % (progress, progress * 100.0 / length)
- padding = "\b" * len(msg)
- if progress == length:
- padding = "\n"
- sys.stdout.write(msg + padding)
- sys.stdout.flush()
-
- t = time.time()
- data = esp.read_flash(args.address, args.size, flash_progress)
- t = time.time() - t
- speed_msg = " ({:.1f} kbit/s)".format(len(data) / t * 8 / 1000) if t > 0.0 else ""
- print_overwrite(
- "Read {:d} bytes at {:#010x} in {:.1f} seconds{}...".format(
- len(data), args.address, t, speed_msg
- ),
- last_line=True,
- )
- with open(args.filename, "wb") as f:
- f.write(data)
-
-
-def verify_flash(esp, args):
- differences = False
-
- for address, argfile in args.addr_filename:
- image = pad_to(argfile.read(), 4)
- argfile.seek(0) # rewind in case we need it again
-
- image = _update_image_flash_params(esp, address, args, image)
-
- image_size = len(image)
- print(
- "Verifying 0x%x (%d) bytes @ 0x%08x in flash against %s..."
- % (image_size, image_size, address, argfile.name)
- )
- # Try digest first, only read if there are differences.
- digest = esp.flash_md5sum(address, image_size)
- expected_digest = hashlib.md5(image).hexdigest()
- if digest == expected_digest:
- print("-- verify OK (digest matched)")
- continue
- else:
- differences = True
- if getattr(args, "diff", "no") != "yes":
- print("-- verify FAILED (digest mismatch)")
- continue
-
- flash = esp.read_flash(address, image_size)
- assert flash != image
- diff = [i for i in range(image_size) if flash[i] != image[i]]
- print(
- "-- verify FAILED: %d differences, first @ 0x%08x"
- % (len(diff), address + diff[0])
- )
- for d in diff:
- flash_byte = flash[d]
- image_byte = image[d]
- print(" %08x %02x %02x" % (address + d, flash_byte, image_byte))
- if differences:
- raise FatalError("Verify failed.")
-
-
-def read_flash_status(esp, args):
- print("Status value: 0x%04x" % esp.read_status(args.bytes))
-
-
-def write_flash_status(esp, args):
- fmt = "0x%%0%dx" % (args.bytes * 2)
- args.value = args.value & ((1 << (args.bytes * 8)) - 1)
- print(("Initial flash status: " + fmt) % esp.read_status(args.bytes))
- print(("Setting flash status: " + fmt) % args.value)
- esp.write_status(args.value, args.bytes, args.non_volatile)
- print(("After flash status: " + fmt) % esp.read_status(args.bytes))
-
-
-def get_security_info(esp, args):
- si = esp.get_security_info()
- # TODO: better display
- 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"]))
- 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"]))
-
-
-def merge_bin(args):
- try:
- chip_class = CHIP_DEFS[args.chip]
- except KeyError:
- msg = (
- "Please specify the chip argument"
- if args.chip == "auto"
- else "Invalid chip choice: '{}'".format(args.chip)
- )
- msg = msg + " (choose from {})".format(", ".join(CHIP_LIST))
- raise FatalError(msg)
-
- # sort the files by offset.
- # The AddrFilenamePairAction has already checked for overlap
- input_files = sorted(args.addr_filename, key=lambda x: x[0])
- if not input_files:
- raise FatalError("No input files specified")
- 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)
- )
-
- if args.format != "raw":
- raise FatalError(
- "This version of esptool only supports the 'raw' output format"
- )
-
- 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()))
-
- 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(
- "Wrote 0x%x bytes to file %s, ready to flash to offset 0x%x"
- % (of.tell(), args.output, args.target_offset)
- )
-
-
-def version(args):
- from . import __version__
-
- print(__version__)
diff --git a/installer/bin/esptool/esptool/config.py b/installer/bin/esptool/esptool/config.py
deleted file mode 100644
index 5566bec..0000000
--- a/installer/bin/esptool/esptool/config.py
+++ /dev/null
@@ -1,92 +0,0 @@
-# SPDX-FileCopyrightText: 2014-2023 Espressif Systems (Shanghai) CO LTD,
-# other contributors as noted.
-#
-# SPDX-License-Identifier: GPL-2.0-or-later
-
-import configparser
-import os
-
-CONFIG_OPTIONS = [
- "timeout",
- "chip_erase_timeout",
- "max_timeout",
- "sync_timeout",
- "md5_timeout_per_mb",
- "erase_region_timeout_per_mb",
- "erase_write_timeout_per_mb",
- "mem_end_rom_timeout",
- "serial_write_timeout",
- "connect_attempts",
- "write_block_attempts",
- "reset_delay",
- "custom_reset_sequence",
-]
-
-
-def _validate_config_file(file_path, verbose=False):
- if not os.path.exists(file_path):
- return False
-
- cfg = configparser.RawConfigParser()
- try:
- cfg.read(file_path, encoding="UTF-8")
- # Only consider it a valid config file if it contains [esptool] section
- if cfg.has_section("esptool"):
- if verbose:
- unknown_opts = list(set(cfg.options("esptool")) - set(CONFIG_OPTIONS))
- unknown_opts.sort()
- no_of_unknown_opts = len(unknown_opts)
- if no_of_unknown_opts > 0:
- suffix = "s" if no_of_unknown_opts > 1 else ""
- print(
- "Ignoring unknown config file option{}: {}".format(
- suffix, ", ".join(unknown_opts)
- )
- )
- return True
- except (UnicodeDecodeError, configparser.Error) as e:
- if verbose:
- print(f"Ignoring invalid config file {file_path}: {e}")
- return False
-
-
-def _find_config_file(dir_path, verbose=False):
- for candidate in ("esptool.cfg", "setup.cfg", "tox.ini"):
- cfg_path = os.path.join(dir_path, candidate)
- if _validate_config_file(cfg_path, verbose):
- return cfg_path
- return None
-
-
-def load_config_file(verbose=False):
- set_with_env_var = False
- env_var_path = os.environ.get("ESPTOOL_CFGFILE")
- if env_var_path is not None and _validate_config_file(env_var_path):
- cfg_file_path = env_var_path
- set_with_env_var = True
- else:
- home_dir = os.path.expanduser("~")
- os_config_dir = (
- f"{home_dir}/.config/esptool"
- if os.name == "posix"
- else f"{home_dir}/AppData/Local/esptool/"
- )
- # Search priority: 1) current dir, 2) OS specific config dir, 3) home dir
- for dir_path in (os.getcwd(), os_config_dir, home_dir):
- cfg_file_path = _find_config_file(dir_path, verbose)
- if cfg_file_path:
- break
-
- cfg = configparser.ConfigParser()
- cfg["esptool"] = {} # Create an empty esptool config for when no file is found
-
- if cfg_file_path is not None:
- # If config file is found and validated, read and parse it
- cfg.read(cfg_file_path)
- if verbose:
- msg = " (set with ESPTOOL_CFGFILE)" if set_with_env_var else ""
- print(
- f"Loaded custom configuration from "
- f"{os.path.abspath(cfg_file_path)}{msg}"
- )
- return cfg, cfg_file_path
diff --git a/installer/bin/esptool/esptool/loader.py b/installer/bin/esptool/esptool/loader.py
deleted file mode 100644
index eb64023..0000000
--- a/installer/bin/esptool/esptool/loader.py
+++ /dev/null
@@ -1,1608 +0,0 @@
-# SPDX-FileCopyrightText: 2014-2023 Fredrik Ahlberg, Angus Gratton,
-# Espressif Systems (Shanghai) CO LTD, other contributors as noted.
-#
-# SPDX-License-Identifier: GPL-2.0-or-later
-
-import base64
-import hashlib
-import itertools
-import json
-import os
-import re
-import string
-import struct
-import sys
-import time
-
-from .config import load_config_file
-from .reset import (
- ClassicReset,
- CustomReset,
- DEFAULT_RESET_DELAY,
- HardReset,
- USBJTAGSerialReset,
- UnixTightReset,
-)
-from .util import FatalError, NotImplementedInROMError, UnsupportedCommandError
-from .util import byte, hexify, mask_to_shift, pad_to, strip_chip_name
-
-try:
- import serial
-except ImportError:
- print(
- "Pyserial is not installed for %s. "
- "Check the README for installation instructions." % (sys.executable)
- )
- raise
-
-# check 'serial' is 'pyserial' and not 'serial'
-# ref. https://github.com/espressif/esptool/issues/269
-try:
- if "serialization" in serial.__doc__ and "deserialization" in serial.__doc__:
- raise ImportError(
- "esptool.py depends on pyserial, but there is a conflict with a currently "
- "installed package named 'serial'.\n"
- "You may work around this by 'pip uninstall serial; pip install pyserial' "
- "but this may break other installed Python software "
- "that depends on 'serial'.\n"
- "There is no good fix for this right now, "
- "apart from configuring virtualenvs. "
- "See https://github.com/espressif/esptool/issues/269#issuecomment-385298196"
- " for discussion of the underlying issue(s)."
- )
-except TypeError:
- pass # __doc__ returns None for pyserial
-
-try:
- import serial.tools.list_ports as list_ports
-except ImportError:
- print(
- "The installed version (%s) of pyserial appears to be too old for esptool.py "
- "(Python interpreter %s). Check the README for installation instructions."
- % (sys.VERSION, sys.executable)
- )
- raise
-except Exception:
- if sys.platform == "darwin":
- # swallow the exception, this is a known issue in pyserial+macOS Big Sur preview
- # ref https://github.com/espressif/esptool/issues/540
- list_ports = None
- else:
- raise
-
-
-cfg, _ = load_config_file()
-cfg = cfg["esptool"]
-
-# Timeout for most flash operations
-DEFAULT_TIMEOUT = cfg.getfloat("timeout", 3)
-# Timeout for full chip erase
-CHIP_ERASE_TIMEOUT = cfg.getfloat("chip_erase_timeout", 120)
-# Longest any command can run
-MAX_TIMEOUT = cfg.getfloat("max_timeout", CHIP_ERASE_TIMEOUT * 2)
-# Timeout for syncing with bootloader
-SYNC_TIMEOUT = cfg.getfloat("sync_timeout", 0.1)
-# Timeout (per megabyte) for calculating md5sum
-MD5_TIMEOUT_PER_MB = cfg.getfloat("md5_timeout_per_mb", 8)
-# Timeout (per megabyte) for erasing a region
-ERASE_REGION_TIMEOUT_PER_MB = cfg.getfloat("erase_region_timeout_per_mb", 30)
-# Timeout (per megabyte) for erasing and writing data
-ERASE_WRITE_TIMEOUT_PER_MB = cfg.getfloat("erase_write_timeout_per_mb", 40)
-# Short timeout for ESP_MEM_END, as it may never respond
-MEM_END_ROM_TIMEOUT = cfg.getfloat("mem_end_rom_timeout", 0.2)
-# Timeout for serial port write
-DEFAULT_SERIAL_WRITE_TIMEOUT = cfg.getfloat("serial_write_timeout", 10)
-# Default number of times to try connection
-DEFAULT_CONNECT_ATTEMPTS = cfg.getint("connect_attempts", 7)
-# Number of times to try writing a data block
-WRITE_BLOCK_ATTEMPTS = cfg.getint("write_block_attempts", 3)
-
-STUBS_DIR = os.path.join(os.path.dirname(__file__), "./targets/stub_flasher/")
-
-
-def get_stub_json_path(chip_name):
- chip_name = strip_chip_name(chip_name)
- chip_name = chip_name.replace("esp", "")
- return STUBS_DIR + "stub_flasher_" + chip_name + ".json"
-
-
-def timeout_per_mb(seconds_per_mb, size_bytes):
- """Scales timeouts which are size-specific"""
- result = seconds_per_mb * (size_bytes / 1e6)
- if result < DEFAULT_TIMEOUT:
- return DEFAULT_TIMEOUT
- return result
-
-
-def check_supported_function(func, check_func):
- """
- Decorator implementation that wraps a check around an ESPLoader
- bootloader function to check if it's supported.
-
- This is used to capture the multidimensional differences in
- functionality between the ESP8266 & ESP32 (and later chips) ROM loaders, and the
- software stub that runs on these. Not possible to do this cleanly
- via inheritance alone.
- """
-
- def inner(*args, **kwargs):
- obj = args[0]
- if check_func(obj):
- return func(*args, **kwargs)
- else:
- raise NotImplementedInROMError(obj, func)
-
- return inner
-
-
-def stub_function_only(func):
- """Attribute for a function only supported in the software stub loader"""
- return check_supported_function(func, lambda o: o.IS_STUB)
-
-
-def stub_and_esp32_function_only(func):
- """Attribute for a function only supported by stubs or ESP32 and later chips ROM"""
- return check_supported_function(
- func, lambda o: o.IS_STUB or o.CHIP_NAME not in ["ESP8266"]
- )
-
-
-def esp32s3_or_newer_function_only(func):
- """Attribute for a function only supported by ESP32S3 and later chips ROM"""
- return check_supported_function(
- func, lambda o: o.CHIP_NAME not in ["ESP8266", "ESP32", "ESP32-S2"]
- )
-
-
-class StubFlasher:
- def __init__(self, json_path):
- with open(json_path) as json_file:
- stub = json.load(json_file)
-
- self.text = base64.b64decode(stub["text"])
- self.text_start = stub["text_start"]
- self.entry = stub["entry"]
-
- try:
- self.data = base64.b64decode(stub["data"])
- self.data_start = stub["data_start"]
- except KeyError:
- self.data = None
- self.data_start = None
-
-
-class ESPLoader(object):
- """Base class providing access to ESP ROM & software stub bootloaders.
- Subclasses provide ESP8266 & ESP32 Family specific functionality.
-
- Don't instantiate this base class directly, either instantiate a subclass or
- call cmds.detect_chip() which will interrogate the chip and return the
- appropriate subclass instance.
-
- """
-
- CHIP_NAME = "Espressif device"
- IS_STUB = False
-
- FPGA_SLOW_BOOT = False
-
- DEFAULT_PORT = "/dev/ttyUSB0"
-
- USES_RFC2217 = False
-
- # Commands supported by ESP8266 ROM bootloader
- ESP_FLASH_BEGIN = 0x02
- ESP_FLASH_DATA = 0x03
- ESP_FLASH_END = 0x04
- ESP_MEM_BEGIN = 0x05
- ESP_MEM_END = 0x06
- ESP_MEM_DATA = 0x07
- ESP_SYNC = 0x08
- ESP_WRITE_REG = 0x09
- ESP_READ_REG = 0x0A
-
- # Some comands supported by ESP32 and later chips ROM bootloader (or -8266 w/ stub)
- ESP_SPI_SET_PARAMS = 0x0B
- ESP_SPI_ATTACH = 0x0D
- ESP_READ_FLASH_SLOW = 0x0E # ROM only, much slower than the stub flash read
- ESP_CHANGE_BAUDRATE = 0x0F
- ESP_FLASH_DEFL_BEGIN = 0x10
- ESP_FLASH_DEFL_DATA = 0x11
- ESP_FLASH_DEFL_END = 0x12
- ESP_SPI_FLASH_MD5 = 0x13
-
- # Commands supported by ESP32-S2 and later chips ROM bootloader only
- ESP_GET_SECURITY_INFO = 0x14
-
- # Some commands supported by stub only
- ESP_ERASE_FLASH = 0xD0
- ESP_ERASE_REGION = 0xD1
- ESP_READ_FLASH = 0xD2
- ESP_RUN_USER_CODE = 0xD3
-
- # Flash encryption encrypted data command
- ESP_FLASH_ENCRYPT_DATA = 0xD4
-
- # Response code(s) sent by ROM
- ROM_INVALID_RECV_MSG = 0x05 # response if an invalid message is received
-
- # Maximum block sized for RAM and Flash writes, respectively.
- ESP_RAM_BLOCK = 0x1800
-
- FLASH_WRITE_SIZE = 0x400
-
- # Default baudrate. The ROM auto-bauds, so we can use more or less whatever we want.
- ESP_ROM_BAUD = 115200
-
- # First byte of the application image
- ESP_IMAGE_MAGIC = 0xE9
-
- # Initial state for the checksum routine
- ESP_CHECKSUM_MAGIC = 0xEF
-
- # Flash sector size, minimum unit of erase.
- FLASH_SECTOR_SIZE = 0x1000
-
- UART_DATE_REG_ADDR = 0x60000078
-
- # This ROM address has a different value on each chip model
- CHIP_DETECT_MAGIC_REG_ADDR = 0x40001000
-
- UART_CLKDIV_MASK = 0xFFFFF
-
- # Memory addresses
- IROM_MAP_START = 0x40200000
- IROM_MAP_END = 0x40300000
-
- # The number of bytes in the UART response that signify command status
- STATUS_BYTES_LENGTH = 2
-
- # Bootloader flashing offset
- BOOTLOADER_FLASH_OFFSET = 0x0
-
- # ROM supports an encrypted flashing mode
- SUPPORTS_ENCRYPTED_FLASH = False
-
- # Response to ESP_SYNC might indicate that flasher stub is running
- # instead of the ROM bootloader
- sync_stub_detected = False
-
- # Device PIDs
- USB_JTAG_SERIAL_PID = 0x1001
-
- # Chip IDs that are no longer supported by esptool
- UNSUPPORTED_CHIPS = {6: "ESP32-S3(beta 3)"}
-
- def __init__(self, port=DEFAULT_PORT, baud=ESP_ROM_BAUD, trace_enabled=False):
- """Base constructor for ESPLoader bootloader interaction
-
- Don't call this constructor, either instantiate a specific
- ROM class directly, or use cmds.detect_chip().
-
- This base class has all of the instance methods for bootloader
- functionality supported across various chips & stub
- loaders. Subclasses replace the functions they don't support
- with ones which throw NotImplementedInROMError().
-
- """
- # True if esptool detects the ROM is in Secure Download Mode
- self.secure_download_mode = False
- # True if esptool detects conditions which require the stub to be disabled
- self.stub_is_disabled = False
-
- # Device-and-runtime-specific cache
- self.cache = {
- "flash_id": None,
- "chip_id": None,
- "uart_no": None,
- }
-
- 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")
- else:
- self._port = port
- self._slip_reader = slip_reader(self._port, self.trace)
- # setting baud rate in a separate step is a workaround for
- # CH341 driver on some Linux versions (this opens at 9600 then
- # sets), shouldn't matter for other platforms/drivers. See
- # https://github.com/espressif/esptool/issues/44#issuecomment-107094446
- self._set_port_baudrate(baud)
- self._trace_enabled = trace_enabled
- # set write timeout, to prevent esptool blocked at write forever.
- try:
- self._port.write_timeout = DEFAULT_SERIAL_WRITE_TIMEOUT
- except NotImplementedError:
- # no write timeout for RFC2217 ports
- # need to set the property back to None or it will continue to fail
- self._port.write_timeout = None
-
- @property
- def serial_port(self):
- return self._port.port
-
- def _set_port_baudrate(self, baud):
- try:
- self._port.baudrate = baud
- except IOError:
- raise FatalError(
- "Failed to set baud rate %d. The driver may not support this rate."
- % baud
- )
-
- def read(self):
- """Read a SLIP packet from the serial port"""
- return next(self._slip_reader)
-
- def write(self, packet):
- """Write bytes to the serial port while performing SLIP escaping"""
- buf = (
- b"\xc0"
- + (packet.replace(b"\xdb", b"\xdb\xdd").replace(b"\xc0", b"\xdb\xdc"))
- + b"\xc0"
- )
- self.trace("Write %d bytes: %s", len(buf), HexFormatter(buf))
- self._port.write(buf)
-
- def trace(self, message, *format_args):
- if self._trace_enabled:
- now = time.time()
- try:
- delta = now - self._last_trace
- except AttributeError:
- delta = 0.0
- self._last_trace = now
- prefix = "TRACE +%.3f " % delta
- print(prefix + (message % format_args))
-
- @staticmethod
- def checksum(data, state=ESP_CHECKSUM_MAGIC):
- """Calculate checksum of a blob, as it is defined by the ROM"""
- for b in data:
- state ^= b
-
- return state
-
- def command(
- self,
- op=None,
- data=b"",
- chk=0,
- wait_response=True,
- timeout=DEFAULT_TIMEOUT,
- ):
- """Send a request and read the response"""
- saved_timeout = self._port.timeout
- new_timeout = min(timeout, MAX_TIMEOUT)
- if new_timeout != saved_timeout:
- self._port.timeout = new_timeout
-
- try:
- if op is not None:
- self.trace(
- "command op=0x%02x data len=%s wait_response=%d "
- "timeout=%.3f data=%s",
- op,
- len(data),
- 1 if wait_response else 0,
- timeout,
- HexFormatter(data),
- )
- pkt = struct.pack(b" self.STATUS_BYTES_LENGTH:
- return data[: -self.STATUS_BYTES_LENGTH]
- else:
- # otherwise, just return the 'val' field which comes from the reply header
- # (this is used by read_reg)
- return val
-
- def flush_input(self):
- self._port.flushInput()
- self._slip_reader = slip_reader(self._port, self.trace)
-
- def sync(self):
- val, _ = self.command(
- self.ESP_SYNC, b"\x07\x07\x12\x20" + 32 * b"\x55", timeout=SYNC_TIMEOUT
- )
-
- # ROM bootloaders send some non-zero "val" response. The flasher stub sends 0.
- # If we receive 0 then it probably indicates that the chip wasn't or couldn't be
- # reseted properly and esptool is talking to the flasher stub.
- self.sync_stub_detected = val == 0
-
- for _ in range(7):
- val, _ = self.command()
- self.sync_stub_detected &= val == 0
-
- def _get_pid(self):
- if list_ports is None:
- print(
- "\nListing all serial ports is currently not available. "
- "Can't get device PID."
- )
- return
- active_port = self._port.port
-
- # Pyserial only identifies regular ports, URL handlers are not supported
- if not active_port.lower().startswith(("com", "/dev/")):
- print(
- "\nDevice PID identification is only supported on "
- "COM and /dev/ serial ports."
- )
- return
- # Return the real path if the active port is a symlink
- if active_port.startswith("/dev/") and os.path.islink(active_port):
- active_port = os.path.realpath(active_port)
-
- # The "cu" (call-up) device has to be used for outgoing communication on MacOS
- if sys.platform == "darwin" and "tty" in active_port:
- active_port = [active_port, active_port.replace("tty", "cu")]
- ports = list_ports.comports()
- for p in ports:
- if p.device in active_port:
- return p.pid
- print(
- "\nFailed to get PID of a device on {}, "
- "using standard reset sequence.".format(active_port)
- )
-
- def _connect_attempt(self, reset_strategy, mode="default_reset"):
- """A single connection attempt"""
- last_error = None
- boot_log_detected = False
- download_mode = False
-
- # If we're doing no_sync, we're likely communicating as a pass through
- # with an intermediate device to the ESP32
- if mode == "no_reset_no_sync":
- return last_error
-
- if mode != "no_reset":
- if not self.USES_RFC2217: # Might block on rfc2217 ports
- # Empty serial buffer to isolate boot log
- self._port.reset_input_buffer()
-
- reset_strategy() # Reset the chip to bootloader (download mode)
-
- # Detect the ROM boot log and check actual boot mode (ESP32 and later only)
- waiting = self._port.inWaiting()
- read_bytes = self._port.read(waiting)
- data = re.search(
- b"boot:(0x[0-9a-fA-F]+)(.*waiting for download)?", read_bytes, re.DOTALL
- )
- if data is not None:
- boot_log_detected = True
- boot_mode = data.group(1)
- download_mode = data.group(2) is not None
-
- for _ in range(5):
- try:
- self.flush_input()
- self._port.flushOutput()
- self.sync()
- return None
- except FatalError as e:
- print(".", end="")
- sys.stdout.flush()
- time.sleep(0.05)
- last_error = e
-
- if boot_log_detected:
- last_error = FatalError(
- "Wrong boot mode detected ({})! "
- "The chip needs to be in download mode.".format(
- boot_mode.decode("utf-8")
- )
- )
- if download_mode:
- last_error = FatalError(
- "Download mode successfully detected, but getting no sync reply: "
- "The serial TX path seems to be down."
- )
- return last_error
-
- def get_memory_region(self, name):
- """
- Returns a tuple of (start, end) for the memory map entry with the given name,
- or None if it doesn't exist
- """
- try:
- return [(start, end) for (start, end, n) in self.MEMORY_MAP if n == name][0]
- except IndexError:
- return None
-
- def _construct_reset_strategy_sequence(self, mode):
- """
- Constructs a sequence of reset strategies based on the OS,
- used ESP chip, external settings, and environment variables.
- Returns a tuple of one or more reset strategies to be tried sequentially.
- """
- cfg_custom_reset_sequence = cfg.get("custom_reset_sequence")
- if cfg_custom_reset_sequence is not None:
- return (CustomReset(self._port, cfg_custom_reset_sequence),)
-
- cfg_reset_delay = cfg.getfloat("reset_delay")
- if cfg_reset_delay is not None:
- delay = extra_delay = cfg_reset_delay
- else:
- delay = DEFAULT_RESET_DELAY
- extra_delay = DEFAULT_RESET_DELAY + 0.5
-
- # This FPGA delay is for Espressif internal use
- if (
- self.FPGA_SLOW_BOOT
- and os.environ.get("ESPTOOL_ENV_FPGA", "").strip() == "1"
- ):
- delay = extra_delay = 7
-
- # USB-JTAG/Serial mode
- if mode == "usb_reset" or self._get_pid() == self.USB_JTAG_SERIAL_PID:
- return (USBJTAGSerialReset(self._port),)
-
- # USB-to-Serial bridge
- if os.name != "nt" and not self._port.name.startswith("rfc2217:"):
- return (
- UnixTightReset(self._port, delay),
- UnixTightReset(self._port, extra_delay),
- ClassicReset(self._port, delay),
- ClassicReset(self._port, extra_delay),
- )
-
- return (
- ClassicReset(self._port, delay),
- ClassicReset(self._port, extra_delay),
- )
-
- def connect(
- self,
- mode="default_reset",
- attempts=DEFAULT_CONNECT_ATTEMPTS,
- detecting=False,
- warnings=True,
- ):
- """Try connecting repeatedly until successful, or giving up"""
- if warnings and mode in ["no_reset", "no_reset_no_sync"]:
- print(
- 'WARNING: Pre-connection option "{}" was selected.'.format(mode),
- "Connection may fail if the chip is not in bootloader "
- "or flasher stub mode.",
- )
- print("Connecting...", end="")
- sys.stdout.flush()
- last_error = None
-
- reset_sequence = self._construct_reset_strategy_sequence(mode)
- try:
- for _, reset_strategy in zip(
- range(attempts) if attempts > 0 else itertools.count(),
- itertools.cycle(reset_sequence),
- ):
- last_error = self._connect_attempt(reset_strategy, mode)
- if last_error is None:
- break
- finally:
- print("") # end 'Connecting...' line
-
- if last_error is not None:
- raise FatalError(
- "Failed to connect to {}: {}"
- "\nFor troubleshooting steps visit: "
- "https://docs.espressif.com/projects/esptool/en/latest/troubleshooting.html".format( # noqa E501
- self.CHIP_NAME, last_error
- )
- )
-
- if not detecting:
- try:
- from .targets import ROM_LIST
-
- # check the date code registers match what we expect to see
- chip_magic_value = self.read_reg(ESPLoader.CHIP_DETECT_MAGIC_REG_ADDR)
- if chip_magic_value not in self.CHIP_DETECT_MAGIC_VALUE:
- actually = None
- for cls in ROM_LIST:
- if chip_magic_value in cls.CHIP_DETECT_MAGIC_VALUE:
- actually = cls
- break
- if warnings and actually is None:
- print(
- "WARNING: This chip doesn't appear to be a %s "
- "(chip magic value 0x%08x). "
- "Probably it is unsupported by this version of esptool."
- % (self.CHIP_NAME, chip_magic_value)
- )
- else:
- raise FatalError(
- "This chip is %s not %s. Wrong --chip argument?"
- % (actually.CHIP_NAME, self.CHIP_NAME)
- )
- except UnsupportedCommandError:
- self.secure_download_mode = True
-
- try:
- self.check_chip_id()
- except UnsupportedCommandError:
- # Fix for ROM not responding in SDM, reconnect and try again
- if self.secure_download_mode:
- self._connect_attempt(mode, reset_sequence[0])
- self.check_chip_id()
- else:
- raise
- self._post_connect()
-
- def _post_connect(self):
- """
- Additional initialization hook, may be overridden by the chip-specific class.
- Gets called after connect, and after auto-detection.
- """
- pass
-
- def read_reg(self, addr, timeout=DEFAULT_TIMEOUT):
- """Read memory address in target"""
- # we don't call check_command here because read_reg() function is called
- # when detecting chip type, and the way we check for success
- # (STATUS_BYTES_LENGTH) is different for different chip types (!)
- val, data = self.command(
- self.ESP_READ_REG, struct.pack(" 0:
- # add a dummy write to a date register as an excuse to have a delay
- command += struct.pack(
- " 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)
- )
-
- return self.check_command(
- "enter RAM download mode",
- self.ESP_MEM_BEGIN,
- struct.pack(" length:
- raise FatalError("Read more than expected")
-
- digest_frame = self.read()
- if len(digest_frame) != 16:
- raise FatalError("Expected digest, got: %s" % hexify(digest_frame))
- expected_digest = hexify(digest_frame).upper()
- digest = hashlib.md5(data).hexdigest().upper()
- if digest != expected_digest:
- raise FatalError(
- "Digest mismatch: expected %s, got %s" % (expected_digest, digest)
- )
- return data
-
- def flash_spi_attach(self, hspi_arg):
- """Send SPI attach command to enable the SPI flash pins
-
- ESP8266 ROM does this when you send flash_begin, ESP32 ROM
- has it as a SPI command.
- """
- # last 3 bytes in ESP_SPI_ATTACH argument are reserved values
- arg = struct.pack(" 0:
- self.write_reg(SPI_MOSI_DLEN_REG, mosi_bits - 1)
- if miso_bits > 0:
- self.write_reg(SPI_MISO_DLEN_REG, miso_bits - 1)
- flags = 0
- if dummy_len > 0:
- flags |= dummy_len - 1
- if addr_len > 0:
- flags |= (addr_len - 1) << SPI_USR_ADDR_LEN_SHIFT
- if flags:
- self.write_reg(SPI_USR1_REG, flags)
-
- else:
-
- def set_data_lengths(mosi_bits, miso_bits):
- SPI_DATA_LEN_REG = SPI_USR1_REG
- SPI_MOSI_BITLEN_S = 17
- SPI_MISO_BITLEN_S = 8
- mosi_mask = 0 if (mosi_bits == 0) else (mosi_bits - 1)
- miso_mask = 0 if (miso_bits == 0) else (miso_bits - 1)
- flags = (miso_mask << SPI_MISO_BITLEN_S) | (
- mosi_mask << SPI_MOSI_BITLEN_S
- )
- if dummy_len > 0:
- flags |= dummy_len - 1
- if addr_len > 0:
- flags |= (addr_len - 1) << SPI_USR_ADDR_LEN_SHIFT
- self.write_reg(SPI_DATA_LEN_REG, flags)
-
- # SPI peripheral "command" bitmasks for SPI_CMD_REG
- SPI_CMD_USR = 1 << 18
-
- # shift values
- SPI_USR2_COMMAND_LEN_SHIFT = 28
- SPI_USR_ADDR_LEN_SHIFT = 26
-
- if read_bits > 32:
- raise FatalError(
- "Reading more than 32 bits back from a SPI flash "
- "operation is unsupported"
- )
- if len(data) > 64:
- raise FatalError(
- "Writing more than 64 bytes of data with one SPI "
- "command is unsupported"
- )
-
- data_bits = len(data) * 8
- old_spi_usr = self.read_reg(SPI_USR_REG)
- old_spi_usr2 = self.read_reg(SPI_USR2_REG)
- flags = SPI_USR_COMMAND
- if read_bits > 0:
- flags |= SPI_USR_MISO
- if data_bits > 0:
- flags |= SPI_USR_MOSI
- if addr_len > 0:
- flags |= SPI_USR_ADDR
- if dummy_len > 0:
- flags |= SPI_USR_DUMMY
- set_data_lengths(data_bits, read_bits)
- self.write_reg(SPI_USR_REG, flags)
- self.write_reg(
- SPI_USR2_REG, (7 << SPI_USR2_COMMAND_LEN_SHIFT) | spiflash_command
- )
- if addr and addr_len > 0:
- self.write_reg(SPI_ADDR_REG, addr)
- if data_bits == 0:
- self.write_reg(SPI_W0_REG, 0) # clear data register before we read it
- else:
- data = pad_to(data, 4, b"\00") # pad to 32-bit multiple
- words = struct.unpack("I" * (len(data) // 4), data)
- next_reg = SPI_W0_REG
- for word in words:
- self.write_reg(next_reg, word)
- next_reg += 4
- self.write_reg(SPI_CMD_REG, SPI_CMD_USR)
-
- def wait_done():
- for _ in range(10):
- if (self.read_reg(SPI_CMD_REG) & SPI_CMD_USR) == 0:
- return
- raise FatalError("SPI command did not complete in time")
-
- wait_done()
-
- status = self.read_reg(SPI_W0_REG)
- # restore some SPI controller registers
- self.write_reg(SPI_USR_REG, old_spi_usr)
- self.write_reg(SPI_USR2_REG, old_spi_usr2)
- return status
-
- def read_spiflash_sfdp(self, addr, read_bits):
- CMD_RDSFDP = 0x5A
- return self.run_spiflash_command(
- CMD_RDSFDP, read_bits=read_bits, addr=addr, addr_len=24, dummy_len=8
- )
-
- def read_status(self, num_bytes=2):
- """Read up to 24 bits (num_bytes) of SPI flash status register contents
- via RDSR, RDSR2, RDSR3 commands
-
- Not all SPI flash supports all three commands. The upper 1 or 2
- bytes may be 0xFF.
- """
- SPIFLASH_RDSR = 0x05
- SPIFLASH_RDSR2 = 0x35
- SPIFLASH_RDSR3 = 0x15
-
- status = 0
- shift = 0
- for cmd in [SPIFLASH_RDSR, SPIFLASH_RDSR2, SPIFLASH_RDSR3][0:num_bytes]:
- status += self.run_spiflash_command(cmd, read_bits=8) << shift
- shift += 8
- return status
-
- def write_status(self, new_status, num_bytes=2, set_non_volatile=False):
- """Write up to 24 bits (num_bytes) of new status register
-
- num_bytes can be 1, 2 or 3.
-
- Not all flash supports the additional commands to write the
- second and third byte of the status register. When writing 2
- bytes, esptool also sends a 16-byte WRSR command (as some
- flash types use this instead of WRSR2.)
-
- If the set_non_volatile flag is set, non-volatile bits will
- be set as well as volatile ones (WREN used instead of WEVSR).
-
- """
- SPIFLASH_WRSR = 0x01
- SPIFLASH_WRSR2 = 0x31
- SPIFLASH_WRSR3 = 0x11
- SPIFLASH_WEVSR = 0x50
- SPIFLASH_WREN = 0x06
- SPIFLASH_WRDI = 0x04
-
- enable_cmd = SPIFLASH_WREN if set_non_volatile else SPIFLASH_WEVSR
-
- # try using a 16-bit WRSR (not supported by all chips)
- # this may be redundant, but shouldn't hurt
- if num_bytes == 2:
- self.run_spiflash_command(enable_cmd)
- self.run_spiflash_command(SPIFLASH_WRSR, struct.pack(">= 8
-
- self.run_spiflash_command(SPIFLASH_WRDI)
-
- def get_crystal_freq(self):
- """
- Figure out the crystal frequency from the UART clock divider
-
- Returns a normalized value in integer MHz (only values 40 or 26 are supported)
- """
- # The logic here is:
- # - We know that our baud rate and the ESP UART baud rate are roughly the same,
- # or we couldn't communicate
- # - We can read the UART clock divider register to know how the ESP derives this
- # from the APB bus frequency
- # - Multiplying these two together gives us the bus frequency which is either
- # the crystal frequency (ESP32) or double the crystal frequency (ESP8266).
- # See the self.XTAL_CLK_DIVIDER parameter for this factor.
- uart_div = self.read_reg(self.UART_CLKDIV_REG) & self.UART_CLKDIV_MASK
- est_xtal = (self._port.baudrate * uart_div) / 1e6 / self.XTAL_CLK_DIVIDER
- norm_xtal = 40 if est_xtal > 33 else 26
- if abs(norm_xtal - est_xtal) > 1:
- print(
- "WARNING: Detected crystal freq %.2fMHz is quite different to "
- "normalized freq %dMHz. Unsupported crystal in use?"
- % (est_xtal, norm_xtal)
- )
- return norm_xtal
-
- def hard_reset(self):
- print("Hard resetting via RTS pin...")
- HardReset(self._port)()
-
- def soft_reset(self, stay_in_bootloader):
- if not self.IS_STUB:
- if stay_in_bootloader:
- return # ROM bootloader is already in bootloader!
- else:
- # 'run user code' is as close to a soft reset as we can do
- self.flash_begin(0, 0)
- self.flash_finish(False)
- else:
- if stay_in_bootloader:
- # soft resetting from the stub loader
- # will re-load the ROM bootloader
- self.flash_begin(0, 0)
- self.flash_finish(True)
- elif self.CHIP_NAME != "ESP8266":
- raise FatalError(
- "Soft resetting is currently only supported on ESP8266"
- )
- else:
- # running user code from stub loader requires some hacks
- # in the stub loader
- self.command(self.ESP_RUN_USER_CODE, wait_response=False)
-
- def check_chip_id(self):
- try:
- chip_id = self.get_chip_id()
- if chip_id != self.IMAGE_CHIP_ID:
- print(
- "WARNING: Chip ID {} ({}) doesn't match expected Chip ID {}. "
- "esptool may not work correctly.".format(
- chip_id,
- self.UNSUPPORTED_CHIPS.get(chip_id, "Unknown"),
- self.IMAGE_CHIP_ID,
- )
- )
- # Try to flash anyways by disabling stub
- self.stub_is_disabled = True
- except NotImplementedInROMError:
- pass
-
-
-def slip_reader(port, trace_function):
- """Generator to read SLIP packets from a serial port.
- Yields one full SLIP packet at a time, raises exception on timeout or invalid data.
-
- Designed to avoid too many calls to serial.read(1), which can bog
- down on slow systems.
- """
-
- def detect_panic_handler(input):
- """
- Checks the input bytes for panic handler messages.
- Raises a FatalError if Guru Meditation or Fatal Exception is found, as both
- of these are used between different ROM versions.
- Tries to also parse the error cause (e.g. IllegalInstruction).
- """
-
- guru_meditation = (
- rb"G?uru Meditation Error: (?:Core \d panic'ed \(([a-zA-Z ]*)\))?"
- )
- fatal_exception = rb"F?atal exception \(\d+\): (?:([a-zA-Z ]*)?.*epc)?"
-
- # Search either for Guru Meditation or Fatal Exception
- data = re.search(
- rb"".join([rb"(?:", guru_meditation, rb"|", fatal_exception, rb")"]),
- input,
- re.DOTALL,
- )
- if data is not None:
- cause = [
- "({})".format(i.decode("utf-8"))
- for i in [data.group(1), data.group(2)]
- if i is not None
- ]
- cause = f" {cause[0]}" if len(cause) else ""
- msg = f"Guru Meditation Error detected{cause}"
- raise FatalError(msg)
-
- partial_packet = None
- in_escape = False
- successful_slip = False
- while True:
- waiting = port.inWaiting()
- read_bytes = port.read(1 if waiting == 0 else waiting)
- if read_bytes == b"":
- if partial_packet is None: # fail due to no data
- msg = (
- "Serial data stream stopped: Possible serial noise or corruption."
- if successful_slip
- else "No serial data received."
- )
- else: # fail during packet transfer
- msg = "Packet content transfer stopped (received {} bytes)".format(
- len(partial_packet)
- )
- trace_function(msg)
- raise FatalError(msg)
- trace_function("Read %d bytes: %s", len(read_bytes), HexFormatter(read_bytes))
- for b in read_bytes:
- b = bytes([b])
- if partial_packet is None: # waiting for packet header
- if b == b"\xc0":
- partial_packet = b""
- else:
- trace_function("Read invalid data: %s", HexFormatter(read_bytes))
- remaining_data = port.read(port.inWaiting())
- trace_function(
- "Remaining data in serial buffer: %s",
- HexFormatter(remaining_data),
- )
- detect_panic_handler(read_bytes + remaining_data)
- raise FatalError(
- "Invalid head of packet (0x%s): "
- "Possible serial noise or corruption." % hexify(b)
- )
- elif in_escape: # part-way through escape sequence
- in_escape = False
- if b == b"\xdc":
- partial_packet += b"\xc0"
- elif b == b"\xdd":
- partial_packet += b"\xdb"
- else:
- trace_function("Read invalid data: %s", HexFormatter(read_bytes))
- remaining_data = port.read(port.inWaiting())
- trace_function(
- "Remaining data in serial buffer: %s",
- HexFormatter(remaining_data),
- )
- detect_panic_handler(read_bytes + remaining_data)
- raise FatalError("Invalid SLIP escape (0xdb, 0x%s)" % (hexify(b)))
- elif b == b"\xdb": # start of escape sequence
- in_escape = True
- elif b == b"\xc0": # end of packet
- trace_function("Received full packet: %s", HexFormatter(partial_packet))
- yield partial_packet
- partial_packet = None
- successful_slip = True
- else: # normal byte in packet
- partial_packet += b
-
-
-class HexFormatter(object):
- """
- Wrapper class which takes binary data in its constructor
- and returns a hex string as it's __str__ method.
-
- This is intended for "lazy formatting" of trace() output
- in hex format. Avoids overhead (significant on slow computers)
- of generating long hex strings even if tracing is disabled.
-
- Note that this doesn't save any overhead if passed as an
- argument to "%", only when passed to trace()
-
- If auto_split is set (default), any long line (> 16 bytes) will be
- printed as separately indented lines, with ASCII decoding at the end
- of each line.
- """
-
- def __init__(self, binary_string, auto_split=True):
- self._s = binary_string
- self._auto_split = auto_split
-
- def __str__(self):
- if self._auto_split and len(self._s) > 16:
- result = ""
- s = self._s
- while len(s) > 0:
- line = s[:16]
- ascii_line = "".join(
- c
- if (
- c == " "
- or (c in string.printable and c not in string.whitespace)
- )
- else "."
- for c in line.decode("ascii", "replace")
- )
- s = s[16:]
- result += "\n %-16s %-16s | %s" % (
- hexify(line[:8], False),
- hexify(line[8:], False),
- ascii_line,
- )
- return result
- else:
- return hexify(self._s, False)
diff --git a/installer/bin/esptool/esptool/reset.py b/installer/bin/esptool/esptool/reset.py
deleted file mode 100644
index 39b9a15..0000000
--- a/installer/bin/esptool/esptool/reset.py
+++ /dev/null
@@ -1,178 +0,0 @@
-# SPDX-FileCopyrightText: 2014-2023 Fredrik Ahlberg, Angus Gratton,
-# Espressif Systems (Shanghai) CO LTD, other contributors as noted.
-#
-# SPDX-License-Identifier: GPL-2.0-or-later
-
-import os
-import struct
-import time
-
-from .util import FatalError
-
-# Used for resetting into bootloader on Unix-like systems
-if os.name != "nt":
- import fcntl
- import termios
-
- # Constants used for terminal status lines reading/setting.
- # Taken from pySerial's backend for IO:
- # https://github.com/pyserial/pyserial/blob/master/serial/serialposix.py
- TIOCMSET = getattr(termios, "TIOCMSET", 0x5418)
- TIOCMGET = getattr(termios, "TIOCMGET", 0x5415)
- TIOCM_DTR = getattr(termios, "TIOCM_DTR", 0x002)
- TIOCM_RTS = getattr(termios, "TIOCM_RTS", 0x004)
-
-DEFAULT_RESET_DELAY = 0.05 # default time to wait before releasing boot pin after reset
-
-
-class ResetStrategy(object):
- def __init__(self, port, reset_delay=DEFAULT_RESET_DELAY):
- self.port = port
- self.reset_delay = reset_delay
-
- def __call__():
- pass
-
- def _setDTR(self, state):
- self.port.setDTR(state)
-
- def _setRTS(self, state):
- self.port.setRTS(state)
- # Work-around for adapters on Windows using the usbser.sys driver:
- # generate a dummy change to DTR so that the set-control-line-state
- # request is sent with the updated RTS state and the same DTR state
- self.port.setDTR(self.port.dtr)
-
- def _setDTRandRTS(self, dtr=False, rts=False):
- status = struct.unpack(
- "I", fcntl.ioctl(self.port.fileno(), TIOCMGET, struct.pack("I", 0))
- )[0]
- if dtr:
- status |= TIOCM_DTR
- else:
- status &= ~TIOCM_DTR
- if rts:
- status |= TIOCM_RTS
- else:
- status &= ~TIOCM_RTS
- fcntl.ioctl(self.port.fileno(), TIOCMSET, struct.pack("I", status))
-
-
-class ClassicReset(ResetStrategy):
- """
- Classic reset sequence, sets DTR and RTS lines sequentially.
- """
-
- def __call__(self):
- self._setDTR(False) # IO0=HIGH
- self._setRTS(True) # EN=LOW, chip in reset
- time.sleep(0.1)
- self._setDTR(True) # IO0=LOW
- self._setRTS(False) # EN=HIGH, chip out of reset
- time.sleep(self.reset_delay)
- self._setDTR(False) # IO0=HIGH, done
-
-
-class UnixTightReset(ResetStrategy):
- """
- UNIX-only reset sequence with custom implementation,
- which allows setting DTR and RTS lines at the same time.
- """
-
- def __call__(self):
- self._setDTRandRTS(False, False)
- self._setDTRandRTS(True, True)
- self._setDTRandRTS(False, True) # IO0=HIGH & EN=LOW, chip in reset
- time.sleep(0.1)
- self._setDTRandRTS(True, False) # IO0=LOW & EN=HIGH, chip out of reset
- time.sleep(self.reset_delay)
- self._setDTRandRTS(False, False) # IO0=HIGH, done
- self._setDTR(False) # Needed in some environments to ensure IO0=HIGH
-
-
-class USBJTAGSerialReset(ResetStrategy):
- """
- Custom reset sequence, which is required when the device
- is connecting via its USB-JTAG-Serial peripheral.
- """
-
- def __call__(self):
- self._setRTS(False)
- self._setDTR(False) # Idle
- time.sleep(0.1)
- self._setDTR(True) # Set IO0
- self._setRTS(False)
- time.sleep(0.1)
- self._setRTS(True) # Reset. Calls inverted to go through (1,1) instead of (0,0)
- self._setDTR(False)
- self._setRTS(True) # RTS set as Windows only propagates DTR on RTS setting
- time.sleep(0.1)
- self._setDTR(False)
- self._setRTS(False) # Chip out of reset
-
-
-class HardReset(ResetStrategy):
- """
- Reset sequence for hard resetting the chip.
- Can be used to reset out of the bootloader or to restart a running app.
- """
-
- def __init__(self, port, uses_usb_otg=False):
- super().__init__(port)
- self.uses_usb_otg = uses_usb_otg
-
- def __call__(self):
- self._setRTS(True) # EN->LOW
- if self.uses_usb_otg:
- # Give the chip some time to come out of reset,
- # to be able to handle further DTR/RTS transitions
- time.sleep(0.2)
- self._setRTS(False)
- time.sleep(0.2)
- else:
- time.sleep(0.1)
- self._setRTS(False)
-
-
-class CustomReset(ResetStrategy):
- """
- Custom reset strategy defined with a string.
-
- CustomReset object is created as "rst = CustomReset(port, seq_str)"
- and can be later executed simply with "rst()"
-
- The seq_str input string consists of individual commands divided by "|".
- Commands (e.g. R0) are defined by a code (R) and an argument (0).
-
- The commands are:
- D: setDTR - 1=True / 0=False
- R: setRTS - 1=True / 0=False
- U: setDTRandRTS (Unix-only) - 0,0 / 0,1 / 1,0 / or 1,1
- W: Wait (time delay) - positive float number
-
- e.g.
- "D0|R1|W0.1|D1|R0|W0.05|D0" represents the ClassicReset strategy
- "U1,1|U0,1|W0.1|U1,0|W0.05|U0,0" represents the UnixTightReset strategy
- """
-
- format_dict = {
- "D": "self.port.setDTR({})",
- "R": "self.port.setRTS({})",
- "W": "time.sleep({})",
- "U": "self._setDTRandRTS({})",
- }
-
- def __call__(self):
- exec(self.constructed_strategy)
-
- def __init__(self, port, seq_str):
- super().__init__(port)
- self.constructed_strategy = self._parse_string_to_seq(seq_str)
-
- def _parse_string_to_seq(self, seq_str):
- try:
- cmds = seq_str.split("|")
- fn_calls_list = [self.format_dict[cmd[0]].format(cmd[1:]) for cmd in cmds]
- except Exception as e:
- raise FatalError(f'Invalid "custom_reset_sequence" option format: {e}')
- return "\n".join(fn_calls_list)
diff --git a/installer/bin/esptool/esptool/targets/__init__.py b/installer/bin/esptool/esptool/targets/__init__.py
deleted file mode 100644
index 9d76ca5..0000000
--- a/installer/bin/esptool/esptool/targets/__init__.py
+++ /dev/null
@@ -1,31 +0,0 @@
-from .esp32 import ESP32ROM
-from .esp32c2 import ESP32C2ROM
-from .esp32c3 import ESP32C3ROM
-from .esp32c6 import ESP32C6ROM
-from .esp32c6beta import ESP32C6BETAROM
-from .esp32h2 import ESP32H2ROM
-from .esp32h2beta1 import ESP32H2BETA1ROM
-from .esp32h2beta2 import ESP32H2BETA2ROM
-from .esp32s2 import ESP32S2ROM
-from .esp32s3 import ESP32S3ROM
-from .esp32s3beta2 import ESP32S3BETA2ROM
-from .esp8266 import ESP8266ROM
-
-
-CHIP_DEFS = {
- "esp8266": ESP8266ROM,
- "esp32": ESP32ROM,
- "esp32s2": ESP32S2ROM,
- "esp32s3beta2": ESP32S3BETA2ROM,
- "esp32s3": ESP32S3ROM,
- "esp32c3": ESP32C3ROM,
- "esp32c6beta": ESP32C6BETAROM,
- "esp32h2beta1": ESP32H2BETA1ROM,
- "esp32h2beta2": ESP32H2BETA2ROM,
- "esp32c2": ESP32C2ROM,
- "esp32c6": ESP32C6ROM,
- "esp32h2": ESP32H2ROM,
-}
-
-CHIP_LIST = list(CHIP_DEFS.keys())
-ROM_LIST = list(CHIP_DEFS.values())
diff --git a/installer/bin/esptool/esptool/targets/esp32.py b/installer/bin/esptool/esptool/targets/esp32.py
deleted file mode 100644
index b805ed4..0000000
--- a/installer/bin/esptool/esptool/targets/esp32.py
+++ /dev/null
@@ -1,393 +0,0 @@
-# SPDX-FileCopyrightText: 2014-2022 Fredrik Ahlberg, Angus Gratton,
-# Espressif Systems (Shanghai) CO LTD, other contributors as noted.
-#
-# SPDX-License-Identifier: GPL-2.0-or-later
-
-import struct
-import time
-
-from ..loader import ESPLoader
-from ..util import FatalError, NotSupportedError
-
-
-class ESP32ROM(ESPLoader):
- """Access class for ESP32 ROM bootloader"""
-
- CHIP_NAME = "ESP32"
- IMAGE_CHIP_ID = 0
- IS_STUB = False
-
- FPGA_SLOW_BOOT = True
-
- CHIP_DETECT_MAGIC_VALUE = [0x00F01D83]
-
- IROM_MAP_START = 0x400D0000
- IROM_MAP_END = 0x40400000
-
- DROM_MAP_START = 0x3F400000
- DROM_MAP_END = 0x3F800000
-
- # ESP32 uses a 4 byte status reply
- STATUS_BYTES_LENGTH = 4
-
- SPI_REG_BASE = 0x3FF42000
- SPI_USR_OFFS = 0x1C
- SPI_USR1_OFFS = 0x20
- SPI_USR2_OFFS = 0x24
- SPI_MOSI_DLEN_OFFS = 0x28
- SPI_MISO_DLEN_OFFS = 0x2C
- EFUSE_RD_REG_BASE = 0x3FF5A000
-
- EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT_REG = EFUSE_RD_REG_BASE + 0x18
- EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT = 1 << 7 # EFUSE_RD_DISABLE_DL_ENCRYPT
-
- EFUSE_SPI_BOOT_CRYPT_CNT_REG = EFUSE_RD_REG_BASE # EFUSE_BLK0_WDATA0_REG
- EFUSE_SPI_BOOT_CRYPT_CNT_MASK = 0x7F << 20 # EFUSE_FLASH_CRYPT_CNT
-
- EFUSE_RD_ABS_DONE_REG = EFUSE_RD_REG_BASE + 0x018
- EFUSE_RD_ABS_DONE_0_MASK = 1 << 4
- EFUSE_RD_ABS_DONE_1_MASK = 1 << 5
-
- DR_REG_SYSCON_BASE = 0x3FF66000
- APB_CTL_DATE_ADDR = DR_REG_SYSCON_BASE + 0x7C
- APB_CTL_DATE_V = 0x1
- APB_CTL_DATE_S = 31
-
- SPI_W0_OFFS = 0x80
-
- UART_CLKDIV_REG = 0x3FF40014
-
- XTAL_CLK_DIVIDER = 1
-
- RTCCALICFG1 = 0x3FF5F06C
- TIMERS_RTC_CALI_VALUE = 0x01FFFFFF
- TIMERS_RTC_CALI_VALUE_S = 7
-
- FLASH_SIZES = {
- "1MB": 0x00,
- "2MB": 0x10,
- "4MB": 0x20,
- "8MB": 0x30,
- "16MB": 0x40,
- "32MB": 0x50,
- "64MB": 0x60,
- "128MB": 0x70,
- }
-
- FLASH_FREQUENCY = {
- "80m": 0xF,
- "40m": 0x0,
- "26m": 0x1,
- "20m": 0x2,
- }
-
- BOOTLOADER_FLASH_OFFSET = 0x1000
-
- OVERRIDE_VDDSDIO_CHOICES = ["1.8V", "1.9V", "OFF"]
-
- MEMORY_MAP = [
- [0x00000000, 0x00010000, "PADDING"],
- [0x3F400000, 0x3F800000, "DROM"],
- [0x3F800000, 0x3FC00000, "EXTRAM_DATA"],
- [0x3FF80000, 0x3FF82000, "RTC_DRAM"],
- [0x3FF90000, 0x40000000, "BYTE_ACCESSIBLE"],
- [0x3FFAE000, 0x40000000, "DRAM"],
- [0x3FFE0000, 0x3FFFFFFC, "DIRAM_DRAM"],
- [0x40000000, 0x40070000, "IROM"],
- [0x40070000, 0x40078000, "CACHE_PRO"],
- [0x40078000, 0x40080000, "CACHE_APP"],
- [0x40080000, 0x400A0000, "IRAM"],
- [0x400A0000, 0x400BFFFC, "DIRAM_IRAM"],
- [0x400C0000, 0x400C2000, "RTC_IRAM"],
- [0x400D0000, 0x40400000, "IROM"],
- [0x50000000, 0x50002000, "RTC_DATA"],
- ]
-
- FLASH_ENCRYPTED_WRITE_ALIGN = 32
-
- """ Try to read the BLOCK1 (encryption key) and check if it is valid """
-
- def is_flash_encryption_key_valid(self):
- """Bit 0 of efuse_rd_disable[3:0] is mapped to BLOCK1
- this bit is at position 16 in EFUSE_BLK0_RDATA0_REG"""
- word0 = self.read_efuse(0)
- rd_disable = (word0 >> 16) & 0x1
-
- # reading of BLOCK1 is NOT ALLOWED so we assume valid key is programmed
- if rd_disable:
- return True
- else:
- # reading of BLOCK1 is ALLOWED so we will read and verify for non-zero.
- # When ESP32 has not generated AES/encryption key in BLOCK1,
- # the contents will be readable and 0.
- # If the flash encryption is enabled it is expected to have a valid
- # non-zero key. We break out on first occurance of non-zero value
- key_word = [0] * 7
- for i in range(len(key_word)):
- key_word[i] = self.read_efuse(14 + i)
- # key is non-zero so break & return
- if key_word[i] != 0:
- return True
- return False
-
- def get_flash_crypt_config(self):
- """For flash encryption related commands we need to make sure
- user has programmed all the relevant efuse correctly so before
- writing encrypted write_flash_encrypt esptool will verify the values
- of flash_crypt_config to be non zero if they are not read
- protected. If the values are zero a warning will be printed
-
- bit 3 in efuse_rd_disable[3:0] is mapped to flash_crypt_config
- this bit is at position 19 in EFUSE_BLK0_RDATA0_REG"""
- word0 = self.read_efuse(0)
- rd_disable = (word0 >> 19) & 0x1
-
- if rd_disable == 0:
- """we can read the flash_crypt_config efuse value
- so go & read it (EFUSE_BLK0_RDATA5_REG[31:28])"""
- word5 = self.read_efuse(5)
- word5 = (word5 >> 28) & 0xF
- return word5
- else:
- # if read of the efuse is disabled we assume it is set correctly
- return 0xF
-
- def get_encrypted_download_disabled(self):
- return (
- self.read_reg(self.EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT_REG)
- & self.EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT
- )
-
- def get_flash_encryption_enabled(self):
- flash_crypt_cnt = (
- self.read_reg(self.EFUSE_SPI_BOOT_CRYPT_CNT_REG)
- & self.EFUSE_SPI_BOOT_CRYPT_CNT_MASK
- )
- # Flash encryption enabled when odd number of bits are set
- return bin(flash_crypt_cnt).count("1") & 1 != 0
-
- def get_secure_boot_enabled(self):
- efuses = self.read_reg(self.EFUSE_RD_ABS_DONE_REG)
- rev = self.get_chip_revision()
- return efuses & self.EFUSE_RD_ABS_DONE_0_MASK or (
- rev >= 300 and efuses & self.EFUSE_RD_ABS_DONE_1_MASK
- )
-
- def get_pkg_version(self):
- word3 = self.read_efuse(3)
- pkg_version = (word3 >> 9) & 0x07
- pkg_version += ((word3 >> 2) & 0x1) << 3
- return pkg_version
-
- def get_chip_revision(self):
- return self.get_major_chip_version() * 100 + self.get_minor_chip_version()
-
- def get_minor_chip_version(self):
- return (self.read_efuse(5) >> 24) & 0x3
-
- def get_major_chip_version(self):
- rev_bit0 = (self.read_efuse(3) >> 15) & 0x1
- rev_bit1 = (self.read_efuse(5) >> 20) & 0x1
- apb_ctl_date = self.read_reg(self.APB_CTL_DATE_ADDR)
- rev_bit2 = (apb_ctl_date >> self.APB_CTL_DATE_S) & self.APB_CTL_DATE_V
- combine_value = (rev_bit2 << 2) | (rev_bit1 << 1) | rev_bit0
-
- revision = {
- 0: 0,
- 1: 1,
- 3: 2,
- 7: 3,
- }.get(combine_value, 0)
- return revision
-
- def get_chip_description(self):
- pkg_version = self.get_pkg_version()
- major_rev = self.get_major_chip_version()
- minor_rev = self.get_minor_chip_version()
- rev3 = major_rev == 3
- single_core = self.read_efuse(3) & (1 << 0) # CHIP_VER DIS_APP_CPU
-
- chip_name = {
- 0: "ESP32-S0WDQ6" if single_core else "ESP32-D0WDQ6",
- 1: "ESP32-S0WD" if single_core else "ESP32-D0WD",
- 2: "ESP32-D2WD",
- 4: "ESP32-U4WDH",
- 5: "ESP32-PICO-V3" if rev3 else "ESP32-PICO-D4",
- 6: "ESP32-PICO-V3-02",
- 7: "ESP32-D0WDR2-V3",
- }.get(pkg_version, "unknown ESP32")
-
- # ESP32-D0WD-V3, ESP32-D0WDQ6-V3
- if chip_name.startswith("ESP32-D0WD") and rev3:
- chip_name += "-V3"
-
- return f"{chip_name} (revision v{major_rev}.{minor_rev})"
-
- def get_chip_features(self):
- features = ["WiFi"]
- word3 = self.read_efuse(3)
-
- # names of variables in this section are lowercase
- # versions of EFUSE names as documented in TRM and
- # ESP-IDF efuse_reg.h
-
- chip_ver_dis_bt = word3 & (1 << 1)
- if chip_ver_dis_bt == 0:
- features += ["BT"]
-
- chip_ver_dis_app_cpu = word3 & (1 << 0)
- if chip_ver_dis_app_cpu:
- features += ["Single Core"]
- else:
- features += ["Dual Core"]
-
- chip_cpu_freq_rated = word3 & (1 << 13)
- if chip_cpu_freq_rated:
- chip_cpu_freq_low = word3 & (1 << 12)
- if chip_cpu_freq_low:
- features += ["160MHz"]
- else:
- features += ["240MHz"]
-
- pkg_version = self.get_pkg_version()
- if pkg_version in [2, 4, 5, 6]:
- features += ["Embedded Flash"]
-
- if pkg_version == 6:
- features += ["Embedded PSRAM"]
-
- word4 = self.read_efuse(4)
- adc_vref = (word4 >> 8) & 0x1F
- if adc_vref:
- features += ["VRef calibration in efuse"]
-
- blk3_part_res = word3 >> 14 & 0x1
- if blk3_part_res:
- features += ["BLK3 partially reserved"]
-
- word6 = self.read_efuse(6)
- coding_scheme = word6 & 0x3
- features += [
- "Coding Scheme %s"
- % {0: "None", 1: "3/4", 2: "Repeat (UNSUPPORTED)", 3: "Invalid"}[
- coding_scheme
- ]
- ]
-
- return features
-
- def read_efuse(self, n):
- """Read the nth word of the ESP3x EFUSE region."""
- return self.read_reg(self.EFUSE_RD_REG_BASE + (4 * n))
-
- def chip_id(self):
- raise NotSupportedError(self, "chip_id")
-
- def read_mac(self):
- """Read MAC from EFUSE region"""
- words = [self.read_efuse(2), self.read_efuse(1)]
- bitstring = struct.pack(">II", *words)
- bitstring = bitstring[2:8] # trim the 2 byte CRC
- return tuple(bitstring)
-
- def get_erase_size(self, offset, size):
- return size
-
- def override_vddsdio(self, new_voltage):
- new_voltage = new_voltage.upper()
- if new_voltage not in self.OVERRIDE_VDDSDIO_CHOICES:
- raise FatalError(
- "The only accepted VDDSDIO overrides are '1.8V', '1.9V' and 'OFF'"
- )
- RTC_CNTL_SDIO_CONF_REG = 0x3FF48074
- RTC_CNTL_XPD_SDIO_REG = 1 << 31
- RTC_CNTL_DREFH_SDIO_M = 3 << 29
- RTC_CNTL_DREFM_SDIO_M = 3 << 27
- RTC_CNTL_DREFL_SDIO_M = 3 << 25
- # RTC_CNTL_SDIO_TIEH = (1 << 23)
- # not used here, setting TIEH=1 would set 3.3V output,
- # not safe for esptool.py to do
- RTC_CNTL_SDIO_FORCE = 1 << 22
- RTC_CNTL_SDIO_PD_EN = 1 << 21
-
- reg_val = RTC_CNTL_SDIO_FORCE # override efuse setting
- reg_val |= RTC_CNTL_SDIO_PD_EN
- if new_voltage != "OFF":
- reg_val |= RTC_CNTL_XPD_SDIO_REG # enable internal LDO
- if new_voltage == "1.9V":
- reg_val |= (
- RTC_CNTL_DREFH_SDIO_M | RTC_CNTL_DREFM_SDIO_M | RTC_CNTL_DREFL_SDIO_M
- ) # boost voltage
- self.write_reg(RTC_CNTL_SDIO_CONF_REG, reg_val)
- print("VDDSDIO regulator set to %s" % new_voltage)
-
- def read_flash_slow(self, offset, length, progress_fn):
- BLOCK_LEN = 64 # ROM read limit per command (this limit is why it's so slow)
-
- data = b""
- while len(data) < length:
- block_len = min(BLOCK_LEN, length - len(data))
- r = self.check_command(
- "read flash block",
- self.ESP_READ_FLASH_SLOW,
- struct.pack("> self.TIMERS_RTC_CALI_VALUE_S
- ) & self.TIMERS_RTC_CALI_VALUE
- clk_8M_freq = self.read_efuse(4) & (0xFF) # EFUSE_RD_CK8M_FREQ
- rom_calculated_freq = cali_val * 15625 * clk_8M_freq / 40
- return rom_calculated_freq
-
- def change_baud(self, baud):
- # 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
- false_rom_baud = int(baud * rom_calculated_freq // valid_freq)
-
- print(f"Changing baud rate to {baud}")
- self.command(self.ESP_CHANGE_BAUDRATE, struct.pack("> 22) & 0x07
-
- def get_chip_description(self):
- chip_name = {
- 0: "ESP32-C2",
- 1: "ESP32-C2",
- }.get(self.get_pkg_version(), "unknown ESP32-C2")
- 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_minor_chip_version(self):
- num_word = 1
- return (self.read_reg(self.EFUSE_BLOCK2_ADDR + (4 * num_word)) >> 16) & 0xF
-
- def get_major_chip_version(self):
- num_word = 1
- return (self.read_reg(self.EFUSE_BLOCK2_ADDR + (4 * num_word)) >> 20) & 0x3
-
- def get_crystal_freq(self):
- # The crystal detection algorithm of ESP32/ESP8266 works for ESP32-C2 as well.
- return ESPLoader.get_crystal_freq(self)
-
- def change_baud(self, baud):
- rom_with_26M_XTAL = not self.IS_STUB and self.get_crystal_freq() == 26
- if rom_with_26M_XTAL:
- # The code is copied over from ESPLoader.change_baud().
- # Probably this is just a temporary solution until the next chip revision.
-
- # The ROM code thinks it uses a 40 MHz XTAL. Recompute the baud rate
- # in order to trick the ROM code to set the correct baud rate for
- # a 26 MHz XTAL.
- false_rom_baud = baud * 40 // 26
-
- print(f"Changing baud rate to {baud}")
- self.command(
- self.ESP_CHANGE_BAUDRATE, struct.pack("> 21) & 0x07
-
- def get_minor_chip_version(self):
- hi_num_word = 5
- hi = (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * hi_num_word)) >> 23) & 0x01
- low_num_word = 3
- low = (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * low_num_word)) >> 18) & 0x07
- return (hi << 3) + low
-
- def get_major_chip_version(self):
- num_word = 5
- return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 24) & 0x03
-
- def get_chip_description(self):
- chip_name = {
- 0: "ESP32-C3",
- }.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"]
-
- def get_crystal_freq(self):
- # ESP32C3 XTAL is fixed to 40MHz
- return 40
-
- def override_vddsdio(self, new_voltage):
- raise NotImplementedInROMError(
- "VDD_SDIO overrides are not supported for ESP32-C3"
- )
-
- def read_mac(self):
- 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-C3
-
- 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 an AES-128 key
- purposes = [self.get_key_block_purpose(b) for b in range(6)]
-
- return any(p == self.PURPOSE_VAL_XTS_AES128_KEY for p in purposes)
-
- def change_baud(self, baud):
- ESPLoader.change_baud(self, baud)
-
- def uses_usb_jtag_serial(self):
- """
- Check the UARTDEV_BUF_NO register to see if USB-JTAG/Serial is being used
- """
- if self.secure_download_mode:
- return False # Can't detect USB-JTAG/Serial in secure download mode
- return self.get_uart_no() == self.UARTDEV_BUF_NO_USB_JTAG_SERIAL
-
- def disable_rtc_watchdog(self):
- # When USB-JTAG/Serial is used, the RTC watchdog is not reset
- # and can then reset the board during flashing. Disable it.
- if self.uses_usb_jtag_serial():
- self.write_reg(self.RTC_CNTL_WDTWPROTECT_REG, self.RTC_CNTL_WDT_WKEY)
- self.write_reg(self.RTC_CNTL_WDTCONFIG0_REG, 0)
- self.write_reg(self.RTC_CNTL_WDTWPROTECT_REG, 0)
-
- def _post_connect(self):
- if not self.sync_stub_detected: # Don't run if stub is reused
- self.disable_rtc_watchdog()
-
-
-class ESP32C3StubLoader(ESP32C3ROM):
- """Access class for ESP32C3 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
-
-
-ESP32C3ROM.STUB_CLASS = ESP32C3StubLoader
diff --git a/installer/bin/esptool/esptool/targets/esp32c6.py b/installer/bin/esptool/esptool/targets/esp32c6.py
deleted file mode 100644
index 0c4575e..0000000
--- a/installer/bin/esptool/esptool/targets/esp32c6.py
+++ /dev/null
@@ -1,189 +0,0 @@
-# SPDX-FileCopyrightText: 2022 Fredrik Ahlberg, Angus Gratton,
-# Espressif Systems (Shanghai) CO LTD, other contributors as noted.
-#
-# SPDX-License-Identifier: GPL-2.0-or-later
-
-import struct
-
-from .esp32c3 import ESP32C3ROM
-from ..util import FatalError, NotImplementedInROMError
-
-
-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
- DROM_MAP_END = 0x43000000
-
- BOOTLOADER_FLASH_OFFSET = 0x0
-
- # Magic value for ESP32C6
- CHIP_DETECT_MAGIC_VALUE = [0x2CE0806F]
-
- SPI_REG_BASE = 0x60003000
- 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
-
- UART_DATE_REG_ADDR = 0x60000000 + 0x7C
-
- EFUSE_BASE = 0x600B0800
- EFUSE_BLOCK1_ADDR = EFUSE_BASE + 0x044
- MAC_EFUSE_REG = EFUSE_BASE + 0x044
-
- 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_AES128_KEY = 4
-
- SUPPORTS_ENCRYPTED_FLASH = True
-
- FLASH_ENCRYPTED_WRITE_ALIGN = 16
-
- UARTDEV_BUF_NO = 0x4087F580 # Variable in ROM .bss which indicates the port in use
- UARTDEV_BUF_NO_USB_JTAG_SERIAL = 3 # The above var when USB-JTAG/Serial is used
-
- DR_REG_LP_WDT_BASE = 0x600B1C00
- RTC_CNTL_WDTCONFIG0_REG = DR_REG_LP_WDT_BASE + 0x0 # LP_WDT_RWDT_CONFIG0_REG
- RTC_CNTL_WDTWPROTECT_REG = DR_REG_LP_WDT_BASE + 0x0018 # LP_WDT_RWDT_WPROTECT_REG
-
- FLASH_FREQUENCY = {
- "80m": 0x0, # workaround for wrong mspi HS div value in ROM
- "40m": 0x0,
- "20m": 0x2,
- }
-
- MEMORY_MAP = [
- [0x00000000, 0x00010000, "PADDING"],
- [0x42800000, 0x43000000, "DROM"],
- [0x40800000, 0x40880000, "DRAM"],
- [0x40800000, 0x40880000, "BYTE_ACCESSIBLE"],
- [0x4004AC00, 0x40050000, "DROM_MASK"],
- [0x40000000, 0x4004AC00, "IROM_MASK"],
- [0x42000000, 0x42800000, "IROM"],
- [0x40800000, 0x40880000, "IRAM"],
- [0x50000000, 0x50004000, "RTC_IRAM"],
- [0x50000000, 0x50004000, "RTC_DRAM"],
- [0x600FE000, 0x60100000, "MEM_INTERNAL2"],
- ]
-
- def get_pkg_version(self):
- num_word = 3
- return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 21) & 0x07
-
- def get_minor_chip_version(self):
- hi_num_word = 5
- hi = (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * hi_num_word)) >> 23) & 0x01
- low_num_word = 3
- low = (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * low_num_word)) >> 18) & 0x07
- return (hi << 3) + low
-
- def get_major_chip_version(self):
- num_word = 5
- return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 24) & 0x03
-
- def get_chip_description(self):
- chip_name = {
- 0: "ESP32-C6",
- }.get(self.get_pkg_version(), "unknown ESP32-C6")
- 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 6", "BT 5", "IEEE802.15.4"]
-
- def get_crystal_freq(self):
- # ESP32C6 XTAL is fixed to 40MHz
- return 40
-
- def override_vddsdio(self, new_voltage):
- raise NotImplementedInROMError(
- "VDD_SDIO overrides are not supported for ESP32-C6"
- )
-
- def read_mac(self):
- 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-C6
-
- 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 an AES-128 key
- purposes = [self.get_key_block_purpose(b) for b in range(6)]
-
- return any(p == self.PURPOSE_VAL_XTS_AES128_KEY for p in purposes)
-
-
-class ESP32C6StubLoader(ESP32C6ROM):
- """Access class for ESP32C6 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
-
-
-ESP32C6ROM.STUB_CLASS = ESP32C6StubLoader
diff --git a/installer/bin/esptool/esptool/targets/esp32c6beta.py b/installer/bin/esptool/esptool/targets/esp32c6beta.py
deleted file mode 100644
index 4c4b6be..0000000
--- a/installer/bin/esptool/esptool/targets/esp32c6beta.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# SPDX-FileCopyrightText: 2014-2022 Fredrik Ahlberg, Angus Gratton,
-# Espressif Systems (Shanghai) CO LTD, other contributors as noted.
-#
-# SPDX-License-Identifier: GPL-2.0-or-later
-
-from .esp32c3 import ESP32C3ROM
-
-
-class ESP32C6BETAROM(ESP32C3ROM):
- CHIP_NAME = "ESP32-C6(beta)"
- IMAGE_CHIP_ID = 7
-
- CHIP_DETECT_MAGIC_VALUE = [0x0DA1806F]
-
- UART_DATE_REG_ADDR = 0x00000500
-
- def get_chip_description(self):
- chip_name = {
- 0: "ESP32-C6",
- }.get(self.get_pkg_version(), "unknown ESP32-C6")
- 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 _post_connect(self):
- pass
diff --git a/installer/bin/esptool/esptool/targets/esp32h2.py b/installer/bin/esptool/esptool/targets/esp32h2.py
deleted file mode 100644
index a37617e..0000000
--- a/installer/bin/esptool/esptool/targets/esp32h2.py
+++ /dev/null
@@ -1,65 +0,0 @@
-# SPDX-FileCopyrightText: 2022 Fredrik Ahlberg, Angus Gratton,
-# Espressif Systems (Shanghai) CO LTD, other contributors as noted.
-#
-# SPDX-License-Identifier: GPL-2.0-or-later
-
-from .esp32c6 import ESP32C6ROM
-
-
-class ESP32H2ROM(ESP32C6ROM):
- CHIP_NAME = "ESP32-H2"
- IMAGE_CHIP_ID = 16
-
- # Magic value for ESP32H2
- CHIP_DETECT_MAGIC_VALUE = [0xD7B73E80]
-
- FLASH_FREQUENCY = {
- "48m": 0xF,
- "24m": 0x0,
- "16m": 0x1,
- "12m": 0x2,
- }
-
- def get_pkg_version(self):
- num_word = 3
- block1_addr = self.EFUSE_BASE + 0x044
- word3 = self.read_reg(block1_addr + (4 * num_word))
- pkg_version = (word3 >> 21) & 0x0F
- return pkg_version
-
- def get_chip_description(self):
- chip_name = {
- 0: "ESP32-H2",
- }.get(self.get_pkg_version(), "unknown ESP32-H2")
- 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 ["BLE"]
-
- def get_crystal_freq(self):
- # ESP32H2 XTAL is fixed to 32MHz
- return 32
-
-
-class ESP32H2StubLoader(ESP32H2ROM):
- """Access class for ESP32H2 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
-
-
-ESP32H2ROM.STUB_CLASS = ESP32H2StubLoader
diff --git a/installer/bin/esptool/esptool/targets/esp32h2beta1.py b/installer/bin/esptool/esptool/targets/esp32h2beta1.py
deleted file mode 100644
index 66b6df9..0000000
--- a/installer/bin/esptool/esptool/targets/esp32h2beta1.py
+++ /dev/null
@@ -1,164 +0,0 @@
-# SPDX-FileCopyrightText: 2014-2022 Fredrik Ahlberg, Angus Gratton,
-# Espressif Systems (Shanghai) CO LTD, other contributors as noted.
-#
-# SPDX-License-Identifier: GPL-2.0-or-later
-
-import struct
-
-from .esp32c3 import ESP32C3ROM
-from ..util import FatalError, NotImplementedInROMError
-
-
-class ESP32H2BETA1ROM(ESP32C3ROM):
- CHIP_NAME = "ESP32-H2(beta1)"
- IMAGE_CHIP_ID = 10
-
- IROM_MAP_START = 0x42000000
- IROM_MAP_END = 0x42800000
- DROM_MAP_START = 0x3C000000
- DROM_MAP_END = 0x3C800000
-
- SPI_REG_BASE = 0x60002000
- 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
-
- BOOTLOADER_FLASH_OFFSET = 0x0
-
- CHIP_DETECT_MAGIC_VALUE = [0xCA26CC22]
-
- UART_DATE_REG_ADDR = 0x60000000 + 0x7C
-
- EFUSE_BASE = 0x6001A000
- EFUSE_BLOCK1_ADDR = EFUSE_BASE + 0x044
- MAC_EFUSE_REG = EFUSE_BASE + 0x044
-
- 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_AES128_KEY = 4
-
- SUPPORTS_ENCRYPTED_FLASH = True
-
- FLASH_ENCRYPTED_WRITE_ALIGN = 16
-
- MEMORY_MAP = []
-
- FLASH_FREQUENCY = {
- "48m": 0xF,
- "24m": 0x0,
- "16m": 0x1,
- "12m": 0x2,
- }
-
- def get_pkg_version(self):
- num_word = 3
- return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 21) & 0x0F
-
- def get_minor_chip_version(self):
- hi_num_word = 5
- hi = (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * hi_num_word)) >> 23) & 0x01
- low_num_word = 3
- low = (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * low_num_word)) >> 18) & 0x07
- return (hi << 3) + low
-
- def get_major_chip_version(self):
- num_word = 5
- return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 24) & 0x03
-
- def get_chip_description(self):
- chip_name = {
- 0: "ESP32-H2",
- }.get(self.get_pkg_version(), "unknown ESP32-H2")
- 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 ["BLE", "IEEE802.15.4"]
-
- def get_crystal_freq(self):
- return 32
-
- def override_vddsdio(self, new_voltage):
- raise NotImplementedInROMError(
- "VDD_SDIO overrides are not supported for ESP32-H2"
- )
-
- def read_mac(self):
- 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-H2
-
- 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 an AES-128 key
- purposes = [self.get_key_block_purpose(b) for b in range(6)]
-
- return any(p == self.PURPOSE_VAL_XTS_AES128_KEY for p in purposes)
-
- def _post_connect(self):
- pass
-
-
-class ESP32H2BETA1StubLoader(ESP32H2BETA1ROM):
- """Access class for ESP32H2BETA1 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
-
-
-ESP32H2BETA1ROM.STUB_CLASS = ESP32H2BETA1StubLoader
diff --git a/installer/bin/esptool/esptool/targets/esp32h2beta2.py b/installer/bin/esptool/esptool/targets/esp32h2beta2.py
deleted file mode 100644
index 6fa8f58..0000000
--- a/installer/bin/esptool/esptool/targets/esp32h2beta2.py
+++ /dev/null
@@ -1,43 +0,0 @@
-# SPDX-FileCopyrightText: 2014-2022 Fredrik Ahlberg, Angus Gratton,
-# Espressif Systems (Shanghai) CO LTD, other contributors as noted.
-#
-# SPDX-License-Identifier: GPL-2.0-or-later
-
-from .esp32h2beta1 import ESP32H2BETA1ROM
-
-
-class ESP32H2BETA2ROM(ESP32H2BETA1ROM):
- CHIP_NAME = "ESP32-H2(beta2)"
- IMAGE_CHIP_ID = 14
-
- CHIP_DETECT_MAGIC_VALUE = [0x6881B06F]
-
- def get_chip_description(self):
- chip_name = {
- 1: "ESP32-H2(beta2)",
- }.get(self.get_pkg_version(), "unknown ESP32-H2")
- major_rev = self.get_major_chip_version()
- minor_rev = self.get_minor_chip_version()
- return f"{chip_name} (revision v{major_rev}.{minor_rev})"
-
-
-class ESP32H2BETA2StubLoader(ESP32H2BETA2ROM):
- """Access class for ESP32H2BETA2 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
-
-
-ESP32H2BETA2ROM.STUB_CLASS = ESP32H2BETA2StubLoader
diff --git a/installer/bin/esptool/esptool/targets/esp32s2.py b/installer/bin/esptool/esptool/targets/esp32s2.py
deleted file mode 100644
index bffd553..0000000
--- a/installer/bin/esptool/esptool/targets/esp32s2.py
+++ /dev/null
@@ -1,305 +0,0 @@
-# SPDX-FileCopyrightText: 2014-2023 Fredrik Ahlberg, Angus Gratton,
-# Espressif Systems (Shanghai) CO LTD, other contributors as noted.
-#
-# SPDX-License-Identifier: GPL-2.0-or-later
-
-import os
-import struct
-
-from .esp32 import ESP32ROM
-from ..loader import ESPLoader
-from ..reset import HardReset
-from ..util import FatalError, NotImplementedInROMError
-
-
-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
- DROM_MAP_END = 0x3F3F0000
-
- CHIP_DETECT_MAGIC_VALUE = [0x000007C6]
-
- SPI_REG_BASE = 0x3F402000
- 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
-
- MAC_EFUSE_REG = 0x3F41A044 # ESP32-S2 has special block for MAC efuses
-
- UART_CLKDIV_REG = 0x3F400014
-
- SUPPORTS_ENCRYPTED_FLASH = True
-
- FLASH_ENCRYPTED_WRITE_ALIGN = 16
-
- # todo: use espefuse APIs to get this info
- EFUSE_BASE = 0x3F41A000
- EFUSE_RD_REG_BASE = EFUSE_BASE + 0x030 # BLOCK0 read base address
- EFUSE_BLOCK1_ADDR = EFUSE_BASE + 0x044
- EFUSE_BLOCK2_ADDR = EFUSE_BASE + 0x05C
-
- 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 << 19
-
- 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
-
- EFUSE_RD_REPEAT_DATA3_REG = EFUSE_BASE + 0x3C
- EFUSE_RD_REPEAT_DATA3_REG_FLASH_TYPE_MASK = 1 << 9
-
- PURPOSE_VAL_XTS_AES256_KEY_1 = 2
- PURPOSE_VAL_XTS_AES256_KEY_2 = 3
- PURPOSE_VAL_XTS_AES128_KEY = 4
-
- UARTDEV_BUF_NO = 0x3FFFFD14 # Variable in ROM .bss which indicates the port in use
- UARTDEV_BUF_NO_USB_OTG = 2 # Value of the above indicating that USB-OTG is in use
-
- USB_RAM_BLOCK = 0x800 # Max block size USB-OTG is used
-
- GPIO_STRAP_REG = 0x3F404038
- GPIO_STRAP_SPI_BOOT_MASK = 0x8 # Not download mode
- RTC_CNTL_OPTION1_REG = 0x3F408128
- RTC_CNTL_FORCE_DOWNLOAD_BOOT_MASK = 0x1 # Is download mode forced over USB?
-
- MEMORY_MAP = [
- [0x00000000, 0x00010000, "PADDING"],
- [0x3F000000, 0x3FF80000, "DROM"],
- [0x3F500000, 0x3FF80000, "EXTRAM_DATA"],
- [0x3FF9E000, 0x3FFA0000, "RTC_DRAM"],
- [0x3FF9E000, 0x40000000, "BYTE_ACCESSIBLE"],
- [0x3FF9E000, 0x40072000, "MEM_INTERNAL"],
- [0x3FFB0000, 0x40000000, "DRAM"],
- [0x40000000, 0x4001A100, "IROM_MASK"],
- [0x40020000, 0x40070000, "IRAM"],
- [0x40070000, 0x40072000, "RTC_IRAM"],
- [0x40080000, 0x40800000, "IROM"],
- [0x50000000, 0x50002000, "RTC_DATA"],
- ]
-
- def get_pkg_version(self):
- num_word = 4
- return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 0) & 0x0F
-
- def get_minor_chip_version(self):
- hi_num_word = 3
- hi = (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * hi_num_word)) >> 20) & 0x01
- low_num_word = 4
- low = (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * low_num_word)) >> 4) & 0x07
- return (hi << 3) + low
-
- def get_major_chip_version(self):
- num_word = 3
- return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 18) & 0x03
-
- def get_flash_version(self):
- num_word = 3
- return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 21) & 0x0F
-
- def get_psram_version(self):
- num_word = 3
- return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 28) & 0x0F
-
- def get_block2_version(self):
- # BLK_VERSION_MINOR
- num_word = 4
- return (self.read_reg(self.EFUSE_BLOCK2_ADDR + (4 * num_word)) >> 4) & 0x07
-
- def get_chip_description(self):
- chip_name = {
- 0: "ESP32-S2",
- 1: "ESP32-S2FH2",
- 2: "ESP32-S2FH4",
- 102: "ESP32-S2FNR2",
- 100: "ESP32-S2R2",
- }.get(
- self.get_flash_version() + self.get_psram_version() * 100,
- "unknown ESP32-S2",
- )
- 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):
- features = ["WiFi"]
-
- if self.secure_download_mode:
- features += ["Secure Download Mode Enabled"]
-
- flash_version = {
- 0: "No Embedded Flash",
- 1: "Embedded Flash 2MB",
- 2: "Embedded Flash 4MB",
- }.get(self.get_flash_version(), "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")
- features += [psram_version]
-
- block2_version = {
- 0: "No calibration in BLK2 of efuse",
- 1: "ADC and temperature sensor calibration in BLK2 of efuse V1",
- 2: "ADC and temperature sensor calibration in BLK2 of efuse V2",
- }.get(self.get_block2_version(), "Unknown Calibration in BLK2")
- features += [block2_version]
-
- return features
-
- def get_crystal_freq(self):
- # ESP32-S2 XTAL is fixed to 40MHz
- return 40
-
- def override_vddsdio(self, new_voltage):
- raise NotImplementedInROMError(
- "VDD_SDIO overrides are not supported for ESP32-S2"
- )
-
- def read_mac(self):
- 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 flash_type(self):
- return (
- 1
- if self.read_reg(self.EFUSE_RD_REPEAT_DATA3_REG)
- & self.EFUSE_RD_REPEAT_DATA3_REG_FLASH_TYPE_MASK
- else 0
- )
-
- def get_flash_crypt_config(self):
- return None # doesn't exist on ESP32-S2
-
- 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 uses_usb_otg(self):
- """
- Check the UARTDEV_BUF_NO register to see if USB-OTG console is being used
- """
- if self.secure_download_mode:
- return False # can't detect native USB in secure download mode
- return self.get_uart_no() == self.UARTDEV_BUF_NO_USB_OTG
-
- def _post_connect(self):
- if self.uses_usb_otg():
- self.ESP_RAM_BLOCK = self.USB_RAM_BLOCK
-
- def _check_if_can_reset(self):
- """
- Check the strapping register to see if we can reset out of download mode.
- """
- if os.getenv("ESPTOOL_TESTING") is not None:
- print("ESPTOOL_TESTING is set, ignoring strapping mode check")
- # Esptool tests over USB-OTG run with GPIO0 strapped low,
- # don't complain in this case.
- return
- strap_reg = self.read_reg(self.GPIO_STRAP_REG)
- force_dl_reg = self.read_reg(self.RTC_CNTL_OPTION1_REG)
- if (
- strap_reg & self.GPIO_STRAP_SPI_BOOT_MASK == 0
- and force_dl_reg & self.RTC_CNTL_FORCE_DOWNLOAD_BOOT_MASK == 0
- ):
- print(
- "WARNING: {} chip was placed into download mode using GPIO0.\n"
- "esptool.py can not exit the download mode over USB. "
- "To run the app, reset the chip manually.\n"
- "To suppress this note, set --after option to 'no_reset'.".format(
- self.get_chip_description()
- )
- )
- raise SystemExit(1)
-
- def hard_reset(self):
- uses_usb_otg = self.uses_usb_otg()
- if uses_usb_otg:
- self._check_if_can_reset()
-
- print("Hard resetting via RTS pin...")
- HardReset(self._port, uses_usb_otg)()
-
- def change_baud(self, baud):
- ESPLoader.change_baud(self, baud)
-
-
-class ESP32S2StubLoader(ESP32S2ROM):
- """Access class for ESP32-S2 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
-
- if rom_loader.uses_usb_otg():
- self.ESP_RAM_BLOCK = self.USB_RAM_BLOCK
- self.FLASH_WRITE_SIZE = self.USB_RAM_BLOCK
-
-
-ESP32S2ROM.STUB_CLASS = ESP32S2StubLoader
diff --git a/installer/bin/esptool/esptool/targets/esp32s3.py b/installer/bin/esptool/esptool/targets/esp32s3.py
deleted file mode 100644
index 660537b..0000000
--- a/installer/bin/esptool/esptool/targets/esp32s3.py
+++ /dev/null
@@ -1,315 +0,0 @@
-# SPDX-FileCopyrightText: 2014-2023 Fredrik Ahlberg, Angus Gratton,
-# Espressif Systems (Shanghai) CO LTD, other contributors as noted.
-#
-# SPDX-License-Identifier: GPL-2.0-or-later
-
-import os
-import struct
-
-from .esp32 import ESP32ROM
-from ..loader import ESPLoader
-from ..reset import HardReset
-from ..util import FatalError, NotImplementedInROMError
-
-
-class ESP32S3ROM(ESP32ROM):
- CHIP_NAME = "ESP32-S3"
-
- IMAGE_CHIP_ID = 9
-
- CHIP_DETECT_MAGIC_VALUE = [0x9]
-
- FPGA_SLOW_BOOT = False
-
- IROM_MAP_START = 0x42000000
- IROM_MAP_END = 0x44000000
- DROM_MAP_START = 0x3C000000
- DROM_MAP_END = 0x3E000000
-
- UART_DATE_REG_ADDR = 0x60000080
-
- SPI_REG_BASE = 0x60002000
- 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
-
- BOOTLOADER_FLASH_OFFSET = 0x0
-
- SUPPORTS_ENCRYPTED_FLASH = True
-
- FLASH_ENCRYPTED_WRITE_ALIGN = 16
-
- # todo: use espefuse APIs to get this info
- EFUSE_BASE = 0x60007000 # BLOCK0 read base address
- EFUSE_BLOCK1_ADDR = EFUSE_BASE + 0x44
- EFUSE_BLOCK2_ADDR = EFUSE_BASE + 0x5C
- MAC_EFUSE_REG = EFUSE_BASE + 0x044
-
- 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
-
- EFUSE_RD_REPEAT_DATA3_REG = EFUSE_BASE + 0x3C
- EFUSE_RD_REPEAT_DATA3_REG_FLASH_TYPE_MASK = 1 << 9
-
- PURPOSE_VAL_XTS_AES256_KEY_1 = 2
- PURPOSE_VAL_XTS_AES256_KEY_2 = 3
- PURPOSE_VAL_XTS_AES128_KEY = 4
-
- UARTDEV_BUF_NO = 0x3FCEF14C # Variable in ROM .bss which indicates the port in use
- UARTDEV_BUF_NO_USB_OTG = 3 # The above var when USB-OTG is used
- UARTDEV_BUF_NO_USB_JTAG_SERIAL = 4 # The above var when USB-JTAG/Serial is used
-
- RTC_CNTL_WDT_WKEY = 0x50D83AA1
- RTCCNTL_BASE_REG = 0x60008000
- RTC_CNTL_WDTCONFIG0_REG = RTCCNTL_BASE_REG + 0x0090
- RTC_CNTL_WDTWPROTECT_REG = RTCCNTL_BASE_REG + 0x00B0
-
- USB_RAM_BLOCK = 0x800 # Max block size USB-OTG is used
-
- GPIO_STRAP_REG = 0x60004038
- GPIO_STRAP_SPI_BOOT_MASK = 0x8 # Not download mode
- RTC_CNTL_OPTION1_REG = 0x6000812C
- RTC_CNTL_FORCE_DOWNLOAD_BOOT_MASK = 0x1 # Is download mode forced over USB?
-
- UART_CLKDIV_REG = 0x60000014
-
- MEMORY_MAP = [
- [0x00000000, 0x00010000, "PADDING"],
- [0x3C000000, 0x3D000000, "DROM"],
- [0x3D000000, 0x3E000000, "EXTRAM_DATA"],
- [0x600FE000, 0x60100000, "RTC_DRAM"],
- [0x3FC88000, 0x3FD00000, "BYTE_ACCESSIBLE"],
- [0x3FC88000, 0x403E2000, "MEM_INTERNAL"],
- [0x3FC88000, 0x3FD00000, "DRAM"],
- [0x40000000, 0x4001A100, "IROM_MASK"],
- [0x40370000, 0x403E0000, "IRAM"],
- [0x600FE000, 0x60100000, "RTC_IRAM"],
- [0x42000000, 0x42800000, "IROM"],
- [0x50000000, 0x50002000, "RTC_DATA"],
- ]
-
- def get_pkg_version(self):
- num_word = 3
- return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 21) & 0x07
-
- def is_eco0(self, minor_raw):
- # Workaround: The major version field was allocated to other purposes
- # when block version is v1.1.
- # Luckily only chip v0.0 have this kind of block version and efuse usage.
- return (
- (minor_raw & 0x7) == 0
- and self.get_blk_version_major() == 1
- and self.get_blk_version_minor() == 1
- )
-
- def get_minor_chip_version(self):
- minor_raw = self.get_raw_minor_chip_version()
- if self.is_eco0(minor_raw):
- return 0
- return minor_raw
-
- def get_raw_minor_chip_version(self):
- hi_num_word = 5
- hi = (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * hi_num_word)) >> 23) & 0x01
- low_num_word = 3
- low = (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * low_num_word)) >> 18) & 0x07
- return (hi << 3) + low
-
- def get_blk_version_major(self):
- num_word = 4
- return (self.read_reg(self.EFUSE_BLOCK2_ADDR + (4 * num_word)) >> 0) & 0x03
-
- def get_blk_version_minor(self):
- num_word = 3
- return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 24) & 0x07
-
- def get_major_chip_version(self):
- minor_raw = self.get_raw_minor_chip_version()
- if self.is_eco0(minor_raw):
- return 0
- return self.get_raw_major_chip_version()
-
- def get_raw_major_chip_version(self):
- num_word = 5
- return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 24) & 0x03
-
- 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})"
-
- def get_chip_features(self):
- return ["WiFi", "BLE"]
-
- def get_crystal_freq(self):
- # ESP32S3 XTAL is fixed to 40MHz
- return 40
-
- def get_flash_crypt_config(self):
- return None # doesn't exist on ESP32-S3
-
- 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 get_secure_boot_enabled(self):
- return (
- self.read_reg(self.EFUSE_SECURE_BOOT_EN_REG)
- & self.EFUSE_SECURE_BOOT_EN_MASK
- )
-
- def override_vddsdio(self, new_voltage):
- raise NotImplementedInROMError(
- "VDD_SDIO overrides are not supported for ESP32-S3"
- )
-
- def read_mac(self):
- 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 flash_type(self):
- return (
- 1
- if self.read_reg(self.EFUSE_RD_REPEAT_DATA3_REG)
- & self.EFUSE_RD_REPEAT_DATA3_REG_FLASH_TYPE_MASK
- else 0
- )
-
- def uses_usb_otg(self):
- """
- Check the UARTDEV_BUF_NO register to see if USB-OTG console is being used
- """
- if self.secure_download_mode:
- return False # can't detect native USB in secure download mode
- return self.get_uart_no() == self.UARTDEV_BUF_NO_USB_OTG
-
- def uses_usb_jtag_serial(self):
- """
- Check the UARTDEV_BUF_NO register to see if USB-JTAG/Serial is being used
- """
- if self.secure_download_mode:
- return False # can't detect USB-JTAG/Serial in secure download mode
- return self.get_uart_no() == self.UARTDEV_BUF_NO_USB_JTAG_SERIAL
-
- def disable_rtc_watchdog(self):
- # When USB-JTAG/Serial is used, the RTC watchdog is not reset
- # and can then reset the board during flashing. Disable it.
- if self.uses_usb_jtag_serial():
- self.write_reg(self.RTC_CNTL_WDTWPROTECT_REG, self.RTC_CNTL_WDT_WKEY)
- self.write_reg(self.RTC_CNTL_WDTCONFIG0_REG, 0)
- self.write_reg(self.RTC_CNTL_WDTWPROTECT_REG, 0)
-
- def _post_connect(self):
- if self.uses_usb_otg():
- self.ESP_RAM_BLOCK = self.USB_RAM_BLOCK
- if not self.sync_stub_detected: # Don't run if stub is reused
- self.disable_rtc_watchdog()
-
- def _check_if_can_reset(self):
- """
- Check the strapping register to see if we can reset out of download mode.
- """
- if os.getenv("ESPTOOL_TESTING") is not None:
- print("ESPTOOL_TESTING is set, ignoring strapping mode check")
- # Esptool tests over USB-OTG run with GPIO0 strapped low,
- # don't complain in this case.
- return
- strap_reg = self.read_reg(self.GPIO_STRAP_REG)
- force_dl_reg = self.read_reg(self.RTC_CNTL_OPTION1_REG)
- if (
- strap_reg & self.GPIO_STRAP_SPI_BOOT_MASK == 0
- and force_dl_reg & self.RTC_CNTL_FORCE_DOWNLOAD_BOOT_MASK == 0
- ):
- print(
- "WARNING: {} chip was placed into download mode using GPIO0.\n"
- "esptool.py can not exit the download mode over USB. "
- "To run the app, reset the chip manually.\n"
- "To suppress this note, set --after option to 'no_reset'.".format(
- self.get_chip_description()
- )
- )
- raise SystemExit(1)
-
- def hard_reset(self):
- uses_usb_otg = self.uses_usb_otg()
- if uses_usb_otg:
- self._check_if_can_reset()
-
- print("Hard resetting via RTS pin...")
- HardReset(self._port, uses_usb_otg)()
-
- def change_baud(self, baud):
- ESPLoader.change_baud(self, baud)
-
-
-class ESP32S3StubLoader(ESP32S3ROM):
- """Access class for ESP32S3 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
-
- if rom_loader.uses_usb_otg():
- self.ESP_RAM_BLOCK = self.USB_RAM_BLOCK
- self.FLASH_WRITE_SIZE = self.USB_RAM_BLOCK
-
-
-ESP32S3ROM.STUB_CLASS = ESP32S3StubLoader
diff --git a/installer/bin/esptool/esptool/targets/esp32s3beta2.py b/installer/bin/esptool/esptool/targets/esp32s3beta2.py
deleted file mode 100644
index b7958bd..0000000
--- a/installer/bin/esptool/esptool/targets/esp32s3beta2.py
+++ /dev/null
@@ -1,42 +0,0 @@
-# SPDX-FileCopyrightText: 2014-2022 Fredrik Ahlberg, Angus Gratton,
-# Espressif Systems (Shanghai) CO LTD, other contributors as noted.
-#
-# SPDX-License-Identifier: GPL-2.0-or-later
-
-from .esp32s3 import ESP32S3ROM
-
-
-class ESP32S3BETA2ROM(ESP32S3ROM):
- CHIP_NAME = "ESP32-S3(beta2)"
- IMAGE_CHIP_ID = 4
-
- CHIP_DETECT_MAGIC_VALUE = [0xEB004136]
-
- 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.
-
- (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
-
-
-ESP32S3BETA2ROM.STUB_CLASS = ESP32S3BETA2StubLoader
diff --git a/installer/bin/esptool/esptool/targets/esp8266.py b/installer/bin/esptool/esptool/targets/esp8266.py
deleted file mode 100644
index f996663..0000000
--- a/installer/bin/esptool/esptool/targets/esp8266.py
+++ /dev/null
@@ -1,191 +0,0 @@
-# SPDX-FileCopyrightText: 2014-2022 Fredrik Ahlberg, Angus Gratton,
-# Espressif Systems (Shanghai) CO LTD, other contributors as noted.
-#
-# SPDX-License-Identifier: GPL-2.0-or-later
-
-from ..loader import ESPLoader
-from ..util import FatalError, NotImplementedInROMError
-
-
-class ESP8266ROM(ESPLoader):
- """Access class for ESP8266 ROM bootloader"""
-
- CHIP_NAME = "ESP8266"
- IS_STUB = False
-
- CHIP_DETECT_MAGIC_VALUE = [0xFFF0C101]
-
- # OTP ROM addresses
- ESP_OTP_MAC0 = 0x3FF00050
- ESP_OTP_MAC1 = 0x3FF00054
- ESP_OTP_MAC3 = 0x3FF0005C
-
- SPI_REG_BASE = 0x60000200
- SPI_USR_OFFS = 0x1C
- SPI_USR1_OFFS = 0x20
- SPI_USR2_OFFS = 0x24
- SPI_MOSI_DLEN_OFFS = None
- SPI_MISO_DLEN_OFFS = None
- SPI_W0_OFFS = 0x40
-
- UART_CLKDIV_REG = 0x60000014
-
- XTAL_CLK_DIVIDER = 2
-
- FLASH_SIZES = {
- "512KB": 0x00,
- "256KB": 0x10,
- "1MB": 0x20,
- "2MB": 0x30,
- "4MB": 0x40,
- "2MB-c1": 0x50,
- "4MB-c1": 0x60,
- "8MB": 0x80,
- "16MB": 0x90,
- }
-
- FLASH_FREQUENCY = {
- "80m": 0xF,
- "40m": 0x0,
- "26m": 0x1,
- "20m": 0x2,
- }
-
- BOOTLOADER_FLASH_OFFSET = 0
-
- MEMORY_MAP = [
- [0x3FF00000, 0x3FF00010, "DPORT"],
- [0x3FFE8000, 0x40000000, "DRAM"],
- [0x40100000, 0x40108000, "IRAM"],
- [0x40201010, 0x402E1010, "IROM"],
- ]
-
- def get_efuses(self):
- # Return the 128 bits of ESP8266 efuse as a single Python integer
- result = self.read_reg(0x3FF0005C) << 96
- result |= self.read_reg(0x3FF00058) << 64
- result |= self.read_reg(0x3FF00054) << 32
- result |= self.read_reg(0x3FF00050)
- return result
-
- def _get_flash_size(self, efuses):
- # rX_Y = EFUSE_DATA_OUTX[Y]
- r0_4 = (efuses & (1 << 4)) != 0
- r3_25 = (efuses & (1 << 121)) != 0
- r3_26 = (efuses & (1 << 122)) != 0
- r3_27 = (efuses & (1 << 123)) != 0
-
- if r0_4 and not r3_25:
- if not r3_27 and not r3_26:
- return 1
- elif not r3_27 and r3_26:
- return 2
- if not r0_4 and r3_25:
- if not r3_27 and not r3_26:
- return 2
- elif not r3_27 and r3_26:
- return 4
- return -1
-
- def get_chip_description(self):
- efuses = self.get_efuses()
- is_8285 = (
- efuses & ((1 << 4) | 1 << 80)
- ) != 0 # One or the other efuse bit is set for ESP8285
- if is_8285:
- flash_size = self._get_flash_size(efuses)
- max_temp = (
- efuses & (1 << 5)
- ) != 0 # This efuse bit identifies the max flash temperature
- chip_name = {
- 1: "ESP8285H08" if max_temp else "ESP8285N08",
- 2: "ESP8285H16" if max_temp else "ESP8285N16",
- }.get(flash_size, "ESP8285")
- return chip_name
- return "ESP8266EX"
-
- def get_chip_features(self):
- features = ["WiFi"]
- if "ESP8285" in self.get_chip_description():
- features += ["Embedded Flash"]
- return features
-
- def flash_spi_attach(self, hspi_arg):
- if self.IS_STUB:
- super(ESP8266ROM, self).flash_spi_attach(hspi_arg)
- else:
- # ESP8266 ROM has no flash_spi_attach command in serial protocol,
- # but flash_begin will do it
- self.flash_begin(0, 0)
-
- def flash_set_parameters(self, size):
- # not implemented in ROM, but OK to silently skip for ROM
- if self.IS_STUB:
- super(ESP8266ROM, self).flash_set_parameters(size)
-
- def chip_id(self):
- """
- Read Chip ID from efuse - the equivalent of the SDK system_get_chip_id() func
- """
- id0 = self.read_reg(self.ESP_OTP_MAC0)
- id1 = self.read_reg(self.ESP_OTP_MAC1)
- return (id0 >> 24) | ((id1 & 0xFFFFFF) << 8)
-
- def read_mac(self):
- """Read MAC from OTP ROM"""
- mac0 = self.read_reg(self.ESP_OTP_MAC0)
- mac1 = self.read_reg(self.ESP_OTP_MAC1)
- mac3 = self.read_reg(self.ESP_OTP_MAC3)
- if mac3 != 0:
- oui = ((mac3 >> 16) & 0xFF, (mac3 >> 8) & 0xFF, mac3 & 0xFF)
- elif ((mac1 >> 16) & 0xFF) == 0:
- oui = (0x18, 0xFE, 0x34)
- elif ((mac1 >> 16) & 0xFF) == 1:
- oui = (0xAC, 0xD0, 0x74)
- else:
- raise FatalError("Unknown OUI")
- return oui + ((mac1 >> 8) & 0xFF, mac1 & 0xFF, (mac0 >> 24) & 0xFF)
-
- def get_erase_size(self, offset, size):
- """Calculate an erase size given a specific size in bytes.
-
- Provides a workaround for the bootloader erase bug."""
-
- sectors_per_block = 16
- sector_size = self.FLASH_SECTOR_SIZE
- num_sectors = (size + sector_size - 1) // sector_size
- start_sector = offset // sector_size
-
- head_sectors = sectors_per_block - (start_sector % sectors_per_block)
- if num_sectors < head_sectors:
- head_sectors = num_sectors
-
- if num_sectors < 2 * head_sectors:
- return (num_sectors + 1) // 2 * sector_size
- else:
- return (num_sectors - head_sectors) * sector_size
-
- def override_vddsdio(self, new_voltage):
- raise NotImplementedInROMError(
- "Overriding VDDSDIO setting only applies to ESP32"
- )
-
-
-class ESP8266StubLoader(ESP8266ROM):
- """Access class for ESP8266 stub loader, runs on top of ROM."""
-
- FLASH_WRITE_SIZE = 0x4000 # matches MAX_WRITE_BLOCK in stub_loader.c
- 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
-
- def get_erase_size(self, offset, size):
- return size # stub doesn't have same size bug as ROM loader
-
-
-ESP8266ROM.STUB_CLASS = ESP8266StubLoader
diff --git a/installer/bin/esptool/esptool/targets/stub_flasher/stub_flasher_32.json b/installer/bin/esptool/esptool/targets/stub_flasher/stub_flasher_32.json
deleted file mode 100644
index 3e87d81..0000000
--- a/installer/bin/esptool/esptool/targets/stub_flasher/stub_flasher_32.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "entry": 1074521560,
- "text": "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",
- "text_start": 1074520064,
- "data": "GOv8P9jnC0Bx6AtA8+wLQO3oC0CP6AtA7egLQEnpC0AG6gtAeOoLQCHqC0CB5wtAo+kLQPjpC0Bn6QtAmuoLQI7pC0Ca6gtAXegLQLPoC0Dt6AtASekLQHfoC0BM6wtAs+wLQKXmC0DX7AtApeYLQKXmC0Cl5gtApeYLQKXmC0Cl5gtApeYLQKXmC0Dz6gtApeYLQM3rC0Cz7AtA",
- "data_start": 1073605544
-}
\ No newline at end of file
diff --git a/installer/bin/esptool/esptool/targets/stub_flasher/stub_flasher_32c2.json b/installer/bin/esptool/esptool/targets/stub_flasher/stub_flasher_32c2.json
deleted file mode 100644
index 07887d4..0000000
--- a/installer/bin/esptool/esptool/targets/stub_flasher/stub_flasher_32c2.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "entry": 1077413304,
- "text": "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",
- "text_start": 1077411840,
- "data": "GGvKP+AIOEAsCThAhAk4QCgKOECUCjhAQgo4QKgHOEDkCThAJAo4QJgJOEBYBzhAzAk4QFgHOEC6CDhA/gg4QCwJOECECThAzAg4QBIIOEBCCDhAyAg4QOYMOEAsCThArAs4QJoMOECkBjhAxAw4QKQGOECkBjhApAY4QKQGOECkBjhApAY4QKQGOECkBjhASAs4QKQGOEDICzhAmgw4QA==",
- "data_start": 1070295976
-}
\ No newline at end of file
diff --git a/installer/bin/esptool/esptool/targets/stub_flasher/stub_flasher_32c3.json b/installer/bin/esptool/esptool/targets/stub_flasher/stub_flasher_32c3.json
deleted file mode 100644
index 8426a63..0000000
--- a/installer/bin/esptool/esptool/targets/stub_flasher/stub_flasher_32c3.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "entry": 1077413532,
- "text": "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",
- "text_start": 1077411840,
- "data": "IGvIP1YKOECmCjhA/go4QKILOEAODDhAvAs4QCIJOEBeCzhAngs4QBILOEDSCDhARgs4QNIIOEAwCjhAdgo4QKYKOED+CjhAQgo4QIYJOEC2CThAPgo4QGAOOECmCjhAJg04QBgOOEASCDhAQA44QBIIOEASCDhAEgg4QBIIOEASCDhAEgg4QBIIOEASCDhAwgw4QBIIOEBEDThAGA44QA==",
- "data_start": 1070164912
-}
\ No newline at end of file
diff --git a/installer/bin/esptool/esptool/targets/stub_flasher/stub_flasher_32c6.json b/installer/bin/esptool/esptool/targets/stub_flasher/stub_flasher_32c6.json
deleted file mode 100644
index 2bf3acc..0000000
--- a/installer/bin/esptool/esptool/targets/stub_flasher/stub_flasher_32c6.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "entry": 1082132112,
- "text": "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",
- "text_start": 1082130432,
- "data": "HCuEQCoKgEB6CoBA0gqAQHYLgEDiC4BAkAuAQPYIgEAyC4BAcguAQOYKgECmCIBAGguAQKYIgEAECoBASgqAQHoKgEDSCoBAFgqAQFoJgECKCYBAEgqAQDQOgEB6CoBA+gyAQOwNgEDmB4BAFA6AQOYHgEDmB4BA5geAQOYHgEDmB4BA5geAQOYHgEDmB4BAlgyAQOYHgEAYDYBA7A2AQA==",
- "data_start": 1082469292
-}
\ No newline at end of file
diff --git a/installer/bin/esptool/esptool/targets/stub_flasher/stub_flasher_32c6beta.json b/installer/bin/esptool/esptool/targets/stub_flasher/stub_flasher_32c6beta.json
deleted file mode 100644
index 4709f9d..0000000
--- a/installer/bin/esptool/esptool/targets/stub_flasher/stub_flasher_32c6beta.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "entry": 1077413318,
- "text": "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",
- "text_start": 1077411840,
- "data": "GGvIP/gIOEBECThAnAk4QEAKOECsCjhAWgo4QMAHOED8CThAPAo4QLAJOEBwBzhA5Ak4QHAHOEDSCDhAFgk4QEQJOECcCThA5Ag4QCoIOEBaCDhA4Ag4QP4MOEBECThAxAs4QLIMOEC8BjhA3Aw4QLwGOEC8BjhAvAY4QLwGOEC8BjhAvAY4QLwGOEC8BjhAYAs4QLwGOEDgCzhAsgw4QA==",
- "data_start": 1070164904
-}
\ No newline at end of file
diff --git a/installer/bin/esptool/esptool/targets/stub_flasher/stub_flasher_32h2.json b/installer/bin/esptool/esptool/targets/stub_flasher/stub_flasher_32h2.json
deleted file mode 100644
index f003a55..0000000
--- a/installer/bin/esptool/esptool/targets/stub_flasher/stub_flasher_32h2.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "entry": 1082132112,
- "text": "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",
- "text_start": 1082130432,
- "data": "HCuDQCoKgEB6CoBA0gqAQHYLgEDiC4BAkAuAQPYIgEAyC4BAcguAQOYKgECmCIBAGguAQKYIgEAECoBASgqAQHoKgEDSCoBAFgqAQFoJgECKCYBAEgqAQDQOgEB6CoBA+gyAQOwNgEDmB4BAFA6AQOYHgEDmB4BA5geAQOYHgEDmB4BA5geAQOYHgEDmB4BAlgyAQOYHgEAYDYBA7A2AQA==",
- "data_start": 1082403756
-}
\ No newline at end of file
diff --git a/installer/bin/esptool/esptool/targets/stub_flasher/stub_flasher_32h2beta1.json b/installer/bin/esptool/esptool/targets/stub_flasher/stub_flasher_32h2beta1.json
deleted file mode 100644
index 37d29e8..0000000
--- a/installer/bin/esptool/esptool/targets/stub_flasher/stub_flasher_32h2beta1.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "entry": 1077413318,
- "text": "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",
- "text_start": 1077411840,
- "data": "GGvIP/gIOEBECThAnAk4QEAKOECsCjhAWgo4QMAHOED8CThAPAo4QLAJOEBwBzhA5Ak4QHAHOEDSCDhAFgk4QEQJOECcCThA5Ag4QCoIOEBaCDhA4Ag4QP4MOEBECThAxAs4QLIMOEC8BjhA3Aw4QLwGOEC8BjhAvAY4QLwGOEC8BjhAvAY4QLwGOEC8BjhAYAs4QLwGOEDgCzhAsgw4QA==",
- "data_start": 1070164904
-}
\ No newline at end of file
diff --git a/installer/bin/esptool/esptool/targets/stub_flasher/stub_flasher_32h2beta2.json b/installer/bin/esptool/esptool/targets/stub_flasher/stub_flasher_32h2beta2.json
deleted file mode 100644
index f7cc1ce..0000000
--- a/installer/bin/esptool/esptool/targets/stub_flasher/stub_flasher_32h2beta2.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "entry": 1077413318,
- "text": "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",
- "text_start": 1077411840,
- "data": "GGvIP/gIOEBECThAnAk4QEAKOECsCjhAWgo4QMAHOED8CThAPAo4QLAJOEBwBzhA5Ak4QHAHOEDSCDhAFgk4QEQJOECcCThA5Ag4QCoIOEBaCDhA4Ag4QP4MOEBECThAxAs4QLIMOEC8BjhA3Aw4QLwGOEC8BjhAvAY4QLwGOEC8BjhAvAY4QLwGOEC8BjhAYAs4QLwGOEDgCzhAsgw4QA==",
- "data_start": 1070164904
-}
\ No newline at end of file
diff --git a/installer/bin/esptool/esptool/targets/stub_flasher/stub_flasher_32s2.json b/installer/bin/esptool/esptool/targets/stub_flasher/stub_flasher_32s2.json
deleted file mode 100644
index de8cdc2..0000000
--- a/installer/bin/esptool/esptool/targets/stub_flasher/stub_flasher_32s2.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "entry": 1073907696,
- "text": "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",
- "text_start": 1073905664,
- "data": "ZCv9PzaLAkDBiwJAhpACQEqMAkDjiwJASowCQKmMAkByjQJA5Y0CQI2NAkDAigJAC40CQGSNAkDMjAJACI4CQPaMAkAIjgJAr4sCQA6MAkBKjAJAqYwCQMeLAkACiwJAx44CQD2QAkDYiQJAZZACQNiJAkDYiQJA2IkCQNiJAkDYiQJA2IkCQNiJAkDYiQJAZI4CQNiJAkBZjwJAPZACQA==",
- "data_start": 1073622012
-}
\ No newline at end of file
diff --git a/installer/bin/esptool/esptool/targets/stub_flasher/stub_flasher_32s3.json b/installer/bin/esptool/esptool/targets/stub_flasher/stub_flasher_32s3.json
deleted file mode 100644
index 1a73fca..0000000
--- a/installer/bin/esptool/esptool/targets/stub_flasher/stub_flasher_32s3.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "entry": 1077381684,
- "text": "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",
- "text_start": 1077379072,
- "data": "ZCvKP5aNN0B7jjdAPJM3QAaPN0CbjjdABo83QGWPN0AykDdApZA3QE2QN0AhjTdAyI83QCSQN0CIjzdAx5A3QLKPN0DHkDdAaY43QMaON0AGjzdAZY83QIGON0BijTdAiJE3QAKTN0A+jDdAIpM3QD6MN0A+jDdAPow3QD6MN0A+jDdAPow3QD6MN0A+jDdAIpE3QD6MN0AdkjdAApM3QAQInwAAAAAAAAAYAQQIBQAAAAAAAAAIAQQIBgAAAAAAAAAAAQQIIQAAAAAAIAAAEQQI3AAAAAAAIAAAEQQIDAAAAAAAIAAAAQQIEgAAAAAAIAAAESAoDAAQAQAA",
- "data_start": 1070279668
-}
\ No newline at end of file
diff --git a/installer/bin/esptool/esptool/targets/stub_flasher/stub_flasher_32s3beta2.json b/installer/bin/esptool/esptool/targets/stub_flasher/stub_flasher_32s3beta2.json
deleted file mode 100644
index 8621a93..0000000
--- a/installer/bin/esptool/esptool/targets/stub_flasher/stub_flasher_32s3beta2.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "entry": 1077381176,
- "text": "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",
- "text_start": 1077379072,
- "data": "ZCvKP4KLN0APjDdA15A3QJqMN0AvjDdAmow3QPmMN0DGjTdAOY43QOGNN0ANizdAXI03QLiNN0AcjTdAXI43QEaNN0BcjjdA/Ys3QFqMN0CajDdA+Yw3QBWMN0BOizdAHI83QJuQN0AsijdAvZA3QCyKN0AsijdALIo3QCyKN0AsijdALIo3QCyKN0AsijdAto43QCyKN0CyjzdAm5A3QA==",
- "data_start": 1070279668
-}
\ No newline at end of file
diff --git a/installer/bin/esptool/esptool/targets/stub_flasher/stub_flasher_8266.json b/installer/bin/esptool/esptool/targets/stub_flasher/stub_flasher_8266.json
deleted file mode 100644
index 8d42b24..0000000
--- a/installer/bin/esptool/esptool/targets/stub_flasher/stub_flasher_8266.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "entry": 1074843652,
- "text": "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",
- "text_start": 1074843648,
- "data": "CIH+PwUFBAACAwcAAwMLALnXEEDv1xBAHdgQQLrYEEBo5xBAHtkQQHTZEEDA2RBAaOcQQILaEED/2hBAwNsQQGjnEEBo5xBAWNwQQGjnEEA33xBAAOAQQDvgEEBo5xBAaOcQQNfgEEBo5xBAv+EQQGXiEECj4xBAY+QQQDTlEEBo5xBAaOcQQGjnEEBo5xBAYuYQQGjnEEBX5xBAkN0QQI/YEECm5RBAq9oQQPzZEEBo5xBA7OYQQDHnEEBo5xBAaOcQQGjnEEBo5xBAaOcQQGjnEEBo5xBAaOcQQCLaEEBf2hBAvuUQQAEAAAACAAAAAwAAAAQAAAAFAAAABwAAAAkAAAANAAAAEQAAABkAAAAhAAAAMQAAAEEAAABhAAAAgQAAAMEAAAABAQAAgQEAAAECAAABAwAAAQQAAAEGAAABCAAAAQwAAAEQAAABGAAAASAAAAEwAAABQAAAAWAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAgAAAAIAAAADAAAAAwAAAAQAAAAEAAAABQAAAAUAAAAGAAAABgAAAAcAAAAHAAAACAAAAAgAAAAJAAAACQAAAAoAAAAKAAAACwAAAAsAAAAMAAAADAAAAA0AAAANAAAAAAAAAAAAAAADAAAABAAAAAUAAAAGAAAABwAAAAgAAAAJAAAACgAAAAsAAAANAAAADwAAABEAAAATAAAAFwAAABsAAAAfAAAAIwAAACsAAAAzAAAAOwAAAEMAAABTAAAAYwAAAHMAAACDAAAAowAAAMMAAADjAAAAAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAEAAAABAAAAAgAAAAIAAAACAAAAAgAAAAMAAAADAAAAAwAAAAMAAAAEAAAABAAAAAQAAAAEAAAABQAAAAUAAAAFAAAABQAAAAAAAAAAAAAAAAAAABAREgAIBwkGCgULBAwDDQIOAQ8AAQEAAAEAAAAEAAAA",
- "data_start": 1073720488
-}
\ No newline at end of file
diff --git a/installer/bin/esptool/esptool/util.py b/installer/bin/esptool/esptool/util.py
deleted file mode 100644
index 66d9bd4..0000000
--- a/installer/bin/esptool/esptool/util.py
+++ /dev/null
@@ -1,174 +0,0 @@
-# SPDX-FileCopyrightText: 2014-2022 Fredrik Ahlberg, Angus Gratton,
-# Espressif Systems (Shanghai) CO LTD, other contributors as noted.
-#
-# SPDX-License-Identifier: GPL-2.0-or-later
-
-import re
-import struct
-import sys
-
-
-def byte(bitstr, index):
- return bitstr[index]
-
-
-def mask_to_shift(mask):
- """Return the index of the least significant bit in the mask"""
- shift = 0
- while mask & 0x1 == 0:
- shift += 1
- mask >>= 1
- return shift
-
-
-def div_roundup(a, b):
- """Return a/b rounded up to nearest integer,
- equivalent result to int(math.ceil(float(int(a)) / float(int(b))), only
- without possible floating point accuracy errors.
- """
- return (int(a) + int(b) - 1) // int(b)
-
-
-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 "MB" in size:
- return int(size[: size.index("MB")]) * 1024 * 1024
- elif "KB" in size:
- return int(size[: size.index("KB")]) * 1024
- else:
- raise FatalError("Unknown size %s" % size)
-
-
-def hexify(s, uppercase=True):
- format_str = "%02X" if uppercase else "%02x"
- return "".join(format_str % c for c in s)
-
-
-def pad_to(data, alignment, pad_character=b"\xFF"):
- """Pad to the next alignment boundary"""
- pad_mod = len(data) % alignment
- if pad_mod != 0:
- data += pad_character * (alignment - pad_mod)
- return data
-
-
-def print_overwrite(message, last_line=False):
- """Print a message, overwriting the currently printed line.
-
- If last_line is False, don't append a newline at the end
- (expecting another subsequent call will overwrite this one.)
-
- After a sequence of calls with last_line=False, call once with last_line=True.
-
- 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():
- print("\r%s" % message, end="\n" if last_line else "")
- else:
- print(message)
-
-
-def expand_chip_name(chip_name):
- """Change chip name to official form, e.g. `esp32s3beta2` -> `ESP32-S3(beta2)`"""
- # Put "-" after "esp32"
- chip_name = re.sub(r"(esp32)(?!$)", r"\1-", chip_name)
- # Put "()" around "betaN"
- chip_name = re.sub(r"(beta\d*)", r"(\1)", chip_name)
- # Uppercase everything before "(betaN)"
- chip_name = re.sub(r"^[^\(]+", lambda x: x.group(0).upper(), chip_name)
- return chip_name
-
-
-def strip_chip_name(chip_name):
- """Strip chip name to normalized form, e.g. `ESP32-S3(beta2)` -> `esp32s3beta2`"""
- return re.sub(r"[-()]", "", chip_name.lower())
-
-
-class FatalError(RuntimeError):
- """
- Wrapper class for runtime errors that aren't caused by internal bugs, but by
- ESP ROM responses or input content.
- """
-
- def __init__(self, message):
- RuntimeError.__init__(self, message)
-
- @staticmethod
- def WithResult(message, result):
- """
- Return a fatal error object that appends the hex values of
- 'result' and its meaning as a string formatted argument.
- """
-
- err_defs = {
- # ROM error codes
- 0x101: "Out of memory",
- 0x102: "Invalid argument",
- 0x103: "Invalid state",
- 0x104: "Invalid size",
- 0x105: "Requested resource not found",
- 0x106: "Operation or feature not supported",
- 0x107: "Operation timed out",
- 0x108: "Received response was invalid",
- 0x109: "CRC or checksum was invalid",
- 0x10A: "Version was invalid",
- 0x10B: "MAC address was invalid",
- # Flasher stub error codes
- 0xC000: "Bad data length",
- 0xC100: "Bad data checksum",
- 0xC200: "Bad blocksize",
- 0xC300: "Invalid command",
- 0xC400: "Failed SPI operation",
- 0xC500: "Failed SPI unlock",
- 0xC600: "Not in flash mode",
- 0xC700: "Inflate error",
- 0xC800: "Not enough data",
- 0xC900: "Too much data",
- 0xFF00: "Command not implemented",
- }
-
- err_code = struct.unpack(">H", result[:2])
- message += " (result was {}: {})".format(
- hexify(result), err_defs.get(err_code[0], "Unknown result")
- )
- return FatalError(message)
-
-
-class NotImplementedInROMError(FatalError):
- """
- Wrapper class for the error thrown when a particular ESP bootloader function
- is not implemented in the ROM bootloader.
- """
-
- def __init__(self, bootloader, func):
- FatalError.__init__(
- self,
- "%s ROM does not support function %s."
- % (bootloader.CHIP_NAME, func.__name__),
- )
-
-
-class NotSupportedError(FatalError):
- def __init__(self, esp, function_name):
- FatalError.__init__(
- self,
- "Function %s is not supported for %s." % (function_name, esp.CHIP_NAME),
- )
-
-
-class UnsupportedCommandError(RuntimeError):
- """
- Wrapper class for when ROM loader returns an invalid command response.
-
- Usually this indicates the loader is running in Secure Download Mode.
- """
-
- def __init__(self, esp, op):
- if esp.secure_download_mode:
- msg = "This command (0x%x) is not supported in Secure Download Mode" % op
- else:
- msg = "Invalid (unsupported) command 0x%x" % op
- RuntimeError.__init__(self, msg)