@@ -39,6 +39,9 @@ use tock_registers::register_bitfields;
39
39
/// Firmware Load Command Opcode
40
40
const FW_LOAD_CMD_OPCODE : u32 = 0x4657_4C44 ;
41
41
42
+ /// Recovery register interface download Command Opcode
43
+ const RI_DOWNLOAD_FIRMWARE : u32 = 0x5249_4644 ;
44
+
42
45
/// The number of CPU clock cycles it takes to write the firmware to the mailbox.
43
46
const FW_WRITE_TICKS : u64 = 1000 ;
44
47
@@ -162,6 +165,11 @@ fn main() -> io::Result<()> {
162
165
. value_parser ( value_parser ! ( u64 ) )
163
166
. default_value ( & ( EXPECTED_CALIPTRA_BOOT_TIME_IN_CYCLES . to_string ( ) ) )
164
167
)
168
+ . arg (
169
+ arg ! ( --"active-mode" ... "Active mode: get image update via recovery register interface" )
170
+ . required ( false )
171
+ . action ( ArgAction :: SetTrue )
172
+ )
165
173
. get_matches ( ) ;
166
174
167
175
let args_rom = args. get_one :: < PathBuf > ( "rom" ) . unwrap ( ) ;
@@ -267,6 +275,11 @@ fn main() -> io::Result<()> {
267
275
} ,
268
276
) ;
269
277
278
+ let active_mode = args. get_flag ( "active-mode" ) ;
279
+
280
+ // Clippy seems wrong about this clone not being necessary
281
+ #[ allow( clippy:: redundant_clone) ]
282
+ let firmware_buffer = current_fw_buf. clone ( ) ;
270
283
let bus_args = CaliptraRootBusArgs {
271
284
rom : rom_buffer,
272
285
log_dir : args_log_dir. clone ( ) ,
@@ -275,12 +288,20 @@ fn main() -> io::Result<()> {
275
288
0xFF => exit ( 0x00 ) ,
276
289
_ => print ! ( "{}" , val as char ) ,
277
290
} ) ,
278
- ready_for_fw_cb : ReadyForFwCb :: new ( move |args| {
279
- let firmware_buffer = current_fw_buf. clone ( ) ;
280
- args. schedule_later ( FW_WRITE_TICKS , move |mailbox : & mut MailboxInternal | {
281
- upload_fw_to_mailbox ( mailbox, firmware_buffer) ;
282
- } ) ;
283
- } ) ,
291
+ ready_for_fw_cb : if active_mode {
292
+ ReadyForFwCb :: new ( move |args| {
293
+ args. schedule_later ( FW_WRITE_TICKS , move |mailbox : & mut MailboxInternal | {
294
+ rri_download ( mailbox)
295
+ } )
296
+ } )
297
+ } else {
298
+ ReadyForFwCb :: new ( move |args| {
299
+ let firmware_buffer = firmware_buffer. clone ( ) ;
300
+ args. schedule_later ( FW_WRITE_TICKS , move |mailbox : & mut MailboxInternal | {
301
+ upload_fw_to_mailbox ( mailbox, firmware_buffer)
302
+ } ) ;
303
+ } )
304
+ } ,
284
305
security_state,
285
306
upload_update_fw : UploadUpdateFwCb :: new ( move |mailbox : & mut MailboxInternal | {
286
307
upload_fw_to_mailbox ( mailbox, update_fw_buf. clone ( ) ) ;
@@ -294,10 +315,16 @@ fn main() -> io::Result<()> {
294
315
download_idev_id_csr ( mailbox, log_dir. clone ( ) , cptra_dbg_manuf_service_reg) ;
295
316
} ,
296
317
) ,
318
+ active_mode,
297
319
..Default :: default ( )
298
320
} ;
299
321
300
- let root_bus = CaliptraRootBus :: new ( & clock, bus_args) ;
322
+ let mut root_bus = CaliptraRootBus :: new ( & clock, bus_args) ;
323
+ // Populate the RRI data
324
+ if active_mode {
325
+ root_bus. dma . axi . recovery . cms_data = Some ( current_fw_buf) ;
326
+ }
327
+
301
328
let soc_ifc = unsafe {
302
329
caliptra_registers:: soc_ifc:: RegisterBlock :: new_with_mmio (
303
330
0x3003_0000 as * mut u32 ,
@@ -457,6 +484,22 @@ fn upload_fw_to_mailbox(mailbox: &mut MailboxInternal, firmware_buffer: Rc<Vec<u
457
484
soc_mbox. execute ( ) . write ( |w| w. execute ( true ) ) ;
458
485
}
459
486
487
+ fn rri_download ( mailbox : & mut MailboxInternal ) {
488
+ let soc_mbox = mailbox. as_external ( ) . regs ( ) ;
489
+ // Write the cmd to mailbox.
490
+
491
+ assert ! ( !soc_mbox. lock( ) . read( ) . lock( ) ) ;
492
+
493
+ // Set command
494
+ soc_mbox. cmd ( ) . write ( |_| RI_DOWNLOAD_FIRMWARE ) ;
495
+
496
+ // No data to send so set len to 0
497
+ soc_mbox. dlen ( ) . write ( |_| 0 ) ;
498
+
499
+ // Execute
500
+ soc_mbox. execute ( ) . write ( |w| w. execute ( true ) ) ;
501
+ }
502
+
460
503
fn download_idev_id_csr (
461
504
mailbox : & mut MailboxInternal ,
462
505
path : Rc < PathBuf > ,
0 commit comments