@@ -1284,6 +1284,10 @@ def run_stub(self, stub: StubFlasher | None = None) -> "ESPLoader":
1284
1284
log .print ("Stub flasher is already running. No upload is necessary." )
1285
1285
return self .STUB_CLASS (self ) if self .STUB_CLASS is not None else self
1286
1286
1287
+ secure_boot_workflow = (
1288
+ self .CHIP_NAME == "ESP32-S3" and self .get_secure_boot_enabled ()
1289
+ )
1290
+
1287
1291
# Upload
1288
1292
log .print ("Uploading stub flasher..." )
1289
1293
for field in [stub .text , stub .data ]:
@@ -1296,8 +1300,24 @@ def run_stub(self, stub: StubFlasher | None = None) -> "ESPLoader":
1296
1300
from_offs = seq * self .ESP_RAM_BLOCK
1297
1301
to_offs = from_offs + self .ESP_RAM_BLOCK
1298
1302
self .mem_block (field [from_offs :to_offs ], seq )
1303
+
1299
1304
log .print ("Running stub flasher..." )
1300
- self .mem_finish (stub .entry )
1305
+ if not secure_boot_workflow :
1306
+ self .mem_finish (stub .entry )
1307
+ else :
1308
+ # Bug in ESP32-S3 ROM prevents stub execution if secure boot is enabled
1309
+ # Hijack the `read` function in ROM to point to the stub entrypoint
1310
+ # got with GDB - p &rom_spiflash_legacy_funcs.read
1311
+ rom_spiflash_legacy_funcs_read_ptr = 0x3FCEF688
1312
+ self .mem_finish (0 ) # Finish uploading to RAM but don't run the stub yet
1313
+ stored_read_pointer = self .read_reg (rom_spiflash_legacy_funcs_read_ptr )
1314
+ self .write_reg (rom_spiflash_legacy_funcs_read_ptr , stub .entry )
1315
+ self .command ( # Trigger the `read` in ROM to jump to the stub entrypoint
1316
+ self .ESP_CMDS ["READ_FLASH_SLOW" ],
1317
+ struct .pack ("<II" , 0 , 0 ),
1318
+ wait_response = False ,
1319
+ )
1320
+
1301
1321
try :
1302
1322
p = self .read ()
1303
1323
except StopIteration :
@@ -1309,6 +1329,9 @@ def run_stub(self, stub: StubFlasher | None = None) -> "ESPLoader":
1309
1329
1310
1330
if p != b"OHAI" :
1311
1331
raise FatalError (f"Failed to start stub flasher. Unexpected response: { p } " )
1332
+ if secure_boot_workflow :
1333
+ # Restore the original `read` function pointer
1334
+ self .write_reg (rom_spiflash_legacy_funcs_read_ptr , stored_read_pointer )
1312
1335
log .stage (finish = True )
1313
1336
log .print ("Stub flasher running." )
1314
1337
return self .STUB_CLASS (self ) if self .STUB_CLASS is not None else self
0 commit comments