1# SPDX-FileCopyrightText: 2023 Fredrik Ahlberg, Angus Gratton, 2# Espressif Systems (Shanghai) CO LTD, other contributors as noted. 3# 4# SPDX-License-Identifier: GPL-2.0-or-later 5 6import struct 7from typing import Dict 8 9from .esp32 import ESP32ROM 10from ..loader import ESPLoader 11from ..util import FatalError, NotImplementedInROMError 12 13 14class ESP32P4ROM(ESP32ROM): 15 CHIP_NAME = "ESP32-P4" 16 IMAGE_CHIP_ID = 18 17 18 IROM_MAP_START = 0x40000000 19 IROM_MAP_END = 0x4C000000 20 DROM_MAP_START = 0x40000000 21 DROM_MAP_END = 0x4C000000 22 23 BOOTLOADER_FLASH_OFFSET = 0x2000 # First 2 sectors are reserved for FE purposes 24 25 CHIP_DETECT_MAGIC_VALUE = [0x0, 0x0ADDBAD0] 26 27 UART_DATE_REG_ADDR = 0x500CA000 + 0x8C 28 29 EFUSE_BASE = 0x5012D000 30 EFUSE_BLOCK1_ADDR = EFUSE_BASE + 0x044 31 MAC_EFUSE_REG = EFUSE_BASE + 0x044 32 33 SPI_REG_BASE = 0x5008D000 # SPIMEM1 34 SPI_USR_OFFS = 0x18 35 SPI_USR1_OFFS = 0x1C 36 SPI_USR2_OFFS = 0x20 37 SPI_MOSI_DLEN_OFFS = 0x24 38 SPI_MISO_DLEN_OFFS = 0x28 39 SPI_W0_OFFS = 0x58 40 41 SPI_ADDR_REG_MSB = False 42 43 EFUSE_RD_REG_BASE = EFUSE_BASE + 0x030 # BLOCK0 read base address 44 45 EFUSE_PURPOSE_KEY0_REG = EFUSE_BASE + 0x34 46 EFUSE_PURPOSE_KEY0_SHIFT = 24 47 EFUSE_PURPOSE_KEY1_REG = EFUSE_BASE + 0x34 48 EFUSE_PURPOSE_KEY1_SHIFT = 28 49 EFUSE_PURPOSE_KEY2_REG = EFUSE_BASE + 0x38 50 EFUSE_PURPOSE_KEY2_SHIFT = 0 51 EFUSE_PURPOSE_KEY3_REG = EFUSE_BASE + 0x38 52 EFUSE_PURPOSE_KEY3_SHIFT = 4 53 EFUSE_PURPOSE_KEY4_REG = EFUSE_BASE + 0x38 54 EFUSE_PURPOSE_KEY4_SHIFT = 8 55 EFUSE_PURPOSE_KEY5_REG = EFUSE_BASE + 0x38 56 EFUSE_PURPOSE_KEY5_SHIFT = 12 57 58 EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT_REG = EFUSE_RD_REG_BASE 59 EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT = 1 << 20 60 61 EFUSE_SPI_BOOT_CRYPT_CNT_REG = EFUSE_BASE + 0x034 62 EFUSE_SPI_BOOT_CRYPT_CNT_MASK = 0x7 << 18 63 64 EFUSE_SECURE_BOOT_EN_REG = EFUSE_BASE + 0x038 65 EFUSE_SECURE_BOOT_EN_MASK = 1 << 20 66 67 PURPOSE_VAL_XTS_AES256_KEY_1 = 2 68 PURPOSE_VAL_XTS_AES256_KEY_2 = 3 69 PURPOSE_VAL_XTS_AES128_KEY = 4 70 71 SUPPORTS_ENCRYPTED_FLASH = True 72 73 FLASH_ENCRYPTED_WRITE_ALIGN = 16 74 75 MEMORY_MAP = [ 76 [0x00000000, 0x00010000, "PADDING"], 77 [0x40000000, 0x4C000000, "DROM"], 78 [0x4FF00000, 0x4FFA0000, "DRAM"], 79 [0x4FF00000, 0x4FFA0000, "BYTE_ACCESSIBLE"], 80 [0x4FC00000, 0x4FC20000, "DROM_MASK"], 81 [0x4FC00000, 0x4FC20000, "IROM_MASK"], 82 [0x40000000, 0x4C000000, "IROM"], 83 [0x4FF00000, 0x4FFA0000, "IRAM"], 84 [0x50108000, 0x50110000, "RTC_IRAM"], 85 [0x50108000, 0x50110000, "RTC_DRAM"], 86 [0x600FE000, 0x60100000, "MEM_INTERNAL2"], 87 ] 88 89 UF2_FAMILY_ID = 0x3D308E94 90 91 EFUSE_MAX_KEY = 5 92 KEY_PURPOSES: Dict[int, str] = { 93 0: "USER/EMPTY", 94 1: "ECDSA_KEY", 95 2: "XTS_AES_256_KEY_1", 96 3: "XTS_AES_256_KEY_2", 97 4: "XTS_AES_128_KEY", 98 5: "HMAC_DOWN_ALL", 99 6: "HMAC_DOWN_JTAG", 100 7: "HMAC_DOWN_DIGITAL_SIGNATURE", 101 8: "HMAC_UP", 102 9: "SECURE_BOOT_DIGEST0", 103 10: "SECURE_BOOT_DIGEST1", 104 11: "SECURE_BOOT_DIGEST2", 105 12: "KM_INIT_KEY", 106 } 107 108 def get_pkg_version(self): 109 num_word = 2 110 return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 20) & 0x07 111 112 def get_minor_chip_version(self): 113 num_word = 2 114 return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 0) & 0x0F 115 116 def get_major_chip_version(self): 117 num_word = 2 118 return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 4) & 0x03 119 120 def get_chip_description(self): 121 chip_name = { 122 0: "ESP32-P4", 123 }.get(self.get_pkg_version(), "unknown ESP32-P4") 124 major_rev = self.get_major_chip_version() 125 minor_rev = self.get_minor_chip_version() 126 return f"{chip_name} (revision v{major_rev}.{minor_rev})" 127 128 def get_chip_features(self): 129 return ["High-Performance MCU"] 130 131 def get_crystal_freq(self): 132 # ESP32P4 XTAL is fixed to 40MHz 133 return 40 134 135 def get_flash_voltage(self): 136 pass # not supported on ESP32-P4 137 138 def override_vddsdio(self, new_voltage): 139 raise NotImplementedInROMError( 140 "VDD_SDIO overrides are not supported for ESP32-P4" 141 ) 142 143 def read_mac(self, mac_type="BASE_MAC"): 144 """Read MAC from EFUSE region""" 145 if mac_type != "BASE_MAC": 146 return None 147 mac0 = self.read_reg(self.MAC_EFUSE_REG) 148 mac1 = self.read_reg(self.MAC_EFUSE_REG + 4) # only bottom 16 bits are MAC 149 bitstring = struct.pack(">II", mac1, mac0)[2:] 150 return tuple(bitstring) 151 152 def get_flash_crypt_config(self): 153 return None # doesn't exist on ESP32-P4 154 155 def get_secure_boot_enabled(self): 156 return ( 157 self.read_reg(self.EFUSE_SECURE_BOOT_EN_REG) 158 & self.EFUSE_SECURE_BOOT_EN_MASK 159 ) 160 161 def get_key_block_purpose(self, key_block): 162 if key_block < 0 or key_block > self.EFUSE_MAX_KEY: 163 raise FatalError( 164 f"Valid key block numbers must be in range 0-{self.EFUSE_MAX_KEY}" 165 ) 166 167 reg, shift = [ 168 (self.EFUSE_PURPOSE_KEY0_REG, self.EFUSE_PURPOSE_KEY0_SHIFT), 169 (self.EFUSE_PURPOSE_KEY1_REG, self.EFUSE_PURPOSE_KEY1_SHIFT), 170 (self.EFUSE_PURPOSE_KEY2_REG, self.EFUSE_PURPOSE_KEY2_SHIFT), 171 (self.EFUSE_PURPOSE_KEY3_REG, self.EFUSE_PURPOSE_KEY3_SHIFT), 172 (self.EFUSE_PURPOSE_KEY4_REG, self.EFUSE_PURPOSE_KEY4_SHIFT), 173 (self.EFUSE_PURPOSE_KEY5_REG, self.EFUSE_PURPOSE_KEY5_SHIFT), 174 ][key_block] 175 return (self.read_reg(reg) >> shift) & 0xF 176 177 def is_flash_encryption_key_valid(self): 178 # Need to see either an AES-128 key or two AES-256 keys 179 purposes = [ 180 self.get_key_block_purpose(b) for b in range(self.EFUSE_MAX_KEY + 1) 181 ] 182 183 if any(p == self.PURPOSE_VAL_XTS_AES128_KEY for p in purposes): 184 return True 185 186 return any(p == self.PURPOSE_VAL_XTS_AES256_KEY_1 for p in purposes) and any( 187 p == self.PURPOSE_VAL_XTS_AES256_KEY_2 for p in purposes 188 ) 189 190 def change_baud(self, baud): 191 ESPLoader.change_baud(self, baud) 192 193 def _post_connect(self): 194 pass 195 # TODO: Disable watchdogs when USB modes are supported in the stub 196 # if not self.sync_stub_detected: # Don't run if stub is reused 197 # self.disable_watchdogs() 198 199 def check_spi_connection(self, spi_connection): 200 if not set(spi_connection).issubset(set(range(0, 55))): 201 raise FatalError("SPI Pin numbers must be in the range 0-54.") 202 if any([v for v in spi_connection if v in [24, 25]]): 203 print( 204 "WARNING: GPIO pins 24 and 25 are used by USB-Serial/JTAG, " 205 "consider using other pins for SPI flash connection." 206 ) 207 208 209class ESP32P4StubLoader(ESP32P4ROM): 210 """Access class for ESP32P4 stub loader, runs on top of ROM. 211 212 (Basically the same as ESP32StubLoader, but different base class. 213 Can possibly be made into a mixin.) 214 """ 215 216 FLASH_WRITE_SIZE = 0x4000 # matches MAX_WRITE_BLOCK in stub_loader.c 217 STATUS_BYTES_LENGTH = 2 # same as ESP8266, different to ESP32 ROM 218 IS_STUB = True 219 220 def __init__(self, rom_loader): 221 self.secure_download_mode = rom_loader.secure_download_mode 222 self._port = rom_loader._port 223 self._trace_enabled = rom_loader._trace_enabled 224 self.cache = rom_loader.cache 225 self.flush_input() # resets _slip_reader 226 227 228ESP32P4ROM.STUB_CLASS = ESP32P4StubLoader 229