Skip to main content

islet_rmm/rmi/rec/
params.rs

1use super::mpidr;
2use crate::const_assert_eq;
3use crate::granule::{GranuleState, GRANULE_SIZE};
4use crate::measurement::Hashable;
5use crate::rmi;
6use crate::rmi::error::Error;
7use crate::{get_granule, get_granule_if};
8
9use autopadding::*;
10
11pub const NR_AUX: usize = 16;
12pub const NR_GPRS: usize = 8;
13
14pad_struct_and_impl_default!(
15pub struct Params {
16    0x0    pub flags: u64,
17    0x100  pub mpidr: u64,
18    0x200  pub pc: u64,
19    0x300  pub gprs: [u64; NR_GPRS],
20    0x800  pub num_aux: u64,
21    0x808  pub aux: [u64; NR_AUX],
22    0x1000 => @END,
23}
24);
25const_assert_eq!(core::mem::size_of::<Params>(), GRANULE_SIZE);
26
27impl Params {
28    pub fn verify_compliance(&self, rec: usize, rd: usize, params_ptr: usize) -> Result<(), Error> {
29        // Currently, we use rmi::MAX_REC_AUX_GRANULES for RecAuxCount(rd)
30        if !mpidr::validate(self.mpidr) || self.num_aux as usize != rmi::MAX_REC_AUX_GRANULES {
31            return Err(Error::RmiErrorInput);
32        }
33
34        let mut aux = self.aux;
35        aux.sort();
36        for idx in 0..self.num_aux as usize {
37            let addr = aux[idx] as usize;
38            if addr == rec || addr == rd || addr == params_ptr {
39                return Err(Error::RmiErrorInput);
40            }
41
42            if idx != 0 && aux[idx - 1] == aux[idx] {
43                return Err(Error::RmiErrorInput);
44            }
45
46            let _aux_granule = get_granule_if!(addr, GranuleState::Delegated)?;
47        }
48
49        Ok(())
50    }
51}
52
53impl core::fmt::Debug for Params {
54    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
55        f.debug_struct("Params")
56            .field("flags", &format_args!("{:#X}", &self.flags))
57            .field("mpidr", &format_args!("{:#X}", &self.mpidr))
58            .field("pc", &format_args!("{:#X}", &self.pc))
59            .field("gprs", &format_args!("{:#X?}", self.gprs))
60            .field("num_aux", &self.num_aux)
61            .field("aux", &self.aux)
62            .finish()
63    }
64}
65
66impl safe_abstraction::raw_ptr::RawPtr for Params {}
67
68impl safe_abstraction::raw_ptr::SafetyChecked for Params {}
69
70impl safe_abstraction::raw_ptr::SafetyAssured for Params {
71    fn is_initialized(&self) -> bool {
72        // Given the fact that this memory is initialized by the Host,
73        // it's not possible to unequivocally guarantee
74        // that the values have been initialized from the perspective of the RMM.
75        // However, any values, whether correctly initialized or not, will undergo
76        // verification during the Measurement phase.
77        // Consequently, this function returns `true`.
78        true
79    }
80
81    fn verify_ownership(&self) -> bool {
82        // This memory has permissions from the Host's perspective,
83        // which inherently implies that exclusive ownership cannot be guaranteed by the RMM alone.
84        // However, since the RMM only performs read operations and any incorrect values will be
85        // verified during the Measurement phase.
86        // Consequently, this function returns `true`.
87        true
88    }
89}
90
91impl Hashable for Params {
92    fn hash(
93        &self,
94        hasher: &crate::measurement::Hasher,
95        out: &mut [u8],
96    ) -> Result<(), crate::measurement::MeasurementError> {
97        hasher.hash_fields_into(out, |h| {
98            h.hash_u64(self.flags);
99            h.hash(self._padflags);
100            h.hash_u64(0); // mpidr not used
101            h.hash(self._padmpidr);
102            h.hash_u64(self.pc);
103            h.hash(self._padpc);
104            h.hash_u64_array(self.gprs.as_slice());
105            h.hash(self._padgprs);
106            h.hash_u64(0); // num_aux not used
107            h.hash_u64_array([0u64; 16].as_slice()); // aux is not used
108            h.hash(self._padaux);
109        })
110    }
111}