Repository: chipsalliance/caliptra-sw
Pull request #792 (2023-09-14 20:29:07)

Make test-fmc use FIRMWARE_LOAD to trigger the update reset.
This is necessary to work around the race condition in #786.

bluegate010: Will probably also want to make the same change [here](https://github.com/chipsalliance/caliptra-sw/blob/b1f43f36f8a5e2d262b04c702b324baf8addd33c/fmc/tests/test_rtalias.rs#L179).
korran: (Waiting for verilator tests to run to confirm that this fully fixes #786)
korran: Confirmed that the tests passed under verilator.

Patch:
diff --git a/hw-model/src/lib.rs b/hw-model/src/lib.rs
index bfdc81e2..7ea55906 100644
--- a/hw-model/src/lib.rs
+++ b/hw-model/src/lib.rs
@@ -671,6 +671,16 @@ pub trait HwModel {
         cmd: u32,
         buf: &[u8],
     ) -> std::result::Result<Option<Vec<u8>>, ModelError> {
+        self.start_mailbox_execute(cmd, buf)?;
+        self.finish_mailbox_execute()
+    }
+
+    /// Send a command to the mailbox but don't wait for the response
+    fn start_mailbox_execute(
+        &mut self,
+        cmd: u32,
+        buf: &[u8],
+    ) -> std::result::Result<(), ModelError> {
         if self.soc_mbox().lock().read().lock() {
             return Err(ModelError::UnableToLockMailbox);
         }
@@ -688,6 +698,11 @@ pub trait HwModel {
         // Ask the microcontroller to execute this command
         self.soc_mbox().execute().write(|w| w.execute(true));
 
+        Ok(())
+    }
+
+    /// Wait for the response to a previous call to `start_mailbox_execute()`.
+    fn finish_mailbox_execute(&mut self) -> std::result::Result<Option<Vec<u8>>, ModelError> {
         // Wait for the microcontroller to finish executing
         while self.soc_mbox().status().read().status().cmd_busy() {
             self.step();


Test patch:
diff --git a/rom/dev/tests/test_fake_rom.rs b/rom/dev/tests/test_fake_rom.rs
index b5d41f69..2dedf3e1 100644
--- a/rom/dev/tests/test_fake_rom.rs
+++ b/rom/dev/tests/test_fake_rom.rs
@@ -2,6 +2,7 @@
 
 use caliptra_builder::ROM_FAKE_WITH_UART;
 use caliptra_builder::{FwId, ImageOptions, APP_WITH_UART};
+use caliptra_common::mailbox_api::CommandId;
 use caliptra_common::RomBootStatus::*;
 use caliptra_drivers::{Array4x12, CaliptraError};
 use caliptra_hw_model::{
@@ -10,8 +11,6 @@ use caliptra_hw_model::{
 
 pub mod helpers;
 
-const TEST_FMC_CMD_RESET_FOR_UPDATE: u32 = 0x1000_0004;
-
 const PUB_KEY_X: [u8; 48] = [
     0xD7, 0x9C, 0x6D, 0x97, 0x2B, 0x34, 0xA1, 0xDF, 0xC9, 0x16, 0xA7, 0xB6, 0xE0, 0xA9, 0x9B, 0x6B,
     0x53, 0x87, 0xB3, 0x4D, 0xA2, 0x18, 0x76, 0x07, 0xC1, 0xAD, 0x0A, 0x4D, 0x1A, 0x8C, 0x2E, 0x41,
@@ -142,18 +141,19 @@ fn test_fake_rom_update_reset() {
 
     hw.step_until_boot_status(ColdResetComplete.into(), true);
 
-    // Send command to test FMC to initiate a reset for update
-    hw.mailbox_execute(TEST_FMC_CMD_RESET_FOR_UPDATE, &[])
-        .unwrap();
+    // Upload FW again
+    hw.start_mailbox_execute(
+        CommandId::FIRMWARE_LOAD.into(),
+        &image_bundle.to_bytes().unwrap(),
+    )
+    .unwrap();
 
     hw.step_until_boot_status(UpdateResetStarted.into(), true);
 
-    // Upload FW again
-    hw.step_until(|m| m.soc_ifc().cptra_flow_status().read().ready_for_fw());
-    hw.upload_firmware(&image_bundle.to_bytes().unwrap())
-        .unwrap();
-
     hw.step_until_boot_status(UpdateResetComplete.into(), true);
+
+    assert_eq!(hw.finish_mailbox_execute(), Ok(None));
+
     hw.step_until_exit_success().unwrap();
 }
 
diff --git a/rom/dev/tests/test_fmcalias_derivation.rs b/rom/dev/tests/test_fmcalias_derivation.rs
index 78a62d4c..a0840788 100644
--- a/rom/dev/tests/test_fmcalias_derivation.rs
+++ b/rom/dev/tests/test_fmcalias_derivation.rs
@@ -422,8 +422,6 @@ fn test_pcr_log_across_update_reset() {
     }
 
     // Trigger an update reset.
-    hw.mailbox_execute(0x1000_0004, &[]).unwrap();
-    hw.step_until_boot_status(UpdateResetStarted.into(), true);
     hw.upload_firmware(&image_bundle.to_bytes().unwrap())
         .unwrap();
     hw.step_until_boot_status(UpdateResetComplete.into(), true);
diff --git a/rom/dev/tests/test_update_reset.rs b/rom/dev/tests/test_update_reset.rs
index 964a160b..9b84a8a0 100644
--- a/rom/dev/tests/test_update_reset.rs
+++ b/rom/dev/tests/test_update_reset.rs
@@ -4,12 +4,13 @@ use caliptra_builder::{FwId, ImageOptions, APP_WITH_UART, ROM_WITH_UART};
 use caliptra_common::mailbox_api::CommandId;
 use caliptra_common::RomBootStatus::*;
 use caliptra_error::CaliptraError;
-use caliptra_hw_model::{BootParams, Fuses, HwModel, InitParams, SecurityState};
+use caliptra_hw_model::{BootParams, HwModel, InitParams};
 use caliptra_image_fake_keys::VENDOR_CONFIG_KEY_0;
 use caliptra_image_gen::ImageGeneratorVendorConfig;
 pub mod helpers;
 
 const TEST_FMC_CMD_RESET_FOR_UPDATE: u32 = 0x1000_0004;
+const TEST_FMC_CMD_RESET_FOR_UPDATE_KEEP_MBOX_CMD: u32 = 0x1000_000B;
 
 #[test]
 fn test_update_reset_success() {
@@ -20,43 +21,40 @@ fn test_update_reset_success() {
         workspace_dir: None,
     };
 
-    let fuses = Fuses::default();
     let rom = caliptra_builder::build_firmware_rom(&ROM_WITH_UART).unwrap();
+    let image_bundle = caliptra_builder::build_and_sign_image(
+        &TEST_FMC_WITH_UART,
+        &APP_WITH_UART,
+        ImageOptions::default(),
+    )
+    .unwrap();
+
     let mut hw = caliptra_hw_model::new(BootParams {
         init_params: InitParams {
             rom: &rom,
-            security_state: SecurityState::from(fuses.life_cycle as u32),
             ..Default::default()
         },
-        fuses,
+        fw_image: Some(&image_bundle.to_bytes().unwrap()),
         ..Default::default()
     })
     .unwrap();
 
-    let image_bundle = caliptra_builder::build_and_sign_image(
-        &TEST_FMC_WITH_UART,
-        &APP_WITH_UART,
-        ImageOptions::default(),
-    )
-    .unwrap();
-
-    hw.step_until_boot_status(KatStarted.into(), true);
-
-    hw.upload_firmware(&image_bundle.to_bytes().unwrap())
-        .unwrap();
-
     hw.step_until_boot_status(ColdResetComplete.into(), true);
 
-    hw.mailbox_execute(TEST_FMC_CMD_RESET_FOR_UPDATE, &[])
-        .unwrap();
+    // Trigger an update reset with "new" firmware
+    hw.start_mailbox_execute(
+        CommandId::FIRMWARE_LOAD.into(),
+        &image_bundle.to_bytes().unwrap(),
+    )
+    .unwrap();
 
     hw.step_until_boot_status(KatStarted.into(), true);
     hw.step_until_boot_status(KatComplete.into(), true);
-
     hw.step_until_boot_status(UpdateResetStarted.into(), false);
 
-    hw.upload_firmware(&image_bundle.to_bytes().unwrap())
-        .unwrap();
+    assert_eq!(hw.finish_mailbox_execute(), Ok(None));
+
+    hw.step_until_boot_status(UpdateResetComplete.into(), true);
 
     hw.step_until_exit_success().unwrap();
 }
@@ -70,31 +68,27 @@ fn test_update_reset_no_mailbox_cmd() {
         workspace_dir: None,
     };
 
-    let fuses = Fuses::default();
     let rom = caliptra_builder::build_firmware_rom(&ROM_WITH_UART).unwrap();
+    let image_bundle = caliptra_builder::build_and_sign_image(
+        &TEST_FMC_WITH_UART,
+        &APP_WITH_UART,
+        ImageOptions::default(),
+    )
+    .unwrap();
     let mut hw = caliptra_hw_model::new(BootParams {
         init_params: InitParams {
             rom: &rom,
-            security_state: SecurityState::from(fuses.life_cycle as u32),
             ..Default::default()
         },
-        fuses,
+        fw_image: Some(&image_bundle.to_bytes().unwrap()),
         ..Default::default()
     })
     .unwrap();
 
-    let image_bundle = caliptra_builder::build_and_sign_image(
-        &TEST_FMC_WITH_UART,
-        &APP_WITH_UART,
-        ImageOptions::default(),
-    )
-    .unwrap();
-
-    hw.upload_firmware(&image_bundle.to_bytes().unwrap())
-        .unwrap();
-
     hw.step_until_boot_status(ColdResetComplete.into(), true);
 
+    // This command tells the test-fmc to do an update reset after clearing
+    // itself from the mailbox.
     hw.mailbox_execute(TEST_FMC_CMD_RESET_FOR_UPDATE, &[])
         .unwrap();
 
@@ -103,17 +97,15 @@ fn test_update_reset_no_mailbox_cmd() {
     hw.step_until_boot_status(UpdateResetStarted.into(), false);
 
     // No command in the mailbox.
-    hw.soc_mbox().cmd().write(|_| 0);
     hw.step_until(|m| m.soc_ifc().cptra_fw_error_non_fatal().read() != 0);
-
-    let _ = hw.mailbox_execute(0xDEADBEEF, &[]);
-    hw.step_until_exit_success().unwrap();
-
     assert_eq!(
         hw.soc_ifc().cptra_fw_error_non_fatal().read(),
         CaliptraError::ROM_UPDATE_RESET_FLOW_MAILBOX_ACCESS_FAILURE.into()
     );
 
+    let _ = hw.mailbox_execute(0xDEADBEEF, &[]);
+    hw.step_until_exit_success().unwrap();
+
     assert_eq!(
         hw.soc_ifc().cptra_boot_status().read(),
         UpdateResetStarted.into()
@@ -129,38 +121,33 @@ fn test_update_reset_non_fw_load_cmd() {
         workspace_dir: None,
     };
 
-    let fuses = Fuses::default();
     let rom = caliptra_builder::build_firmware_rom(&ROM_WITH_UART).unwrap();
+    let image_bundle = caliptra_builder::build_and_sign_image(
+        &TEST_FMC_WITH_UART,
+        &APP_WITH_UART,
+        ImageOptions::default(),
+    )
+    .unwrap();
     let mut hw = caliptra_hw_model::new(BootParams {
         init_params: InitParams {
             rom: &rom,
-            security_state: SecurityState::from(fuses.life_cycle as u32),
             ..Default::default()
         },
-        fuses,
+        fw_image: Some(&image_bundle.to_bytes().unwrap()),
         ..Default::default()
     })
     .unwrap();
 
-    let image_bundle = caliptra_builder::build_and_sign_image(
-        &TEST_FMC_WITH_UART,
-        &APP_WITH_UART,
-        ImageOptions::default(),
-    )
-    .unwrap();
-
-    hw.upload_firmware(&image_bundle.to_bytes().unwrap())
-        .unwrap();
-
     hw.step_until_boot_status(ColdResetComplete.into(), true);
 
-    hw.mailbox_execute(TEST_FMC_CMD_RESET_FOR_UPDATE, &[])
+    // This command tells the test-fmc to do an update reset but leave the
+    // "unknown" command in the mailbox for the ROM to find
+    hw.start_mailbox_execute(TEST_FMC_CMD_RESET_FOR_UPDATE_KEEP_MBOX_CMD, &[])
         .unwrap();
     hw.step_until_boot_status(KatStarted.into(), true);
     hw.step_until_boot_status(KatComplete.into(), true);
     hw.step_until_boot_status(UpdateResetStarted.into(), false);
 
-    // Send a non-fw load command
     let _ = hw.mailbox_execute(0xDEADBEEF, &[]);
     hw.step_until_exit_success().unwrap();
 
@@ -184,41 +171,35 @@ fn test_update_reset_verify_image_failure() {
         workspace_dir: None,
     };
 
-    let fuses = Fuses::default();
     let rom = caliptra_builder::build_firmware_rom(&ROM_WITH_UART).unwrap();
+    let image_bundle = caliptra_builder::build_and_sign_image(
+        &TEST_FMC_WITH_UART,
+        &APP_WITH_UART,
+        ImageOptions::default(),
+    )
+    .unwrap();
     let mut hw = caliptra_hw_model::new(BootParams {
         init_params: InitParams {
             rom: &rom,
-            security_state: SecurityState::from(fuses.life_cycle as u32),
             ..Default::default()
         },
-        fuses,
+        fw_image: Some(&image_bundle.to_bytes().unwrap()),
         ..Default::default()
     })
     .unwrap();
 
-    let image_bundle = caliptra_builder::build_and_sign_image(
-        &TEST_FMC_WITH_UART,
-        &APP_WITH_UART,
-        ImageOptions::default(),
-    )
-    .unwrap();
-
-    hw.upload_firmware(&image_bundle.to_bytes().unwrap())
-        .unwrap();
-
     hw.step_until_boot_status(ColdResetComplete.into(), true);
 
-    hw.mailbox_execute(TEST_FMC_CMD_RESET_FOR_UPDATE, &[])
+    // Upload invalid manifest
+    hw.start_mailbox_execute(CommandId::FIRMWARE_LOAD.into(), &[0u8; 4])
         .unwrap();
+
     hw.step_until_boot_status(KatStarted.into(), true);
     hw.step_until_boot_status(KatComplete.into(), true);
-
     hw.step_until_boot_status(UpdateResetStarted.into(), false);
 
-    // Upload invalid manifest
     assert_eq!(
-        hw.upload_firmware(&[0u8; 4]),
+        hw.finish_mailbox_execute(),
         Err(caliptra_hw_model::ModelError::MailboxCmdFailed(
             CaliptraError::IMAGE_VERIFIER_ERR_MANIFEST_MARKER_MISMATCH.into()
         ))
@@ -246,62 +227,35 @@ fn test_update_reset_boot_status() {
         workspace_dir: None,
     };
 
-    let fuses = Fuses::default();
     let rom = caliptra_builder::build_firmware_rom(&ROM_WITH_UART).unwrap();
+    let image_bundle = caliptra_builder::build_and_sign_image(
+        &TEST_FMC_WITH_UART,
+        &APP_WITH_UART,
+        ImageOptions::default(),
+    )
+    .unwrap();
     let mut hw = caliptra_hw_model::new(BootParams {
         init_params: InitParams {
             rom: &rom,
-            security_state: SecurityState::from(fuses.life_cycle as u32),
             ..Default::default()
         },
-        fuses,
+        fw_image: Some(&image_bundle.to_bytes().unwrap()),
         ..Default::default()
     })
     .unwrap();
 
-    let image_bundle = caliptra_builder::build_and_sign_image(
-        &TEST_FMC_WITH_UART,
-        &APP_WITH_UART,
-        ImageOptions::default(),
+    hw.step_until_boot_status(ColdResetComplete.into(), true);
+
+    // Start the firmware update process
+    hw.start_mailbox_execute(
+        CommandId::FIRMWARE_LOAD.into(),
+        &image_bundle.to_bytes().unwrap(),
     )
     .unwrap();
 
-    hw.upload_firmware(&image_bundle.to_bytes().unwrap())
-        .unwrap();
-
-    hw.step_until_boot_status(FmcAliasDerivationComplete.into(), true);
-
-    hw.mailbox_execute(TEST_FMC_CMD_RESET_FOR_UPDATE, &[])
-        .unwrap();
-    hw.step_until_boot_status(KatStarted.into(), true);
-    hw.step_until_boot_status(KatComplete.into(), true);
-
+    hw.step_until_boot_status(KatStarted.into(), false);
+    hw.step_until_boot_status(KatComplete.into(), false);
     hw.step_until_boot_status(UpdateResetStarted.into(), false);
-
-    // Manually put the firmware in the mailbox because
-    // HwModel::upload_firmware returns only when the transaction is complete.
-    // This is too late for this test.
-    let buf: &[u8] = &image_bundle.to_bytes().unwrap();
-    assert!(!hw.soc_mbox().lock().read().lock());
-    hw.soc_mbox()
-        .cmd()
-        .write(|_| CommandId::FIRMWARE_LOAD.into());
-    hw.soc_mbox().dlen().write(|_| buf.len() as u32);
-    let mut remaining = buf;
-    while remaining.len() >= 4 {
-        // Panic is impossible because the subslice is always 4 bytes
-        let word = u32::from_le_bytes(remaining[..4].try_into().unwrap());
-        hw.soc_mbox().datain().write(|_| word);
-        remaining = &remaining[4..];
-    }
-    if !remaining.is_empty() {
-        let mut word_bytes = [0u8; 4];
-        word_bytes[..remaining.len()].copy_from_slice(remaining);
-        let word = u32::from_le_bytes(word_bytes);
-        hw.soc_mbox().datain().write(|_| word);
-    }
-    hw.soc_mbox().execute().write(|w| w.execute(true));
-
     hw.step_until_boot_status(UpdateResetLoadManifestComplete.into(), false);
     hw.step_until_boot_status(UpdateResetImageVerificationComplete.into(), false);
     hw.step_until_boot_status(UpdateResetPopulateDataVaultComplete.into(), false);
@@ -310,6 +264,8 @@ fn test_update_reset_boot_status() {
     hw.step_until_boot_status(UpdateResetOverwriteManifestComplete.into(), false);
     hw.step_until_boot_status(UpdateResetComplete.into(), false);
 
+    assert_eq!(hw.finish_mailbox_execute(), Ok(None));
+
     hw.step_until_exit_success().unwrap();
 }
 
@@ -322,19 +278,7 @@ fn test_update_reset_vendor_ecc_pub_key_idx_dv_mismatch() {
         workspace_dir: None,
     };
 
-    let fuses = Fuses::default();
     let rom = caliptra_builder::build_firmware_rom(&ROM_WITH_UART).unwrap();
-    let mut hw = caliptra_hw_model::new(BootParams {
-        init_params: InitParams {
-            rom: &rom,
-            security_state: SecurityState::from(fuses.life_cycle as u32),
-            ..Default::default()
-        },
-        fuses,
-        ..Default::default()
-    })
-    .unwrap();
-
     let vendor_config_cold_boot = ImageGeneratorVendorConfig {
         ecc_key_idx: 3,
         ..VENDOR_CONFIG_KEY_0
@@ -343,20 +287,21 @@ fn test_update_reset_vendor_ecc_pub_key_idx_dv_mismatch() {
         vendor_config: vendor_config_cold_boot,
         ..Default::default()
     };
-
     let image_bundle =
         caliptra_builder::build_and_sign_image(&TEST_FMC_WITH_UART, &APP_WITH_UART, image_options)
             .unwrap();
-
-    hw.upload_firmware(&image_bundle.to_bytes().unwrap())
-        .unwrap();
+    let mut hw = caliptra_hw_model::new(BootParams {
+        init_params: InitParams {
+            rom: &rom,
+            ..Default::default()
+        },
+        fw_image: Some(&image_bundle.to_bytes().unwrap()),
+        ..Default::default()
+    })
+    .unwrap();
 
     hw.step_until_boot_status(ColdResetComplete.into(), true);
 
-    hw.mailbox_execute(TEST_FMC_CMD_RESET_FOR_UPDATE, &[])
-        .unwrap();
-    hw.step_until_boot_status(UpdateResetStarted.into(), true);
-
     // Upload firmware with a different vendor ECC key index.
     let vendor_config_update_reset = ImageGeneratorVendorConfig {
         ecc_key_idx: 2,
@@ -371,7 +316,20 @@ fn test_update_reset_vendor_ecc_pub_key_idx_dv_mismatch() {
         caliptra_builder::build_and_sign_image(&TEST_FMC_WITH_UART, &APP_WITH_UART, image_options)
             .unwrap();
 
-    let _ = hw.upload_firmware(&image_bundle.to_bytes().unwrap());
+    hw.start_mailbox_execute(
+        CommandId::FIRMWARE_LOAD.into(),
+        &image_bundle.to_bytes().unwrap(),
+    )
+    .unwrap();
+
+    hw.step_until_boot_status(UpdateResetStarted.into(), true);
+
+    assert_eq!(
+        hw.finish_mailbox_execute(),
+        Err(caliptra_hw_model::ModelError::MailboxCmdFailed(
+            CaliptraError::IMAGE_VERIFIER_ERR_UPDATE_RESET_VENDOR_ECC_PUB_KEY_IDX_MISMATCH.into()
+        ))
+    );
 
     hw.step_until_exit_success().unwrap();
 
@@ -390,23 +348,7 @@ fn test_update_reset_vendor_lms_pub_key_idx_dv_mismatch() {
         workspace_dir: None,
     };
 
-    let fuses = caliptra_hw_model::Fuses {
-        lms_verify: true,
-        ..Default::default()
-    };
-
     let rom = caliptra_builder::build_firmware_rom(&ROM_WITH_UART).unwrap();
-    let mut hw = caliptra_hw_model::new(BootParams {
-        init_params: InitParams {
-            rom: &rom,
-            security_state: SecurityState::from(fuses.life_cycle as u32),
-            ..Default::default()
-        },
-        fuses,
-        ..Default::default()
-    })
-    .unwrap();
-
     let vendor_config_cold_boot = ImageGeneratorVendorConfig {
         lms_key_idx: 3,
         ..VENDOR_CONFIG_KEY_0
@@ -415,21 +357,25 @@ fn test_update_reset_vendor_lms_pub_key_idx_dv_mismatch() {
         vendor_config: vendor_config_cold_boot,
         ..Default::default()
     };
-
     let image_bundle =
         caliptra_builder::build_and_sign_image(&TEST_FMC_WITH_UART, &APP_WITH_UART, image_options)
             .unwrap();
-
-    hw.upload_firmware(&image_bundle.to_bytes().unwrap())
-        .unwrap();
+    let mut hw = caliptra_hw_model::new(BootParams {
+        init_params: InitParams {
+            rom: &rom,
+            ..Default::default()
+        },
+        fuses: caliptra_hw_model::Fuses {
+            lms_verify: true,
+            ..Default::default()
+        },
+        fw_image: Some(&image_bundle.to_bytes().unwrap()),
+        ..Default::default()
+    })
+    .unwrap();
 
     hw.step_until_boot_status(ColdResetComplete.into(), true);
 
-    hw.mailbox_execute(TEST_FMC_CMD_RESET_FOR_UPDATE, &[])
-        .unwrap();
-
-    hw.step_until_boot_status(UpdateResetStarted.into(), true);
-
     // Upload firmware with a different vendor LMS key index.
     let vendor_config_update_reset = ImageGeneratorVendorConfig {
         lms_key_idx: 2,
@@ -444,7 +390,12 @@ fn test_update_reset_vendor_lms_pub_key_idx_dv_mismatch() {
         caliptra_builder::build_and_sign_image(&TEST_FMC_WITH_UART, &APP_WITH_UART, image_options)
             .unwrap();
 
-    let _ = hw.upload_firmware(&image_bundle.to_bytes().unwrap());
+    assert_eq!(
+        hw.upload_firmware(&image_bundle.to_bytes().unwrap()),
+        Err(caliptra_hw_model::ModelError::MailboxCmdFailed(
+            CaliptraError::IMAGE_VERIFIER_ERR_UPDATE_RESET_VENDOR_LMS_PUB_KEY_IDX_MISMATCH.into()
+        ))
+    );
 
     hw.step_until_exit_success().unwrap();
 
diff --git a/rom/dev/tools/test-fmc/src/main.rs b/rom/dev/tools/test-fmc/src/main.rs
index a7d7a942..5461835a 100644
--- a/rom/dev/tools/test-fmc/src/main.rs
+++ b/rom/dev/tools/test-fmc/src/main.rs
@@ -15,7 +15,7 @@ Abstract:
 #![cfg_attr(not(feature = "std"), no_main)]
 
 use caliptra_common::pcr::PCR_ID_STASH_MEASUREMENT;
-use caliptra_common::{FuseLogEntry, FuseLogEntryId};
+use caliptra_common::{mailbox_api, FuseLogEntry, FuseLogEntryId};
 use caliptra_common::{PcrLogEntry, PcrLogEntryId};
 use caliptra_drivers::pcr_log::MeasurementLogEntry;
 use caliptra_drivers::{
@@ -24,8 +24,8 @@ use caliptra_drivers::{
 };
 use caliptra_registers::dv::DvReg;
 use caliptra_registers::pv::PvReg;
+use caliptra_registers::soc_ifc::SocIfcReg;
 use caliptra_x509::{Ecdsa384CertBuilder, Ecdsa384Signature, FmcAliasCertTbs, LocalDevIdCertTbs};
-use core::ptr;
 use ureg::RealMmioMut;
 use zerocopy::AsBytes;
 
@@ -35,6 +35,8 @@ core::arch::global_asm!(include_str!("start.S"));
 mod exception;
 mod print;
 
+const FW_LOAD_CMD_OPCODE: u32 = mailbox_api::CommandId::FIRMWARE_LOAD.0;
+
 #[cfg(feature = "std")]
 pub fn main() {}
 
@@ -178,6 +180,9 @@ fn get_measurement_entry(entry_index: usize) -> MeasurementLogEntry {
 }
 
 fn process_mailbox_command(mbox: &caliptra_registers::mbox::RegisterBlock<RealMmioMut>) {
+    if !mbox.status().read().mbox_fsm_ps().mbox_execute_uc() {
+        return;
+    }
     let cmd = mbox.cmd().read();
     cprintln!("[fmc] Received command: 0x{:08X}", cmd);
     match cmd {
@@ -194,8 +199,11 @@ fn process_mailbox_command(mbox: &caliptra_registers::mbox::RegisterBlock<RealMm
             read_fht(mbox);
         }
         0x1000_0004 => {
-            trigger_update_reset(mbox);
+            mbox.status().write(|w| w.status(|w| w.cmd_complete()));
+            // Reset the CPU with no command in the mailbox
+            trigger_update_reset();
         }
+
         0x1000_0005 => {
             read_datavault_coldresetentry4(mbox);
         }
@@ -214,7 +222,14 @@ fn process_mailbox_command(mbox: &caliptra_registers::mbox::RegisterBlock<RealMm
         0x1000_000A => {
             read_measurement_log(mbox);
         }
-
+        0x1000_000B => {
+            // Reset the CPU with an unknown command in the mailbox
+            trigger_update_reset();
+        }
+        FW_LOAD_CMD_OPCODE => {
+            // Reset the CPU with the firmware-update command in the mailbox
+            trigger_update_reset();
+        }
         _ => {}
     }
 }
@@ -262,12 +277,11 @@ fn read_datavault_coldresetentry4(mbox: &caliptra_registers::mbox::RegisterBlock
     mbox.status().write(|w| w.status(|w| w.data_ready()));
 }
 
-fn trigger_update_reset(mbox: &caliptra_registers::mbox::RegisterBlock<RealMmioMut>) {
-    mbox.status().write(|w| w.status(|w| w.cmd_complete()));
-    const STDOUT: *mut u32 = 0x3003_0624 as *mut u32;
-    unsafe {
-        ptr::write_volatile(STDOUT, 1_u32);
-    }
+fn trigger_update_reset() {
+    unsafe { SocIfcReg::new() }
+        .regs_mut()
+        .internal_fw_update_reset()
+        .write(|w| w.core_rst(true));
 }
 
 fn read_pcr_log(mbox: &caliptra_registers::mbox::RegisterBlock<RealMmioMut>) {