Update: 更新esptool ( version: 4.7.0 )

This commit is contained in:
王立帮
2024-09-01 12:36:51 +08:00
parent caf26e2fbc
commit 557a035010
37 changed files with 4733 additions and 185 deletions

View File

@@ -11,6 +11,8 @@ import sys
import time
import zlib
from intelhex import IntelHex
from bin_image import ELFFile, ImageSegment, LoadFirmwareImage
from bin_image import (
ESP8266ROMFirmwareImage,
@@ -25,6 +27,7 @@ from loader import (
timeout_per_mb,
)
from targets import CHIP_DEFS, CHIP_LIST, ROM_LIST
from uf2_writer import UF2Writer
from util import (
FatalError,
NotImplementedInROMError,
@@ -96,7 +99,7 @@ def detect_chip(
print("Detecting chip type...", end="")
chip_id = detect_port.get_chip_id()
for cls in [
n for n in ROM_LIST if n.CHIP_NAME not in ("ESP8266", "ESP32", "ESP32S2")
n for n in ROM_LIST if n.CHIP_NAME not in ("ESP8266", "ESP32", "ESP32-S2")
]:
# cmd not supported on ESP8266 and ESP32 + ESP32-S2 doesn't return chip_id
if chip_id == cls.IMAGE_CHIP_ID:
@@ -466,7 +469,7 @@ def write_flash(esp, args):
flash_end = flash_size_bytes(
detect_flash_size(esp) if args.flash_size == "keep" else args.flash_size
)
if flash_end is not None: # Secure download mode
if flash_end is not None: # Not in secure download mode
for address, argfile in args.addr_filename:
argfile.seek(0, os.SEEK_END)
if address + argfile.tell() > flash_end:
@@ -979,6 +982,8 @@ def elf2image(args):
args.chip = "esp8266"
print("Creating {} image...".format(args.chip))
if args.ram_only_header:
print("ROM segments hidden - only RAM segments are visible to the ROM loader!")
if args.chip != "esp8266":
image = CHIP_DEFS[args.chip].BOOTLOADER_IMAGE()
@@ -989,6 +994,7 @@ def elf2image(args):
image.min_rev = args.min_rev
image.min_rev_full = args.min_rev_full
image.max_rev_full = args.max_rev_full
image.ram_only_header = args.ram_only_header
image.append_digest = args.append_digest
elif args.version == "1": # ESP8266
image = ESP8266ROMFirmwareImage()
@@ -1106,9 +1112,9 @@ def read_flash(esp, args):
def flash_progress(progress, length):
msg = "%d (%d %%)" % (progress, progress * 100.0 / length)
# padding = "\b" * len(msg)
# if progress == length:
padding = "\n"
padding = "\b" * len(msg)
if progress == length:
padding = "\n"
sys.stdout.write(msg + padding)
sys.stdout.flush()
@@ -1180,15 +1186,95 @@ def write_flash_status(esp, args):
print(("After flash status: " + fmt) % esp.read_status(args.bytes))
# The following mapping was taken from the ROM code
# This mapping is same across all targets in the ROM
SECURITY_INFO_FLAG_MAP = {
"SECURE_BOOT_EN": (1 << 0),
"SECURE_BOOT_AGGRESSIVE_REVOKE": (1 << 1),
"SECURE_DOWNLOAD_ENABLE": (1 << 2),
"SECURE_BOOT_KEY_REVOKE0": (1 << 3),
"SECURE_BOOT_KEY_REVOKE1": (1 << 4),
"SECURE_BOOT_KEY_REVOKE2": (1 << 5),
"SOFT_DIS_JTAG": (1 << 6),
"HARD_DIS_JTAG": (1 << 7),
"DIS_USB": (1 << 8),
"DIS_DOWNLOAD_DCACHE": (1 << 9),
"DIS_DOWNLOAD_ICACHE": (1 << 10),
}
# Get the status of respective security flag
def get_security_flag_status(flag_name, flags_value):
try:
return (flags_value & SECURITY_INFO_FLAG_MAP[flag_name]) != 0
except KeyError:
raise ValueError(f"Invalid flag name: {flag_name}")
def get_security_info(esp, args):
si = esp.get_security_info()
# TODO: better display
print()
title = "Security Information:"
print(title)
print("=" * len(title))
print("Flags: {:#010x} ({})".format(si["flags"], bin(si["flags"])))
print("Flash_Crypt_Cnt: {:#x}".format(si["flash_crypt_cnt"]))
print("Key_Purposes: {}".format(si["key_purposes"]))
print("Key Purposes: {}".format(si["key_purposes"]))
if si["chip_id"] is not None and si["api_version"] is not None:
print("Chip_ID: {}".format(si["chip_id"]))
print("Api_Version: {}".format(si["api_version"]))
print("Chip ID: {}".format(si["chip_id"]))
print("API Version: {}".format(si["api_version"]))
flags = si["flags"]
if get_security_flag_status("SECURE_BOOT_EN", flags):
print("Secure Boot: Enabled")
if get_security_flag_status("SECURE_BOOT_AGGRESSIVE_REVOKE", flags):
print("Secure Boot Aggressive key revocation: Enabled")
revoked_keys = []
for i, key in enumerate(
[
"SECURE_BOOT_KEY_REVOKE0",
"SECURE_BOOT_KEY_REVOKE1",
"SECURE_BOOT_KEY_REVOKE2",
]
):
if get_security_flag_status(key, flags):
revoked_keys.append(i)
if len(revoked_keys) > 0:
print("Secure Boot Key Revocation Status:\n")
for i in revoked_keys:
print(f"\tSecure Boot Key{i} is Revoked\n")
else:
print("Secure Boot: Disabled")
flash_crypt_cnt = bin(si["flash_crypt_cnt"])
if (flash_crypt_cnt.count("1") % 2) != 0:
print("Flash Encryption: Enabled")
else:
print("Flash Encryption: Disabled")
CRYPT_CNT_STRING = "SPI Boot Crypt Count (SPI_BOOT_CRYPT_CNT)"
if esp.CHIP_NAME == "esp32":
CRYPT_CNT_STRING = "Flash Crypt Count (FLASH_CRYPT_CNT)"
print(f"{CRYPT_CNT_STRING}: {si['flash_crypt_cnt']:#x}")
if get_security_flag_status("DIS_DOWNLOAD_DCACHE", flags):
print("Dcache in UART download mode: Disabled")
if get_security_flag_status("DIS_DOWNLOAD_ICACHE", flags):
print("Icache in UART download mode: Disabled")
hard_dis_jtag = get_security_flag_status("HARD_DIS_JTAG", flags)
soft_dis_jtag = get_security_flag_status("SOFT_DIS_JTAG", flags)
if hard_dis_jtag:
print("JTAG: Permenantly Disabled")
elif soft_dis_jtag:
print("JTAG: Software Access Disabled")
if get_security_flag_status("DIS_USB", flags):
print("USB Access: Disabled")
def merge_bin(args):
@@ -1198,9 +1284,9 @@ def merge_bin(args):
msg = (
"Please specify the chip argument"
if args.chip == "auto"
else "Invalid chip choice: '{}'".format(args.chip)
else f"Invalid chip choice: '{args.chip}'"
)
msg = msg + " (choose from {})".format(", ".join(CHIP_LIST))
msg = f"{msg} (choose from {', '.join(CHIP_LIST)})"
raise FatalError(msg)
# sort the files by offset.
@@ -1211,31 +1297,57 @@ def merge_bin(args):
first_addr = input_files[0][0]
if first_addr < args.target_offset:
raise FatalError(
"Output file target offset is 0x%x. Input file offset 0x%x is before this."
% (args.target_offset, first_addr)
f"Output file target offset is {args.target_offset:#x}. "
f"Input file offset {first_addr:#x} is before this."
)
if args.format != "raw":
raise FatalError(
"This version of esptool only supports the 'raw' output format"
if args.format == "uf2":
with UF2Writer(
chip_class.UF2_FAMILY_ID,
args.output,
args.chunk_size,
md5_enabled=not args.md5_disable,
) as writer:
for addr, argfile in input_files:
print(f"Adding {argfile.name} at {addr:#x}")
image = argfile.read()
image = _update_image_flash_params(chip_class, addr, args, image)
writer.add_file(addr, image)
print(
f"Wrote {os.path.getsize(args.output):#x} bytes to file {args.output}, "
f"ready to be flashed with any ESP USB Bridge"
)
with open(args.output, "wb") as of:
elif args.format == "raw":
with open(args.output, "wb") as of:
def pad_to(flash_offs):
# account for output file offset if there is any
of.write(b"\xFF" * (flash_offs - args.target_offset - of.tell()))
def pad_to(flash_offs):
# account for output file offset if there is any
of.write(b"\xFF" * (flash_offs - args.target_offset - of.tell()))
for addr, argfile in input_files:
pad_to(addr)
image = argfile.read()
image = _update_image_flash_params(chip_class, addr, args, image)
of.write(image)
if args.fill_flash_size:
pad_to(flash_size_bytes(args.fill_flash_size))
print(
f"Wrote {of.tell():#x} bytes to file {args.output}, "
f"ready to flash to offset {args.target_offset:#x}"
)
elif args.format == "hex":
out = IntelHex()
for addr, argfile in input_files:
pad_to(addr)
ihex = IntelHex()
image = argfile.read()
image = _update_image_flash_params(chip_class, addr, args, image)
of.write(image)
if args.fill_flash_size:
pad_to(flash_size_bytes(args.fill_flash_size))
ihex.frombytes(image, addr)
out.merge(ihex)
out.write_hex_file(args.output)
print(
"Wrote 0x%x bytes to file %s, ready to flash to offset 0x%x"
% (of.tell(), args.output, args.target_offset)
f"Wrote {os.path.getsize(args.output):#x} bytes to file {args.output}, "
f"ready to flash to offset {args.target_offset:#x}"
)