Add an argument `--esp-encrypt` to flash an ESP32 series chip with encrypted flash. The content of the binary is encrypted on the fly by the chip. It is not required to know the encryption key. However, the fuses that disable encrypted flash download must be kept enabled for this to work. Signed-off-by: Martin Jäger <martin@libre.solar>
142 lines
5.9 KiB
Python
142 lines
5.9 KiB
Python
# Copyright (c) 2017 Linaro Limited.
|
|
# Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd.
|
|
#
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
|
|
'''Runner for flashing ESP32 devices with esptool/espidf.'''
|
|
|
|
import os
|
|
import sys
|
|
from os import path
|
|
|
|
from runners.core import RunnerCaps, ZephyrBinaryRunner
|
|
|
|
|
|
class Esp32BinaryRunner(ZephyrBinaryRunner):
|
|
'''Runner front-end for espidf.'''
|
|
|
|
def __init__(self, cfg, device, boot_address, part_table_address,
|
|
app_address, erase=False, reset=False, baud=921600,
|
|
flash_size='detect', flash_freq='40m', flash_mode='dio',
|
|
espidf='espidf', bootloader_bin=None, partition_table_bin=None,
|
|
encrypt=False, no_stub=False):
|
|
super().__init__(cfg)
|
|
self.elf = cfg.elf_file
|
|
self.app_bin = cfg.bin_file
|
|
self.erase = bool(erase)
|
|
self.reset = bool(reset)
|
|
self.device = device
|
|
self.boot_address = boot_address
|
|
self.part_table_address = part_table_address
|
|
self.app_address = app_address
|
|
self.baud = baud
|
|
self.flash_size = flash_size
|
|
self.flash_freq = flash_freq
|
|
self.flash_mode = flash_mode
|
|
self.espidf = espidf
|
|
self.bootloader_bin = bootloader_bin
|
|
self.partition_table_bin = partition_table_bin
|
|
self.encrypt = encrypt
|
|
self.no_stub = no_stub
|
|
|
|
@classmethod
|
|
def name(cls):
|
|
return 'esp32'
|
|
|
|
@classmethod
|
|
def capabilities(cls):
|
|
return RunnerCaps(commands={'flash'}, erase=True, reset=True)
|
|
|
|
@classmethod
|
|
def do_add_parser(cls, parser):
|
|
# Required
|
|
parser.add_argument('--esp-idf-path', required=True,
|
|
help='path to ESP-IDF')
|
|
# Optional
|
|
parser.add_argument('--esp-boot-address', default='0x1000',
|
|
help='bootloader load address')
|
|
parser.add_argument('--esp-partition-table-address', default='0x8000',
|
|
help='partition table load address')
|
|
parser.add_argument('--esp-app-address', default='0x10000',
|
|
help='application load address')
|
|
parser.add_argument('--esp-device', default=os.environ.get('ESPTOOL_PORT', None),
|
|
help='serial port to flash')
|
|
parser.add_argument('--esp-baud-rate', default='921600',
|
|
help='serial baud rate, default 921600')
|
|
parser.add_argument('--esp-monitor-baud', default='115200',
|
|
help='serial monitor baud rate, default 115200')
|
|
parser.add_argument('--esp-flash-size', default='detect',
|
|
help='flash size, default "detect"')
|
|
parser.add_argument('--esp-flash-freq', default='40m',
|
|
help='flash frequency, default "40m"')
|
|
parser.add_argument('--esp-flash-mode', default='dio',
|
|
help='flash mode, default "dio"')
|
|
parser.add_argument(
|
|
'--esp-tool',
|
|
help='''if given, complete path to espidf. default is to search for
|
|
it in [ESP_IDF_PATH]/tools/esptool_py/esptool.py''')
|
|
parser.add_argument('--esp-flash-bootloader',
|
|
help='Bootloader image to flash')
|
|
parser.add_argument('--esp-flash-partition_table',
|
|
help='Partition table to flash')
|
|
parser.add_argument('--esp-encrypt', default=False, action='store_true',
|
|
help='Encrypt firmware while flashing (correct efuses required)')
|
|
parser.add_argument('--esp-no-stub', default=False, action='store_true',
|
|
help='Disable launching the flasher stub, only talk to ROM bootloader')
|
|
|
|
parser.set_defaults(reset=True)
|
|
|
|
@classmethod
|
|
def do_create(cls, cfg, args):
|
|
if args.esp_tool:
|
|
espidf = args.esp_tool
|
|
else:
|
|
espidf = path.join(args.esp_idf_path, 'tools', 'esptool_py',
|
|
'esptool.py')
|
|
|
|
return Esp32BinaryRunner(
|
|
cfg, args.esp_device, boot_address=args.esp_boot_address,
|
|
part_table_address=args.esp_partition_table_address,
|
|
app_address=args.esp_app_address, erase=args.erase, reset=args.reset,
|
|
baud=args.esp_baud_rate, flash_size=args.esp_flash_size,
|
|
flash_freq=args.esp_flash_freq, flash_mode=args.esp_flash_mode,
|
|
espidf=espidf, bootloader_bin=args.esp_flash_bootloader,
|
|
partition_table_bin=args.esp_flash_partition_table,
|
|
encrypt=args.esp_encrypt, no_stub=args.esp_no_stub)
|
|
|
|
def do_run(self, command, **kwargs):
|
|
self.require(self.espidf)
|
|
|
|
# Add Python interpreter
|
|
cmd_flash = [sys.executable, self.espidf, '--chip', 'auto']
|
|
|
|
if self.device is not None:
|
|
cmd_flash.extend(['--port', self.device])
|
|
|
|
if self.erase is True:
|
|
cmd_erase = cmd_flash + ['erase_flash']
|
|
self.check_call(cmd_erase)
|
|
|
|
if self.no_stub is True:
|
|
cmd_flash.extend(['--no-stub'])
|
|
cmd_flash.extend(['--baud', self.baud])
|
|
cmd_flash.extend(['--before', 'default_reset'])
|
|
if self.reset:
|
|
cmd_flash.extend(['--after', 'hard_reset', 'write_flash', '-u'])
|
|
cmd_flash.extend(['--flash_mode', self.flash_mode])
|
|
cmd_flash.extend(['--flash_freq', self.flash_freq])
|
|
cmd_flash.extend(['--flash_size', self.flash_size])
|
|
|
|
if self.encrypt:
|
|
cmd_flash.extend(['--encrypt'])
|
|
|
|
if self.bootloader_bin:
|
|
cmd_flash.extend([self.boot_address, self.bootloader_bin])
|
|
if self.partition_table_bin:
|
|
cmd_flash.extend([self.part_table_address, self.partition_table_bin])
|
|
cmd_flash.extend([self.app_address, self.app_bin])
|
|
else:
|
|
cmd_flash.extend([self.app_address, self.app_bin])
|
|
|
|
self.logger.info(f"Flashing esp32 chip on {self.device} ({self.baud}bps)")
|
|
self.check_call(cmd_flash)
|