@@ -1213,6 +1213,10 @@ def run_stub(self, stub=None):
12131213 print ("Stub is already running. No upload is necessary." )
12141214 return self .STUB_CLASS (self )
12151215
1216+ secure_boot_workflow = (
1217+ self .CHIP_NAME == "ESP32-S3" and self .get_secure_boot_enabled ()
1218+ )
1219+
12161220 # Upload
12171221 print ("Uploading stub..." )
12181222 for field in [stub .text , stub .data ]:
@@ -1225,8 +1229,24 @@ def run_stub(self, stub=None):
12251229 from_offs = seq * self .ESP_RAM_BLOCK
12261230 to_offs = from_offs + self .ESP_RAM_BLOCK
12271231 self .mem_block (field [from_offs :to_offs ], seq )
1232+
12281233 print ("Running stub..." )
1229- self .mem_finish (stub .entry )
1234+ if not secure_boot_workflow :
1235+ self .mem_finish (stub .entry )
1236+ else :
1237+ # Bug in ESP32-S3 ROM prevents stub execution if secure boot is enabled
1238+ # Hijack the `read` function in ROM to point to the stub entrypoint
1239+ # got with GDB - p &rom_spiflash_legacy_funcs.read
1240+ rom_spiflash_legacy_funcs_read_ptr = 0x3FCEF688
1241+ self .mem_finish (0 ) # Finish uploading to RAM but don't run the stub yet
1242+ stored_read_pointer = self .read_reg (rom_spiflash_legacy_funcs_read_ptr )
1243+ self .write_reg (rom_spiflash_legacy_funcs_read_ptr , stub .entry )
1244+ self .command ( # Trigger the `read` in ROM to jump to the stub entrypoint
1245+ self .ESP_READ_FLASH_SLOW ,
1246+ struct .pack ("<II" , 0 , 0 ),
1247+ wait_response = False ,
1248+ )
1249+
12301250 try :
12311251 p = self .read ()
12321252 except StopIteration :
@@ -1238,6 +1258,9 @@ def run_stub(self, stub=None):
12381258
12391259 if p != b"OHAI" :
12401260 raise FatalError (f"Failed to start stub. Unexpected response: { p } " )
1261+ if secure_boot_workflow :
1262+ # Restore the original `read` function pointer
1263+ self .write_reg (rom_spiflash_legacy_funcs_read_ptr , stored_read_pointer )
12411264 print ("Stub running..." )
12421265 return self .STUB_CLASS (self )
12431266
0 commit comments