1#![warn(missing_docs)]
7use bitflags::bitflags;
8use core::mem;
9use std::str::FromStr;
10
11use serde::ser::SerializeTuple;
12use serde::{Deserialize, Serialize, Serializer};
13
14pub const RMM_REALM_MEASUREMENT_WIDTH: usize = 64;
16pub type RmmRealmMeasurement = [u8; RMM_REALM_MEASUREMENT_WIDTH];
18
19bitflags! {
20#[derive(Default, Debug, Clone, Copy, Serialize, PartialEq, Eq, Hash)]
22pub struct RmiRealmFlags: u64 {
23 const LPA2 = 1 << 0;
25 const SVE = 1 << 1;
27 const PMU = 1 << 2;
29}
30}
31
32bitflags! {
33pub struct RmiRecCreateFlags: u64 {
35 const RUNNABLE = 1 << 0;
37}
38}
39
40bitflags! {
41pub struct RmmDataFlags: u64 {
43 const MEASURE = 1 << 0;
45}
46}
47
48pub const RMM_GRANULE: u64 = 0x1000;
50
51#[derive(Debug, thiserror::Error)]
53pub enum RmmError {
54 #[error("encoding error")]
56 EncodeError(#[from] bincode::Error),
57
58 #[error("unknown hash algorithm `{0}`")]
60 UnknownHashAlgorithm(String),
61}
62type Result<T> = core::result::Result<T, RmmError>;
63
64#[derive(Copy, Clone, Debug, Deserialize, PartialEq, Default)]
66pub enum RmiHashAlgorithm {
67 #[default]
69 RmiHashSha256 = 0,
70 RmiHashSha512 = 1,
72}
73
74impl TryFrom<u8> for RmiHashAlgorithm {
75 type Error = RmmError;
76 fn try_from(algo: u8) -> Result<Self> {
77 match algo {
78 0 => Ok(RmiHashAlgorithm::RmiHashSha256),
79 1 => Ok(RmiHashAlgorithm::RmiHashSha512),
80 _ => Err(RmmError::UnknownHashAlgorithm("{algo}".to_string())),
81 }
82 }
83}
84
85impl FromStr for RmiHashAlgorithm {
86 type Err = RmmError;
87 fn from_str(s: &str) -> Result<Self> {
88 match s {
89 "sha256" => Ok(RmiHashAlgorithm::RmiHashSha256),
90 "sha512" => Ok(RmiHashAlgorithm::RmiHashSha512),
91 _ => Err(RmmError::UnknownHashAlgorithm(String::from(s))),
92 }
93 }
94}
95
96fn serialize_array<S: Serializer, const N: usize>(
99 t: &[u8; N],
100 serializer: S,
101) -> core::result::Result<S::Ok, S::Error> {
102 let mut ser_tuple = serializer.serialize_tuple(N)?;
103 for e in t {
104 ser_tuple.serialize_element(e)?;
105 }
106 ser_tuple.end()
107}
108
109#[derive(Clone, Debug, Serialize, PartialEq, Default)]
113#[repr(C, packed)]
114pub struct RmiRealmParams {
115 flags: u64,
116 s2sz: u8,
117 _empty1: [u8; 7],
118 sve_vl: u8,
119 _empty2: [u8; 7],
120 num_bps: u8,
121 _empty3: [u8; 7],
122 num_wps: u8,
123 _empty4: [u8; 7],
124 pmu_num_ctrs: u8,
125 _empty5: [u8; 7],
126 hash_algo: u8,
127}
128const RMI_REALM_PARAMS_SIZE: usize = 0x1000;
129
130impl RmiRealmParams {
131 pub fn new(
133 flags: RmiRealmFlags,
134 s2sz: u8,
135 num_wps: u8,
136 num_bps: u8,
137 pmu_num_ctrs: u8,
138 sve_vl: u8,
139 hash_algo: RmiHashAlgorithm,
140 ) -> RmiRealmParams {
141 RmiRealmParams {
142 flags: flags.bits(),
143 s2sz,
144 num_wps,
145 num_bps,
146 pmu_num_ctrs,
147 sve_vl,
148 hash_algo: hash_algo as u8,
149 ..Default::default()
150 }
151 }
152 pub fn to_bytes(&self) -> Result<Vec<u8>> {
154 let mut bytes = bincode::serialize(self)?;
155 assert!(bytes.len() == mem::size_of::<RmiRealmParams>());
156 bytes.resize(RMI_REALM_PARAMS_SIZE, 0);
157 Ok(bytes)
158 }
159}
160
161#[derive(Clone, Debug, Serialize, PartialEq)]
164#[repr(C, packed)]
165pub struct RmiRecParams {
166 flags: u64,
167 #[serde(serialize_with = "serialize_array")]
168 _empty1: [u8; 0x200 - 8],
169 pc: u64,
170 #[serde(serialize_with = "serialize_array")]
171 _empty2: [u8; 0x100 - 8],
172 gprs: [u64; 8],
173}
174const RMI_REC_PARAMS_SIZE: usize = 0x1000;
175
176impl RmiRecParams {
177 pub fn new(flags: RmiRecCreateFlags, pc: u64, gprs: [u64; 8]) -> RmiRecParams {
179 RmiRecParams {
180 flags: flags.bits(),
181 _empty1: [0; 0x200 - 8],
183 pc,
184 _empty2: [0; 0x100 - 8],
185 gprs,
186 }
187 }
188
189 pub fn to_bytes(&self) -> Result<Vec<u8>> {
191 let mut bytes = bincode::serialize(self)?;
192 assert!(bytes.len() == mem::size_of::<RmiRecParams>());
193 bytes.resize(RMI_REC_PARAMS_SIZE, 0);
194 Ok(bytes)
195 }
196}
197
198#[derive(Clone, Debug, Serialize, PartialEq)]
200#[repr(C, packed)]
201pub struct RmmMeasurementDescriptorData {
202 desc_type: u8,
203 unused1: [u8; 7],
204 len: u64,
205 #[serde(serialize_with = "serialize_array")]
206 rim: RmmRealmMeasurement,
207 ipa: u64,
208 flags: u64,
209 #[serde(serialize_with = "serialize_array")]
210 content: RmmRealmMeasurement,
211}
212const RMM_REALM_MEASUREMENT_DESCRIPTOR_DATA_SIZE: usize = 0x100;
213
214impl RmmMeasurementDescriptorData {
215 pub fn new(
217 rim: &RmmRealmMeasurement,
218 ipa: u64,
219 flags: RmmDataFlags,
220 content: &RmmRealmMeasurement,
221 ) -> RmmMeasurementDescriptorData {
222 RmmMeasurementDescriptorData {
223 desc_type: 0,
224 unused1: [0; 7],
225 len: RMM_REALM_MEASUREMENT_DESCRIPTOR_DATA_SIZE as u64,
226 rim: *rim,
227 ipa,
228 flags: flags.bits(),
229 content: *content,
230 }
231 }
232 pub fn to_bytes(&self) -> Result<Vec<u8>> {
234 assert!(self.desc_type == 0);
235 let mut bytes = bincode::serialize(self)?;
236 assert!(bytes.len() == mem::size_of::<RmmMeasurementDescriptorData>());
237 bytes.resize(RMM_REALM_MEASUREMENT_DESCRIPTOR_DATA_SIZE, 0);
238 Ok(bytes)
239 }
240}
241
242#[derive(Clone, Debug, Serialize, PartialEq)]
244#[repr(C, packed)]
245pub struct RmmMeasurementDescriptorRec {
246 desc_type: u8,
247 unused1: [u8; 7],
248 len: u64,
249 #[serde(serialize_with = "serialize_array")]
250 rim: RmmRealmMeasurement,
251 #[serde(serialize_with = "serialize_array")]
252 content: RmmRealmMeasurement,
253}
254const RMM_REALM_MEASUREMENT_DESCRIPTOR_REC_SIZE: usize = 0x100;
255
256impl RmmMeasurementDescriptorRec {
257 pub fn new(
259 rim: &RmmRealmMeasurement,
260 content: &RmmRealmMeasurement,
261 ) -> RmmMeasurementDescriptorRec {
262 RmmMeasurementDescriptorRec {
263 desc_type: 1,
264 unused1: [0; 7],
265 len: RMM_REALM_MEASUREMENT_DESCRIPTOR_REC_SIZE as u64,
266 rim: *rim,
267 content: *content,
268 }
269 }
270 pub fn to_bytes(&self) -> Result<Vec<u8>> {
272 assert!(self.desc_type == 1);
273 let mut bytes = bincode::serialize(self)?;
274 assert!(bytes.len() == mem::size_of::<RmmMeasurementDescriptorRec>());
275 bytes.resize(RMM_REALM_MEASUREMENT_DESCRIPTOR_REC_SIZE, 0);
276 Ok(bytes)
277 }
278}
279
280#[derive(Clone, Debug, Serialize, PartialEq)]
282#[repr(C, packed)]
283pub struct RmmMeasurementDescriptorRipas {
284 desc_type: u8,
285 unused1: [u8; 7],
286 len: u64,
287 #[serde(serialize_with = "serialize_array")]
288 rim: RmmRealmMeasurement,
289 base: u64,
290 top: u64,
291}
292const RMM_REALM_MEASUREMENT_DESCRIPTOR_RIPAS_SIZE: usize = 0x100;
293
294impl RmmMeasurementDescriptorRipas {
295 pub fn new(
297 rim: &RmmRealmMeasurement,
298 base: u64,
299 top: u64,
300 ) -> RmmMeasurementDescriptorRipas {
301 RmmMeasurementDescriptorRipas {
302 desc_type: 2,
303 unused1: [0; 7],
304 len: RMM_REALM_MEASUREMENT_DESCRIPTOR_RIPAS_SIZE as u64,
305 rim: *rim,
306 base,
307 top,
308 }
309 }
310 pub fn to_bytes(&self) -> Result<Vec<u8>> {
312 assert!(self.desc_type == 2);
313 let mut bytes = bincode::serialize(self)?;
314 assert!(bytes.len() == mem::size_of::<RmmMeasurementDescriptorRipas>());
315 bytes.resize(RMM_REALM_MEASUREMENT_DESCRIPTOR_RIPAS_SIZE, 0);
316 Ok(bytes)
317 }
318}
319
320#[cfg(test)]
321mod tests {
322 use super::*;
323
324 #[test]
325 fn test_serialize() {
326 let a = 0x12345678u32.to_le();
327 let bytes = bincode::serialize(&a).unwrap();
328
329 assert!(bytes[0] == 0x78);
332 }
333
334 #[test]
335 fn test_hash_algo() {
336 assert_eq!(
337 RmiHashAlgorithm::try_from(0).unwrap(),
338 RmiHashAlgorithm::RmiHashSha256
339 );
340 assert_eq!(
341 RmiHashAlgorithm::try_from(1).unwrap(),
342 RmiHashAlgorithm::RmiHashSha512
343 );
344 assert!(RmiHashAlgorithm::try_from(2).is_err());
345 let h: RmiHashAlgorithm = "sha256".parse().unwrap();
346 assert_eq!(h, RmiHashAlgorithm::RmiHashSha256);
347 assert_eq!(
348 "sha256".parse::<RmiHashAlgorithm>().unwrap(),
349 RmiHashAlgorithm::RmiHashSha256
350 );
351 assert_eq!(
352 "sha512".parse::<RmiHashAlgorithm>().unwrap(),
353 RmiHashAlgorithm::RmiHashSha512
354 );
355 assert!("hello".parse::<RmiHashAlgorithm>().is_err());
356 }
357}