feat(core): 更新py-esptool (version: 4.8.1)
This commit is contained in:
@@ -10,31 +10,33 @@ import struct
|
||||
import sys
|
||||
import time
|
||||
import zlib
|
||||
import itertools
|
||||
|
||||
from intelhex import IntelHex
|
||||
from serial import SerialException
|
||||
|
||||
from bin_image import ELFFile, ImageSegment, LoadFirmwareImage
|
||||
from bin_image import (
|
||||
from .bin_image import ELFFile, ImageSegment, LoadFirmwareImage
|
||||
from .bin_image import (
|
||||
ESP8266ROMFirmwareImage,
|
||||
ESP8266V2FirmwareImage,
|
||||
ESP8266V3FirmwareImage,
|
||||
)
|
||||
from loader import (
|
||||
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 uf2_writer import UF2Writer
|
||||
from util import (
|
||||
from .targets import CHIP_DEFS, CHIP_LIST, ROM_LIST
|
||||
from .uf2_writer import UF2Writer
|
||||
from .util import (
|
||||
FatalError,
|
||||
NotImplementedInROMError,
|
||||
NotSupportedError,
|
||||
UnsupportedCommandError,
|
||||
)
|
||||
from util import (
|
||||
from .util import (
|
||||
div_roundup,
|
||||
flash_size_bytes,
|
||||
get_file_size,
|
||||
@@ -115,7 +117,7 @@ def detect_chip(
|
||||
else:
|
||||
err_msg = f"Unexpected chip ID value {chip_id}."
|
||||
except (UnsupportedCommandError, struct.error, FatalError) as e:
|
||||
# UnsupportedCommmanddError: ESP8266/ESP32 ROM
|
||||
# UnsupportedCommandError: ESP8266/ESP32 ROM
|
||||
# struct.error: ESP32-S2
|
||||
# FatalError: ESP8266/ESP32 STUB
|
||||
print(" Unsupported detection protocol, switching and trying again...")
|
||||
@@ -229,7 +231,7 @@ def detect_flash_size(esp, args=None):
|
||||
if flash_size is None:
|
||||
flash_size = "4MB"
|
||||
print(
|
||||
"Warning: Could not auto-detect Flash size "
|
||||
"WARNING: Could not auto-detect Flash size "
|
||||
f"(FlashID={flash_id:#x}, SizeID={size_id:#x}), defaulting to 4MB"
|
||||
)
|
||||
else:
|
||||
@@ -276,49 +278,60 @@ def _update_image_flash_params(esp, address, args, 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
|
||||
)
|
||||
)
|
||||
# a SHA256 checksum. In that case we recalculate the SHA digest after modifying the header.
|
||||
sha_appended = args.chip != "esp8266" and image[8 + 15] == 1
|
||||
|
||||
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_mode = FLASH_MODES[args.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_freq = esp.parse_flash_freq_arg(args.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_size = esp.parse_flash_size_arg(args.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:]
|
||||
|
||||
# recalculate the SHA digest if it was appended
|
||||
if sha_appended:
|
||||
# Since the changes are only made for images located in the bootloader offset,
|
||||
# we can assume that the image is always a bootloader image.
|
||||
# For merged binaries, we check the bootloader SHA when parameters are changed.
|
||||
image_object = esp.BOOTLOADER_IMAGE(io.BytesIO(image))
|
||||
# get the image header, extended header (if present) and data
|
||||
image_data_before_sha = image[: image_object.data_length]
|
||||
# get the image data after the SHA digest (primary for merged binaries)
|
||||
image_data_after_sha = image[
|
||||
(image_object.data_length + image_object.SHA256_DIGEST_LEN) :
|
||||
]
|
||||
|
||||
sha_digest_calculated = hashlib.sha256(image_data_before_sha).digest()
|
||||
image = bytes(
|
||||
itertools.chain(
|
||||
image_data_before_sha, sha_digest_calculated, image_data_after_sha
|
||||
)
|
||||
)
|
||||
|
||||
# get the SHA digest newly stored in the image and compare it to the calculated one
|
||||
image_stored_sha = image[
|
||||
image_object.data_length : image_object.data_length
|
||||
+ image_object.SHA256_DIGEST_LEN
|
||||
]
|
||||
|
||||
if hexify(sha_digest_calculated) == hexify(image_stored_sha):
|
||||
print("SHA digest in image updated")
|
||||
else:
|
||||
print(
|
||||
"WARNING: SHA recalculation for binary failed!\n"
|
||||
f"\tExpected calculated SHA: {hexify(sha_digest_calculated)}\n"
|
||||
f"\tSHA stored in binary: {hexify(image_stored_sha)}"
|
||||
)
|
||||
|
||||
return image
|
||||
|
||||
|
||||
@@ -465,19 +478,32 @@ def write_flash(esp, args):
|
||||
"Use --force to override the warning."
|
||||
)
|
||||
|
||||
# verify file sizes fit in flash
|
||||
flash_end = flash_size_bytes(
|
||||
detect_flash_size(esp) if args.flash_size == "keep" else args.flash_size
|
||||
set_flash_size = (
|
||||
flash_size_bytes(args.flash_size)
|
||||
if args.flash_size not in ["detect", "keep"]
|
||||
else None
|
||||
)
|
||||
if flash_end is not None: # Not in secure download mode
|
||||
if esp.secure_download_mode:
|
||||
flash_end = set_flash_size
|
||||
else: # Check against real flash chip size if not in SDM
|
||||
flash_end_str = detect_flash_size(esp)
|
||||
flash_end = flash_size_bytes(flash_end_str)
|
||||
if set_flash_size and set_flash_size > flash_end:
|
||||
print(
|
||||
f"WARNING: Set --flash_size {args.flash_size} "
|
||||
f"is larger than the available flash size of {flash_end_str}."
|
||||
)
|
||||
|
||||
# Verify file sizes fit in the set --flash_size, or real flash size if smaller
|
||||
flash_end = min(set_flash_size, flash_end) if set_flash_size else flash_end
|
||||
if flash_end is not None:
|
||||
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)
|
||||
f"File {argfile.name} (length {argfile.tell()}) at offset "
|
||||
f"{address} will not fit in {flash_end} bytes of flash. "
|
||||
"Change the --flash_size argument, or flashing address."
|
||||
)
|
||||
argfile.seek(0)
|
||||
|
||||
@@ -547,70 +573,118 @@ def write_flash(esp, args):
|
||||
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
|
||||
)
|
||||
image = argfile.read()
|
||||
|
||||
if len(image) == 0:
|
||||
print("WARNING: File %s is empty" % argfile.name)
|
||||
continue
|
||||
image = _update_image_flash_params(esp, address, args, image)
|
||||
|
||||
image = pad_to(image, esp.FLASH_ENCRYPTED_WRITE_ALIGN if encrypted else 4)
|
||||
|
||||
if args.no_stub:
|
||||
print("Erasing flash...")
|
||||
|
||||
# It is not possible to write to not aligned addresses without stub,
|
||||
# so there are added 0xFF (erase) bytes at the beginning of the image
|
||||
# to align it.
|
||||
bytes_over = address % esp.FLASH_SECTOR_SIZE
|
||||
address -= bytes_over
|
||||
image = b"\xFF" * bytes_over + image
|
||||
|
||||
if not esp.secure_download_mode and not esp.get_secure_boot_enabled():
|
||||
image = _update_image_flash_params(esp, address, args, image)
|
||||
else:
|
||||
print(
|
||||
"WARNING: Security features enabled, so not changing any flash settings."
|
||||
)
|
||||
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)
|
||||
original_image = image # Save the whole image in case retry is needed
|
||||
# Try again if reconnect was successful
|
||||
for attempt in range(1, esp.WRITE_FLASH_ATTEMPTS + 1):
|
||||
try:
|
||||
if compress:
|
||||
# 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:
|
||||
esp.flash_block(block, seq)
|
||||
bytes_written += len(block)
|
||||
bytes_sent += len(block)
|
||||
image = image[esp.FLASH_WRITE_SIZE :]
|
||||
seq += 1
|
||||
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
|
||||
break
|
||||
except SerialException:
|
||||
if attempt == esp.WRITE_FLASH_ATTEMPTS or encrypted:
|
||||
# Already retried once or encrypted mode is disabled because of security reasons
|
||||
raise
|
||||
print("\nLost connection, retrying...")
|
||||
esp._port.close()
|
||||
print("Waiting for the chip to reconnect", end="")
|
||||
for _ in range(DEFAULT_CONNECT_ATTEMPTS):
|
||||
try:
|
||||
time.sleep(1)
|
||||
esp._port.open()
|
||||
print() # Print new line which was suppressed by print(".")
|
||||
esp.connect()
|
||||
if esp.IS_STUB:
|
||||
# Hack to bypass the stub overwrite check
|
||||
esp.IS_STUB = False
|
||||
# Reflash stub because chip was reset
|
||||
esp = esp.run_stub()
|
||||
image = original_image
|
||||
break
|
||||
except SerialException:
|
||||
print(".", end="")
|
||||
sys.stdout.flush()
|
||||
else:
|
||||
raise # Reconnect limit reached
|
||||
|
||||
if esp.IS_STUB:
|
||||
# Stub only writes each block to flash after 'ack'ing the receive,
|
||||
@@ -645,7 +719,7 @@ def write_flash(esp, args):
|
||||
print("Flash md5: %s" % res)
|
||||
print(
|
||||
"MD5 of 0xFF is %s"
|
||||
% (hashlib.md5(b"\xFF" * uncsize).hexdigest())
|
||||
% (hashlib.md5(b"\xff" * uncsize).hexdigest())
|
||||
)
|
||||
raise FatalError("MD5 of file does not match data in flash!")
|
||||
else:
|
||||
@@ -793,7 +867,7 @@ def image_info(args):
|
||||
format_str = "{:7} {:#07x} {:#010x} {:#010x} {}"
|
||||
app_desc = None
|
||||
bootloader_desc = None
|
||||
for idx, seg in enumerate(image.segments, start=1):
|
||||
for idx, seg in enumerate(image.segments):
|
||||
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
|
||||
@@ -815,9 +889,11 @@ def image_info(args):
|
||||
print(
|
||||
"Checksum: {:#02x} ({})".format(
|
||||
image.checksum,
|
||||
"valid"
|
||||
if image.checksum == calc_checksum
|
||||
else "invalid - calculated {:02x}".format(calc_checksum),
|
||||
(
|
||||
"valid"
|
||||
if image.checksum == calc_checksum
|
||||
else "invalid - calculated {:02x}".format(calc_checksum)
|
||||
),
|
||||
)
|
||||
)
|
||||
try:
|
||||
@@ -892,8 +968,7 @@ def image_info(args):
|
||||
ESP8266V2FirmwareImage.IMAGE_V2_MAGIC,
|
||||
]:
|
||||
raise FatalError(
|
||||
"This is not a valid image "
|
||||
"(invalid magic number: {:#x})".format(magic)
|
||||
f"This is not a valid image (invalid magic number: {magic:#x})"
|
||||
)
|
||||
|
||||
if args.chip == "auto":
|
||||
@@ -940,9 +1015,11 @@ def image_info(args):
|
||||
print(
|
||||
"Checksum: {:02x} ({})".format(
|
||||
image.checksum,
|
||||
"valid"
|
||||
if image.checksum == calc_checksum
|
||||
else "invalid - calculated {:02x}".format(calc_checksum),
|
||||
(
|
||||
"valid"
|
||||
if image.checksum == calc_checksum
|
||||
else "invalid - calculated {:02x}".format(calc_checksum)
|
||||
),
|
||||
)
|
||||
)
|
||||
try:
|
||||
@@ -982,8 +1059,6 @@ def elf2image(args):
|
||||
args.chip = "esp8266"
|
||||
|
||||
print("Creating {} image...".format(args.chip))
|
||||
if args.ram_only_header:
|
||||
print("ROM segments hidden - only RAM segments are visible to the ROM loader!")
|
||||
|
||||
if args.chip != "esp8266":
|
||||
image = CHIP_DEFS[args.chip].BOOTLOADER_IMAGE()
|
||||
@@ -995,7 +1070,10 @@ def elf2image(args):
|
||||
image.min_rev_full = args.min_rev_full
|
||||
image.max_rev_full = args.max_rev_full
|
||||
image.ram_only_header = args.ram_only_header
|
||||
image.append_digest = args.append_digest
|
||||
if image.ram_only_header:
|
||||
image.append_digest = False
|
||||
else:
|
||||
image.append_digest = args.append_digest
|
||||
elif args.version == "1": # ESP8266
|
||||
image = ESP8266ROMFirmwareImage()
|
||||
elif args.version == "2":
|
||||
@@ -1019,6 +1097,13 @@ def elf2image(args):
|
||||
image.elf_sha256 = e.sha256()
|
||||
image.elf_sha256_offset = args.elf_sha256_offset
|
||||
|
||||
if args.ram_only_header:
|
||||
print(
|
||||
"Image has only RAM segments visible. "
|
||||
"ROM segments are hidden and SHA256 digest is not appended."
|
||||
)
|
||||
image.sort_segments()
|
||||
|
||||
before = len(image.segments)
|
||||
image.merge_adjacent_segments()
|
||||
if len(image.segments) != before:
|
||||
@@ -1090,7 +1175,7 @@ def run(esp, args):
|
||||
esp.run()
|
||||
|
||||
|
||||
def flash_id(esp, args):
|
||||
def detect_flash_id(esp):
|
||||
flash_id = esp.flash_id()
|
||||
print("Manufacturer: %02x" % (flash_id & 0xFF))
|
||||
flid_lowbyte = (flash_id >> 16) & 0xFF
|
||||
@@ -1098,11 +1183,27 @@ def flash_id(esp, args):
|
||||
print(
|
||||
"Detected flash size: %s" % (DETECTED_FLASH_SIZES.get(flid_lowbyte, "Unknown"))
|
||||
)
|
||||
|
||||
|
||||
def flash_id(esp, args):
|
||||
detect_flash_id(esp)
|
||||
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}")
|
||||
esp.get_flash_voltage()
|
||||
|
||||
|
||||
def read_flash_sfdp(esp, args):
|
||||
detect_flash_id(esp)
|
||||
|
||||
sfdp = esp.read_spiflash_sfdp(args.addr, args.bytes * 8)
|
||||
print(f"SFDP[{args.addr}..{args.addr+args.bytes-1}]: ", end="")
|
||||
for i in range(args.bytes):
|
||||
print(f"{sfdp&0xff:02X} ", end="")
|
||||
sfdp = sfdp >> 8
|
||||
print()
|
||||
|
||||
|
||||
def read_flash(esp, args):
|
||||
@@ -1218,7 +1319,16 @@ def get_security_info(esp, args):
|
||||
print(title)
|
||||
print("=" * len(title))
|
||||
print("Flags: {:#010x} ({})".format(si["flags"], bin(si["flags"])))
|
||||
print("Key Purposes: {}".format(si["key_purposes"]))
|
||||
if esp.KEY_PURPOSES:
|
||||
print(f"Key Purposes: {si['key_purposes']}")
|
||||
desc = "\n ".join(
|
||||
[
|
||||
f"BLOCK_KEY{key_num} - {esp.KEY_PURPOSES.get(purpose, 'UNKNOWN')}"
|
||||
for key_num, purpose in enumerate(si["key_purposes"])
|
||||
if key_num <= esp.EFUSE_MAX_KEY
|
||||
]
|
||||
)
|
||||
print(f" {desc}")
|
||||
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"]))
|
||||
@@ -1270,7 +1380,7 @@ def get_security_info(esp, args):
|
||||
hard_dis_jtag = get_security_flag_status("HARD_DIS_JTAG", flags)
|
||||
soft_dis_jtag = get_security_flag_status("SOFT_DIS_JTAG", flags)
|
||||
if hard_dis_jtag:
|
||||
print("JTAG: Permenantly Disabled")
|
||||
print("JTAG: Permanently Disabled")
|
||||
elif soft_dis_jtag:
|
||||
print("JTAG: Software Access Disabled")
|
||||
if get_security_flag_status("DIS_USB", flags):
|
||||
@@ -1323,7 +1433,7 @@ def merge_bin(args):
|
||||
|
||||
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()))
|
||||
of.write(b"\xff" * (flash_offs - args.target_offset - of.tell()))
|
||||
|
||||
for addr, argfile in input_files:
|
||||
pad_to(addr)
|
||||
@@ -1338,6 +1448,13 @@ def merge_bin(args):
|
||||
)
|
||||
elif args.format == "hex":
|
||||
out = IntelHex()
|
||||
if len(input_files) == 1:
|
||||
print(
|
||||
"WARNING: Only one input file specified, output may include "
|
||||
"additional padding if input file was previously merged. "
|
||||
"Please refer to the documentation for more information: "
|
||||
"https://docs.espressif.com/projects/esptool/en/latest/esptool/basic-commands.html#hex-output-format" # noqa E501
|
||||
)
|
||||
for addr, argfile in input_files:
|
||||
ihex = IntelHex()
|
||||
image = argfile.read()
|
||||
|
||||
Reference in New Issue
Block a user