@@ -14,18 +14,22 @@ export class ESP32C5ROM extends ESP32C6ROM {
1414
1515 public EFUSE_RD_REG_BASE = this . EFUSE_BASE + 0x030 ; // BLOCK0 read base address
1616
17+ public EFUSE_FORCE_USE_KEY_MANAGER_KEY_REG = this . EFUSE_BASE + 0x34 ;
18+ public EFUSE_FORCE_USE_KEY_MANAGER_KEY_SHIFT = 10 ;
19+ public FORCE_USE_KEY_MANAGER_VAL_XTS_AES_KEY = 2 ;
20+
1721 public EFUSE_PURPOSE_KEY0_REG = this . EFUSE_BASE + 0x34 ;
18- public EFUSE_PURPOSE_KEY0_SHIFT = 24 ;
22+ public EFUSE_PURPOSE_KEY0_SHIFT = 22 ;
1923 public EFUSE_PURPOSE_KEY1_REG = this . EFUSE_BASE + 0x34 ;
20- public EFUSE_PURPOSE_KEY1_SHIFT = 28 ;
24+ public EFUSE_PURPOSE_KEY1_SHIFT = 27 ;
2125 public EFUSE_PURPOSE_KEY2_REG = this . EFUSE_BASE + 0x38 ;
2226 public EFUSE_PURPOSE_KEY2_SHIFT = 0 ;
2327 public EFUSE_PURPOSE_KEY3_REG = this . EFUSE_BASE + 0x38 ;
24- public EFUSE_PURPOSE_KEY3_SHIFT = 4 ;
28+ public EFUSE_PURPOSE_KEY3_SHIFT = 5 ;
2529 public EFUSE_PURPOSE_KEY4_REG = this . EFUSE_BASE + 0x38 ;
26- public EFUSE_PURPOSE_KEY4_SHIFT = 8 ;
30+ public EFUSE_PURPOSE_KEY4_SHIFT = 10 ;
2731 public EFUSE_PURPOSE_KEY5_REG = this . EFUSE_BASE + 0x38 ;
28- public EFUSE_PURPOSE_KEY5_SHIFT = 12 ;
32+ public EFUSE_PURPOSE_KEY5_SHIFT = 15 ;
2933
3034 public EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT_REG = this . EFUSE_RD_REG_BASE ;
3135 public EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT = 1 << 20 ;
@@ -37,9 +41,9 @@ export class ESP32C5ROM extends ESP32C6ROM {
3741 public EFUSE_SECURE_BOOT_EN_MASK = 1 << 20 ;
3842
3943 public IROM_MAP_START = 0x42000000 ;
40- public IROM_MAP_END = 0x42800000 ;
41- public DROM_MAP_START = 0x42800000 ;
42- public DROM_MAP_END = 0x43000000 ;
44+ public IROM_MAP_END = 0x44000000 ;
45+ public DROM_MAP_START = 0x42000000 ;
46+ public DROM_MAP_END = 0x44000000 ;
4347
4448 public PCR_SYSCLK_CONF_REG = 0x60096110 ;
4549 public PCR_SYSCLK_XTAL_FREQ_V = 0x7f << 24 ;
@@ -60,12 +64,12 @@ export class ESP32C5ROM extends ESP32C6ROM {
6064
6165 public MEMORY_MAP : MemoryMapEntry [ ] = [
6266 [ 0x00000000 , 0x00010000 , "PADDING" ] ,
63- [ 0x42800000 , 0x43000000 , "DROM" ] ,
67+ [ 0x42000000 , 0x44000000 , "DROM" ] ,
6468 [ 0x40800000 , 0x40860000 , "DRAM" ] ,
6569 [ 0x40800000 , 0x40860000 , "BYTE_ACCESSIBLE" ] ,
6670 [ 0x4003a000 , 0x40040000 , "DROM_MASK" ] ,
6771 [ 0x40000000 , 0x4003a000 , "IROM_MASK" ] ,
68- [ 0x42000000 , 0x42800000 , "IROM" ] ,
72+ [ 0x42000000 , 0x44000000 , "IROM" ] ,
6973 [ 0x40800000 , 0x40860000 , "IRAM" ] ,
7074 [ 0x50000000 , 0x50004000 , "RTC_IRAM" ] ,
7175 [ 0x50000000 , 0x50004000 , "RTC_DRAM" ] ,
@@ -75,11 +79,10 @@ export class ESP32C5ROM extends ESP32C6ROM {
7579 UF2_FAMILY_ID = 0xf71c0343 ;
7680
7781 EFUSE_MAX_KEY = 5 ;
78- KEY_PURPOSES = {
82+ PURPOSE_VAL_XTS_AES128_KEY = 4 ;
83+ KEY_PURPOSES : { [ key : number ] : string } = {
7984 0 : "USER/EMPTY" ,
8085 1 : "ECDSA_KEY" ,
81- 2 : "XTS_AES_256_KEY_1" ,
82- 3 : "XTS_AES_256_KEY_2" ,
8386 4 : "XTS_AES_128_KEY" ,
8487 5 : "HMAC_DOWN_ALL" ,
8588 6 : "HMAC_DOWN_JTAG" ,
@@ -89,6 +92,10 @@ export class ESP32C5ROM extends ESP32C6ROM {
8992 10 : "SECURE_BOOT_DIGEST1" ,
9093 11 : "SECURE_BOOT_DIGEST2" ,
9194 12 : "KM_INIT_KEY" ,
95+ 15 : "XTS_AES_128_PSRAM_KEY" ,
96+ 16 : "ECDSA_KEY_P192" ,
97+ 17 : "ECDSA_KEY_P384_L" ,
98+ 18 : "ECDSA_KEY_P384_H" ,
9299 } ;
93100
94101 public async getPkgVersion ( loader : ESPLoader ) : Promise < number > {
@@ -120,7 +127,7 @@ export class ESP32C5ROM extends ESP32C6ROM {
120127 }
121128
122129 public async getChipFeatures ( loader : ESPLoader ) : Promise < string [ ] > {
123- return [ "Wi-Fi 6 (dual-band)" , "BT 5 (LE)" ] ;
130+ return [ "Wi-Fi 6 (dual-band)" , "BT 5 (LE)" , "IEEE802.15.4" , "Single Core + LP Core" , "240MHz" ] ;
124131 }
125132
126133 public async getCrystalFreq ( loader : ESPLoader ) : Promise < number > {
@@ -147,4 +154,100 @@ export class ESP32C5ROM extends ESP32C6ROM {
147154 ( ( await loader . readReg ( this . PCR_SYSCLK_CONF_REG ) ) & this . PCR_SYSCLK_XTAL_FREQ_V ) >> this . PCR_SYSCLK_XTAL_FREQ_S
148155 ) ;
149156 }
157+
158+ public async getKeyBlockPurpose ( loader : ESPLoader , keyBlock : number ) : Promise < number > {
159+ if ( keyBlock < 0 || keyBlock > this . EFUSE_MAX_KEY ) {
160+ throw new Error ( `Valid key block numbers must be in range 0-${ this . EFUSE_MAX_KEY } ` ) ;
161+ }
162+
163+ const regShiftDictionary = [
164+ [ this . EFUSE_PURPOSE_KEY0_REG , this . EFUSE_PURPOSE_KEY0_SHIFT ] ,
165+ [ this . EFUSE_PURPOSE_KEY1_REG , this . EFUSE_PURPOSE_KEY1_SHIFT ] ,
166+ [ this . EFUSE_PURPOSE_KEY2_REG , this . EFUSE_PURPOSE_KEY2_SHIFT ] ,
167+ [ this . EFUSE_PURPOSE_KEY3_REG , this . EFUSE_PURPOSE_KEY3_SHIFT ] ,
168+ [ this . EFUSE_PURPOSE_KEY4_REG , this . EFUSE_PURPOSE_KEY4_SHIFT ] ,
169+ [ this . EFUSE_PURPOSE_KEY5_REG , this . EFUSE_PURPOSE_KEY5_SHIFT ] ,
170+ ] ;
171+ const [ reg , shift ] = regShiftDictionary [ keyBlock ] ;
172+
173+ const registerValue = await loader . readReg ( reg ) ;
174+ return ( registerValue >> shift ) & 0x1f ;
175+ }
176+
177+ public async isFlashEncryptionKeyValid ( loader : ESPLoader ) : Promise < boolean > {
178+ // Need to see an AES-128 key
179+ const purposes = [ ] ;
180+ for ( let i = 0 ; i <= this . EFUSE_MAX_KEY ; i ++ ) {
181+ const purpose = await this . getKeyBlockPurpose ( loader , i ) ;
182+ purposes . push ( purpose ) ;
183+ }
184+
185+ if ( purposes . some ( ( p ) => p === this . PURPOSE_VAL_XTS_AES128_KEY ) ) {
186+ return true ;
187+ }
188+
189+ const registerValue = await loader . readReg ( this . EFUSE_FORCE_USE_KEY_MANAGER_KEY_REG ) ;
190+ return (
191+ ( ( registerValue >> this . EFUSE_FORCE_USE_KEY_MANAGER_KEY_SHIFT ) & this . FORCE_USE_KEY_MANAGER_VAL_XTS_AES_KEY ) !== 0
192+ ) ;
193+ }
194+
195+ public checkSpiConnection ( loader : ESPLoader , spiConnection : number [ ] ) : void {
196+ if ( ! spiConnection . every ( ( pin ) => pin >= 0 && pin <= 28 ) ) {
197+ throw new Error ( "SPI Pin numbers must be in the range 0-28." ) ;
198+ }
199+ if ( spiConnection . some ( ( pin ) => pin === 13 || pin === 14 ) ) {
200+ loader . info (
201+ "GPIO pins 13 and 14 are used by USB-Serial/JTAG, " + "consider using other pins for SPI flash connection." ,
202+ ) ;
203+ }
204+ }
205+
206+ public async usesUsbJtagSerial ( loader : ESPLoader ) : Promise < boolean > {
207+ const uartBufNoAddr = this . UARTDEV_BUF_NO ;
208+ const uartNo = ( await loader . readReg ( uartBufNoAddr ) ) & 0xff ;
209+ // ESP32-C5 uses value 3 for USB-JTAG/Serial (similar to ESP32-S3/H2)
210+ return uartNo === 3 ;
211+ }
212+
213+ public async watchdogReset ( loader : ESPLoader ) : Promise < void > {
214+ // Watchdog reset disabled in parent (ESP32-C6) ROM, re-enable it
215+ // This should call the ESP32C3ROM.watchdogReset method
216+ // Note: This is a placeholder - the actual implementation would need
217+ // the watchdog registers from ESP32C3ROM
218+ loader . info ( "Hard resetting with a watchdog..." ) ;
219+ // TODO: Implement watchdog reset using ESP32C3ROM registers
220+ throw new Error ( "watchdogReset not yet implemented for ESP32-C5" ) ;
221+ }
222+
223+ public async changeBaud ( loader : ESPLoader ) : Promise < void > {
224+ // Note: secure_download_mode check would need to be added to ESPLoader if needed
225+ // if (loader.secureDownloadMode) {
226+ // loader.info(
227+ // "Baud rate change is not supported in secure download mode. " + "Keeping 115200 baud.",
228+ // );
229+ // return;
230+ // }
231+ if ( ! loader . IS_STUB ) {
232+ const crystalFreqRomExpect = await this . getCrystalFreqRomExpect ( loader ) ;
233+ const crystalFreqDetect = await this . getCrystalFreq ( loader ) ;
234+ loader . info ( `ROM expects crystal freq: ${ crystalFreqRomExpect } MHz, ` + `detected ${ crystalFreqDetect } MHz.` ) ;
235+ // If detect the XTAL is 48MHz, but the ROM code expects it to be 40MHz
236+ if ( crystalFreqDetect === 48 && crystalFreqRomExpect === 40 ) {
237+ loader . info (
238+ "Crystal frequency mismatch detected. " +
239+ "Baud rate adjustment may be needed but is not fully implemented in this version." ,
240+ ) ;
241+ }
242+ // If detect the XTAL is 40MHz, but the ROM code expects it to be 48MHz
243+ else if ( crystalFreqDetect === 40 && crystalFreqRomExpect === 48 ) {
244+ loader . info (
245+ "Crystal frequency mismatch detected. " +
246+ "Baud rate adjustment may be needed but is not fully implemented in this version." ,
247+ ) ;
248+ }
249+ }
250+ // Call the standard changeBaud method
251+ await loader . changeBaud ( ) ;
252+ }
150253}
0 commit comments