Repository: chipsalliance/caliptra-sw
Pull request #347 (2023-06-02 23:48:41)

[feat] Store ldevid/fmclias TBS sizes and PCR/Fuse log entry counts in FHT


Patch:
diff --git a/common/src/hand_off.rs b/common/src/hand_off.rs
index dad68aa8..23ac48de 100644
--- a/common/src/hand_off.rs
+++ b/common/src/hand_off.rs
@@ -261,6 +261,24 @@ pub struct FirmwareHandoffTable {
     /// Index of RT SVN value in the Data Vault
     pub rt_svn_dv_hdl: HandOffDataHandle,
 
+    /// LdevId TBS Address
+    pub ldevid_tbs_addr: u32,
+
+    /// FmcAlias TBS Address
+    pub fmcalias_tbs_addr: u32,
+
+    /// LdevId TBS Size.
+    pub ldevid_tbs_size: u16,
+
+    /// FmcAlias TBS Size.
+    pub fmcalias_tbs_size: u16,
+
+    /// PCR log Address
+    pub pcr_log_addr: u32,
+
+    /// Fuse log Address
+    pub fuse_log_addr: u32,
+
     /// Reserved for future use.
     pub reserved: [u8; 32],
 }
@@ -291,7 +309,13 @@ impl Default for FirmwareHandoffTable {
             rt_cert_sig_r_dv_hdl: FHT_INVALID_HANDLE,
             rt_cert_sig_s_dv_hdl: FHT_INVALID_HANDLE,
             rt_svn_dv_hdl: FHT_INVALID_HANDLE,
+            ldevid_tbs_size: 0,
+            fmcalias_tbs_size: 0,
             reserved: [0; 32],
+            ldevid_tbs_addr: 0,
+            fmcalias_tbs_addr: 0,
+            pcr_log_addr: 0,
+            fuse_log_addr: 0,
         }
     }
 }
@@ -362,6 +386,13 @@ pub fn print_fht(fht: &FirmwareHandoffTable) {
         fht.rt_cert_sig_s_dv_hdl.0
     );
     crate::cprintln!("RT SVN DV Handle: 0x{:08x}", fht.rt_svn_dv_hdl.0);
+
+    crate::cprintln!("LdevId TBS Address: 0x{:08x}", fht.ldevid_tbs_addr);
+    crate::cprintln!("LdevId TBS Size: {} bytes", fht.ldevid_tbs_size);
+    crate::cprintln!("FmcAlias TBS Address: 0x{:08x}", fht.fmcalias_tbs_addr);
+    crate::cprintln!("FmcAlias TBS Size: {} bytes", fht.fmcalias_tbs_size);
+    crate::cprintln!("PCR log Address: 0x{:08x}", fht.pcr_log_addr);
+    crate::cprintln!("Fuse log Address: 0x{:08x}", fht.fuse_log_addr);
 }
 
 impl FirmwareHandoffTable {
@@ -381,6 +412,12 @@ impl FirmwareHandoffTable {
             && self.rt_fw_entry_point_hdl != FHT_INVALID_HANDLE
             // This is for Gen1 POR.
             && self.fips_fw_load_addr_hdl == FHT_INVALID_HANDLE
+            && self.ldevid_tbs_size != 0
+            && self.fmcalias_tbs_size != 0
+            && self.ldevid_tbs_addr != 0
+            && self.fmcalias_tbs_addr != 0
+            && self.pcr_log_addr != 0
+            && self.fuse_log_addr != 0
     }
     /// Load FHT from its fixed address and perform validity check of
     /// its data.
@@ -414,8 +451,7 @@ pub fn report_handoff_error_and_halt(msg: &str, code: u32) -> ! {
 mod tests {
     use super::*;
     use core::mem;
-    // FHT is currently defined to be 60 bytes in length.
-    const FHT_SIZE: usize = 120;
+    const FHT_SIZE: usize = 140;
 
     fn rt_tci_store() -> HandOffDataHandle {
         HandOffDataHandle::from(DataStore::DataVaultNonSticky48(WarmResetEntry48::RtTci))
diff --git a/error/src/lib.rs b/error/src/lib.rs
index 978e94ae..2dfe75f2 100644
--- a/error/src/lib.rs
+++ b/error/src/lib.rs
@@ -320,6 +320,11 @@ impl CaliptraError {
     pub const ROM_GLOBAL_FUSE_LOG_UNSUPPORTED_DATA_LENGTH: CaliptraError =
         CaliptraError::new_const(0x01040007);
 
+    pub const ROM_GLOBAL_UNSUPPORTED_LDEVID_TBS_SIZE: CaliptraError =
+        CaliptraError::new_const(0x01040008);
+    pub const ROM_GLOBAL_UNSUPPORTED_FMCALIAS_TBS_SIZE: CaliptraError =
+        CaliptraError::new_const(0x01040009);
+
     /// ROM KAT Errors
     pub const ROM_KAT_SHA256_DIGEST_FAILURE: CaliptraError = CaliptraError::new_const(0x90010001);
     pub const ROM_KAT_SHA256_DIGEST_MISMATCH: CaliptraError = CaliptraError::new_const(0x90010002);
diff --git a/rom/dev/src/fht.rs b/rom/dev/src/fht.rs
index c1fe4232..e25cd22b 100644
--- a/rom/dev/src/fht.rs
+++ b/rom/dev/src/fht.rs
@@ -28,7 +28,22 @@ use crate::{
 const FHT_MAJOR_VERSION: u16 = 1;
 const FHT_MINOR_VERSION: u16 = 0;
 
-struct FhtDataStore {}
+extern "C" {
+    static mut LDEVID_TBS_ORG: u8;
+    static mut FMCALIAS_TBS_ORG: u8;
+    static mut PCR_LOG_ORG: u8;
+    static mut FUSE_LOG_ORG: u8;
+}
+
+#[derive(Debug, Default)]
+pub struct FhtDataStore {
+    /// LdevId TBS size
+    pub ldevid_tbs_size: u16,
+
+    /// FmcAlias TBS size
+    pub fmcalias_tbs_size: u16,
+}
+
 impl FhtDataStore {
     /// The FMC CDI is stored in a 32-bit DataVault sticky register.
     pub const fn fmc_cdi_store() -> HandOffDataHandle {
@@ -120,6 +135,18 @@ impl FhtDataStore {
 }
 
 pub fn make_fht(env: &RomEnv) -> FirmwareHandoffTable {
+    let ldevid_tbs_addr: u32;
+    let fmcalias_tbs_addr: u32;
+    let pcr_log_addr: u32;
+    let fuse_log_addr: u32;
+
+    unsafe {
+        ldevid_tbs_addr = &LDEVID_TBS_ORG as *const u8 as u32;
+        fmcalias_tbs_addr = &FMCALIAS_TBS_ORG as *const u8 as u32;
+        pcr_log_addr = &PCR_LOG_ORG as *const u8 as u32;
+        fuse_log_addr = &FUSE_LOG_ORG as *const u8 as u32;
+    }
+
     FirmwareHandoffTable {
         fht_marker: FHT_MARKER,
         fht_major_ver: FHT_MAJOR_VERSION,
@@ -144,6 +171,12 @@ pub fn make_fht(env: &RomEnv) -> FirmwareHandoffTable {
         rt_cert_sig_s_dv_hdl: FHT_INVALID_HANDLE,
         rt_tci_dv_hdl: FhtDataStore::rt_tci_data_store(),
         rt_svn_dv_hdl: FhtDataStore::rt_svn_data_store(),
+        ldevid_tbs_size: env.fht_data_store.ldevid_tbs_size,
+        fmcalias_tbs_size: env.fht_data_store.fmcalias_tbs_size,
+        ldevid_tbs_addr,
+        fmcalias_tbs_addr,
+        pcr_log_addr,
+        fuse_log_addr,
         ..Default::default()
     }
 }
diff --git a/rom/dev/src/flow/cold_reset/fmc_alias.rs b/rom/dev/src/flow/cold_reset/fmc_alias.rs
index 9e035cab..1caf94d1 100644
--- a/rom/dev/src/flow/cold_reset/fmc_alias.rs
+++ b/rom/dev/src/flow/cold_reset/fmc_alias.rs
@@ -249,6 +249,13 @@ impl FmcAliasLayer {
         Ok(info)
     }
 
+    /// Update the fuse log
+    ///
+    /// # Arguments
+    /// * `log_info` - Image Verification Log Info
+    ///
+    /// # Returns
+    /// * CaliptraResult
     fn update_fuse_log(log_info: &ImageVerificationLogInfo) -> CaliptraResult<()> {
         // Log VendorPubKeyIndex
         log_fuse_data(
@@ -496,7 +503,7 @@ impl FmcAliasLayer {
         env.data_vault.set_fmc_pub_key(pub_key);
 
         //  Copy TBS to DCCM.
-        copy_tbs(tbs.tbs(), TbsType::FmcaliasTbs)?;
+        copy_tbs(tbs.tbs(), TbsType::FmcaliasTbs, env)?;
 
         report_boot_status(FmcAliasCertSigGenerationComplete.into());
         Ok(())
diff --git a/rom/dev/src/flow/cold_reset/ldev_id.rs b/rom/dev/src/flow/cold_reset/ldev_id.rs
index d1ba1ce7..bd81449e 100644
--- a/rom/dev/src/flow/cold_reset/ldev_id.rs
+++ b/rom/dev/src/flow/cold_reset/ldev_id.rs
@@ -201,7 +201,7 @@ impl LocalDevIdLayer {
         env.data_vault.set_ldev_dice_pub_key(pub_key);
 
         //  Copy TBS to DCCM.
-        copy_tbs(tbs.tbs(), TbsType::LdevidTbs)?;
+        copy_tbs(tbs.tbs(), TbsType::LdevidTbs, env)?;
 
         report_boot_status(LDevIdCertSigGenerationComplete.into());
         Ok(())
diff --git a/rom/dev/src/flow/cold_reset/mod.rs b/rom/dev/src/flow/cold_reset/mod.rs
index 1d914efc..aca9dd09 100644
--- a/rom/dev/src/flow/cold_reset/mod.rs
+++ b/rom/dev/src/flow/cold_reset/mod.rs
@@ -38,6 +38,9 @@ pub const KEY_ID_FMC_PRIV_KEY: KeyId = KeyId::KeyId7;
 extern "C" {
     static mut LDEVID_TBS_ORG: u8;
     static mut FMCALIAS_TBS_ORG: u8;
+    static mut LDEVID_TBS_SIZE: u8;
+    static mut FMCALIAS_TBS_SIZE: u8;
+
 }
 
 pub enum TbsType {
@@ -73,16 +76,40 @@ impl ColdResetFlow {
     }
 }
 
-pub fn copy_tbs(tbs: &[u8], tbs_type: TbsType) -> CaliptraResult<()> {
+/// Copies the TBS to DCCM
+///
+/// # Arguments
+/// * `tbs` - TBS to copy
+/// * `tbs_type` - Type of TBS
+/// * `env` - ROM Environment
+///
+/// # Returns
+///     CaliptraResult
+pub fn copy_tbs(tbs: &[u8], tbs_type: TbsType, env: &mut RomEnv) -> CaliptraResult<()> {
     let dst = match tbs_type {
-        TbsType::LdevidTbs => unsafe {
-            let ptr = &mut LDEVID_TBS_ORG as *mut u8;
-            core::slice::from_raw_parts_mut(ptr, tbs.len())
-        },
-        TbsType::FmcaliasTbs => unsafe {
-            let ptr = &mut FMCALIAS_TBS_ORG as *mut u8;
-            core::slice::from_raw_parts_mut(ptr, tbs.len())
-        },
+        TbsType::LdevidTbs => {
+            env.fht_data_store.ldevid_tbs_size = tbs.len() as u16;
+            unsafe {
+                let tbs_max_size = &LDEVID_TBS_SIZE as *const u8 as usize;
+                if tbs.len() > tbs_max_size {
+                    return Err(CaliptraError::ROM_GLOBAL_UNSUPPORTED_LDEVID_TBS_SIZE);
+                }
+                let ptr = &mut LDEVID_TBS_ORG as *mut u8;
+                core::slice::from_raw_parts_mut(ptr, tbs.len())
+            }
+        }
+        TbsType::FmcaliasTbs => {
+            env.fht_data_store.fmcalias_tbs_size = tbs.len() as u16;
+            unsafe {
+                let tbs_max_size = &FMCALIAS_TBS_SIZE as *const u8 as usize;
+                if tbs.len() > tbs_max_size {
+                    return Err(CaliptraError::ROM_GLOBAL_UNSUPPORTED_FMCALIAS_TBS_SIZE);
+                }
+
+                let ptr = &mut FMCALIAS_TBS_ORG as *mut u8;
+                core::slice::from_raw_parts_mut(ptr, tbs.len())
+            }
+        }
     };
 
     dst[..tbs.len()].copy_from_slice(tbs);
diff --git a/rom/dev/src/fuse.rs b/rom/dev/src/fuse.rs
index b54ce10a..49968a09 100644
--- a/rom/dev/src/fuse.rs
+++ b/rom/dev/src/fuse.rs
@@ -48,7 +48,10 @@ pub fn log_fuse_data(entry_id: FuseLogEntryId, data: &[u8]) -> CaliptraResult<()
     };
     log_entry.log_data.as_bytes_mut()[..data.len()].copy_from_slice(data);
 
+    // Get a pointer to the FUSE log. This is a static array of FUSE log entries.
     let dst = unsafe { &mut FUSE_LOG_ORG[..] };
+
+    // Store the log entry.
     dst[entry_id as usize - 1] = log_entry;
 
     Ok(())
diff --git a/rom/dev/src/pcr.rs b/rom/dev/src/pcr.rs
index 197228a6..eb369978 100644
--- a/rom/dev/src/pcr.rs
+++ b/rom/dev/src/pcr.rs
@@ -25,10 +25,13 @@ use crate::verifier::RomImageVerificationEnv;
 use caliptra_common::{PcrLogEntry, PcrLogEntryId};
 use caliptra_drivers::{Array4x12, CaliptraError, CaliptraResult, PcrBank, PcrId, Sha384};
 use caliptra_image_verify::ImageVerificationInfo;
+use core::mem::size_of;
 use zerocopy::AsBytes;
 
+const PCR_LOG_SIZE: usize = 1024;
+
 extern "C" {
-    static mut PCR_LOG_ORG: u8;
+    static mut PCR_LOG_ORG: [PcrLogEntry; PCR_LOG_SIZE / size_of::<PcrLogEntry>()];
 }
 
 struct PcrExtender<'a> {
@@ -125,14 +128,11 @@ pub fn log_pcr(pcr_entry_id: PcrLogEntryId, pcr_id: PcrId, data: &[u8]) -> Calip
     };
     pcr_log_entry.pcr_data.as_bytes_mut()[..data.len()].copy_from_slice(data);
 
-    let dst = unsafe {
-        let offset = core::mem::size_of::<PcrLogEntry>() * (pcr_entry_id as usize - 1);
-        let ptr = (&mut PCR_LOG_ORG as *mut u8).add(offset);
-        core::slice::from_raw_parts_mut(ptr, core::mem::size_of::<PcrLogEntry>())
-    };
+    // Get a pointer to the PCR log. This is a static array of PCR log entries.
+    let dst = unsafe { &mut PCR_LOG_ORG[..] };
 
-    // Store log entry
-    dst.copy_from_slice(pcr_log_entry.as_bytes());
+    // Store the log entry.
+    dst[pcr_entry_id as usize - 1] = pcr_log_entry;
 
     Ok(())
 }
diff --git a/rom/dev/src/rom_env.rs b/rom/dev/src/rom_env.rs
index 638244c0..e0c837a5 100644
--- a/rom/dev/src/rom_env.rs
+++ b/rom/dev/src/rom_env.rs
@@ -15,6 +15,7 @@ Abstract:
 
 --*/
 
+use crate::fht::FhtDataStore;
 use caliptra_drivers::{
     DataVault, DeobfuscationEngine, Ecc384, Hmac384, KeyVault, Lms, Mailbox, PcrBank, Sha1, Sha256,
     Sha384, Sha384Acc, SocIfc,
@@ -68,6 +69,9 @@ pub struct RomEnv {
 
     /// PCR Bank
     pub pcr_bank: PcrBank,
+
+    /// FHT Data Store
+    pub fht_data_store: FhtDataStore,
 }
 
 impl RomEnv {
@@ -91,6 +95,7 @@ impl RomEnv {
             soc_ifc: SocIfc::new(SocIfcReg::new()),
             mbox: Mailbox::new(MboxCsr::new()),
             pcr_bank: PcrBank::new(PvReg::new()),
+            fht_data_store: FhtDataStore::default(),
         }
     }
 }


Test patch:
diff --git a/rom/dev/tests/test_fmcalias_derivation.rs b/rom/dev/tests/test_fmcalias_derivation.rs
index a4efbe02..5535b235 100644
--- a/rom/dev/tests/test_fmcalias_derivation.rs
+++ b/rom/dev/tests/test_fmcalias_derivation.rs
@@ -1,7 +1,7 @@
 // Licensed under the Apache-2.0 license
 
 use caliptra_builder::{FwId, ImageOptions, APP_WITH_UART, ROM_WITH_UART};
-use caliptra_common::{FuseLogEntry, FuseLogEntryId};
+use caliptra_common::{FirmwareHandoffTable, FuseLogEntry, FuseLogEntryId};
 use caliptra_common::{PcrLogEntry, PcrLogEntryId};
 use caliptra_hw_model::{BootParams, Fuses, HwModel, InitParams, ModelError, SecurityState};
 use caliptra_image_fake_keys::VENDOR_CONFIG_KEY_1;
@@ -328,3 +328,49 @@ fn test_fuse_log() {
     assert_eq!(fuse_log_entry.entry_id, FuseLogEntryId::FuseRtSvn as u32);
     assert_eq!(fuse_log_entry.log_data[0], FMC_SVN);
 }
+
+#[test]
+fn test_fht_info() {
+    pub const TEST_FMC_WITH_UART: FwId = FwId {
+        crate_name: "caliptra-rom-test-fmc",
+        bin_name: "caliptra-rom-test-fmc",
+        features: &["emu"],
+    };
+    let rom = caliptra_builder::build_firmware_rom(&ROM_WITH_UART).unwrap();
+    let mut hw = caliptra_hw_model::new(BootParams {
+        init_params: InitParams {
+            rom: &rom,
+            ..Default::default()
+        },
+        fuses: Fuses::default(),
+        fw_image: None,
+    })
+    .unwrap();
+
+    let image_bundle = caliptra_builder::build_and_sign_image(
+        &TEST_FMC_WITH_UART,
+        &APP_WITH_UART,
+        ImageOptions::default(),
+    )
+    .unwrap();
+    assert!(hw
+        .upload_firmware(&image_bundle.to_bytes().unwrap())
+        .is_ok());
+
+    hw.step_until_output_contains("[exit] Launching FMC")
+        .unwrap();
+
+    let result = hw.mailbox_execute(0x1000_0003, &[]);
+    assert!(result.is_ok());
+
+    let data = result.unwrap().unwrap();
+    let fht = FirmwareHandoffTable::read_from_prefix(data.as_bytes()).unwrap();
+    assert_eq!(fht.ldevid_tbs_size, 530);
+    assert_eq!(fht.fmcalias_tbs_size, 742);
+    assert_eq!(fht.ldevid_tbs_addr, 0x50003000);
+    assert_eq!(fht.fmcalias_tbs_addr, 0x50003400);
+    assert_eq!(fht.pcr_log_addr, 0x50003800);
+    assert_eq!(fht.fuse_log_addr, 0x50003C00);
+
+    // [TODO] Expand test to validate additional FHT fields.
+}
diff --git a/rom/dev/tools/test-fmc/src/main.rs b/rom/dev/tools/test-fmc/src/main.rs
index 621bab5f..4e644ccc 100644
--- a/rom/dev/tools/test-fmc/src/main.rs
+++ b/rom/dev/tools/test-fmc/src/main.rs
@@ -19,6 +19,7 @@ extern "C" {
     static mut FMCALIAS_TBS_ORG: u8;
     static mut PCR_LOG_ORG: u8;
     static mut FUSE_LOG_ORG: u8;
+    static mut FHT_ORG: u8;
 }
 
 use caliptra_common::FirmwareHandoffTable;
@@ -49,10 +50,6 @@ Running Caliptra FMC ...
 pub extern "C" fn fmc_entry() -> ! {
     cprintln!("{}", BANNER);
 
-    extern "C" {
-        static mut FHT_ORG: u8;
-    }
-
     let slice = unsafe {
         let ptr = &mut FHT_ORG as *mut u8;
         cprintln!("[fmc] Loading FHT from 0x{:08X}", ptr as u32);
@@ -216,10 +213,12 @@ fn process_mailbox_commands() {
         0x1000_0001 => {
             // TODO: Generate certs
         }
-
         0x1000_0002 => {
             read_fuse_log(&mbox);
         }
+        0x1000_0003 => {
+            read_fht(&mbox);
+        }
         _ => {}
     }
 }
@@ -233,24 +232,7 @@ fn read_pcr_log(mbox: &caliptra_registers::mbox::RegisterBlock<RealMmioMut>) {
         }
 
         pcr_entry_count += 1;
-        let pcr_entry_bytes = pcr_entry.as_bytes();
-        let word_size = core::mem::size_of::<u32>();
-        let remainder = pcr_entry_bytes.len() % word_size;
-        let n = pcr_entry_bytes.len() - remainder;
-
-        for idx in (0..n).step_by(word_size) {
-            mbox.datain().write(|_| {
-                u32::from_le_bytes(pcr_entry_bytes[idx..idx + word_size].try_into().unwrap())
-            });
-        }
-
-        if remainder > 0 {
-            let mut last_word = pcr_entry_bytes[n] as u32;
-            for idx in 1..remainder {
-                last_word |= (pcr_entry_bytes[n + idx] as u32) << (idx << 3);
-            }
-            mbox.datain().write(|_| last_word);
-        }
+        send_to_mailbox(mbox, pcr_entry.as_bytes(), false);
     }
 
     mbox.dlen().write(|_| {
@@ -270,24 +252,7 @@ fn read_fuse_log(mbox: &caliptra_registers::mbox::RegisterBlock<RealMmioMut>) {
         }
 
         fuse_entry_count += 1;
-        let fuse_entry_bytes = fuse_entry.as_bytes();
-        let word_size = core::mem::size_of::<u32>();
-        let remainder = fuse_entry_bytes.len() % word_size;
-        let n = fuse_entry_bytes.len() - remainder;
-
-        for idx in (0..n).step_by(word_size) {
-            mbox.datain().write(|_| {
-                u32::from_le_bytes(fuse_entry_bytes[idx..idx + word_size].try_into().unwrap())
-            });
-        }
-
-        if remainder > 0 {
-            let mut last_word = fuse_entry_bytes[n] as u32;
-            for idx in 1..remainder {
-                last_word |= (fuse_entry_bytes[n + idx] as u32) << (idx << 3);
-            }
-            mbox.datain().write(|_| last_word);
-        }
+        send_to_mailbox(mbox, fuse_entry.as_bytes(), false);
     }
 
     mbox.dlen().write(|_| {
@@ -312,3 +277,46 @@ fn get_fuse_entry(entry_index: usize) -> FuseLogEntry {
     fuse_entry.copy_from_slice(src);
     FuseLogEntry::read_from_prefix(fuse_entry.as_bytes()).unwrap()
 }
+
+fn read_fht(mbox: &caliptra_registers::mbox::RegisterBlock<RealMmioMut>) {
+    // Copy the FHT from DCCM
+    let mut fht: [u8; core::mem::size_of::<FirmwareHandoffTable>()] =
+        [0u8; core::mem::size_of::<FirmwareHandoffTable>()];
+
+    let src = unsafe {
+        let ptr = &mut FHT_ORG as *mut u8;
+        core::slice::from_raw_parts_mut(ptr, core::mem::size_of::<FirmwareHandoffTable>())
+    };
+
+    fht.copy_from_slice(src);
+
+    send_to_mailbox(mbox, fht.as_bytes(), true);
+}
+
+fn send_to_mailbox(
+    mbox: &caliptra_registers::mbox::RegisterBlock<RealMmioMut>,
+    data: &[u8],
+    update_mb_state: bool,
+) {
+    let data_len = data.len();
+    let word_size = core::mem::size_of::<u32>();
+    let remainder = data_len % word_size;
+    let n = data_len - remainder;
+    for idx in (0..n).step_by(word_size) {
+        mbox.datain()
+            .write(|_| u32::from_le_bytes(data[idx..idx + word_size].try_into().unwrap()));
+    }
+
+    if remainder > 0 {
+        let mut last_word = data[n] as u32;
+        for idx in 1..remainder {
+            last_word |= (data[n + idx] as u32) << (idx << 3);
+        }
+        mbox.datain().write(|_| last_word);
+    }
+
+    if update_mb_state {
+        mbox.dlen().write(|_| data_len as u32);
+        mbox.status().write(|w| w.status(|w| w.data_ready()));
+    }
+}