blob: deebc474344a1f21729877371c8a30c4a5c62806 [file] [log] [blame]
Balint Dobszay5bf492f2024-07-29 17:21:32 +02001// SPDX-FileCopyrightText: Copyright 2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
2// SPDX-License-Identifier: MIT OR Apache-2.0
3
Balint Dobszaya5846852025-02-26 15:38:53 +01004//! Implementation of FF-A partition discovery data structures.
5
Balint Dobszay2338bd32024-12-19 19:00:14 +01006use thiserror::Error;
Balint Dobszay5bf492f2024-07-29 17:21:32 +02007use uuid::Uuid;
Imre Kis92b663e2025-04-10 14:15:05 +02008use zerocopy::{transmute, FromBytes, IntoBytes};
Balint Dobszay5bf492f2024-07-29 17:21:32 +02009
Balint Dobszayde0dc802025-02-28 14:16:52 +010010// This module uses FF-A v1.1 types by default.
11// FF-A v1.2 specified some previously reserved bits in the partition info properties field, but
12// this doesn't change the descriptor format.
Imre Kis61c34092025-04-10 14:14:38 +020013use crate::{ffa_v1_1::partition_info_descriptor, PartitionInfoGetFlags, SuccessArgs, Version};
Balint Dobszayde0dc802025-02-28 14:16:52 +010014
15// Sanity check to catch if the descriptor format is changed.
16const _: () = assert!(
17 size_of::<crate::ffa_v1_1::partition_info_descriptor>()
18 == size_of::<crate::ffa_v1_2::partition_info_descriptor>()
19);
20
Balint Dobszaya5846852025-02-26 15:38:53 +010021/// Rich error types returned by this module. Should be converted to [`crate::FfaError`] when used
22/// with the `FFA_ERROR` interface.
Balint Dobszay2338bd32024-12-19 19:00:14 +010023#[derive(Debug, Error)]
24pub enum Error {
25 #[error("Invalid buffer size")]
26 InvalidBufferSize,
27 #[error("Malformed descriptor")]
28 MalformedDescriptor,
29}
30
31impl From<Error> for crate::FfaError {
32 fn from(_value: Error) -> Self {
33 Self::InvalidParameters
34 }
35}
36
Balint Dobszaya5846852025-02-26 15:38:53 +010037/// Type of partition identified by the partition ID.
Balint Dobszay2338bd32024-12-19 19:00:14 +010038#[derive(Clone, Copy, Debug, PartialEq, Eq)]
Balint Dobszay5bf492f2024-07-29 17:21:32 +020039pub enum PartitionIdType {
Balint Dobszaya5846852025-02-26 15:38:53 +010040 /// Partition ID is a PE endpoint ID. Contains the number of execution contexts implemented by
41 /// this partition.
Balint Dobszay2338bd32024-12-19 19:00:14 +010042 PeEndpoint { execution_ctx_count: u16 },
Balint Dobszaya5846852025-02-26 15:38:53 +010043 /// Partition ID is a SEPID for an independent peripheral device.
Balint Dobszay5bf492f2024-07-29 17:21:32 +020044 SepidIndep,
Balint Dobszaya5846852025-02-26 15:38:53 +010045 /// Partition ID is a SEPID for an dependent peripheral device. Contains the ID of the proxy
46 /// endpoint for a dependent peripheral device.
Balint Dobszay2338bd32024-12-19 19:00:14 +010047 SepidDep { proxy_endpoint_id: u16 },
Balint Dobszaya5846852025-02-26 15:38:53 +010048 /// Partition ID is an auxiliary ID.
Balint Dobszay5bf492f2024-07-29 17:21:32 +020049 Aux,
50}
51
Balint Dobszay2338bd32024-12-19 19:00:14 +010052impl PartitionIdType {
53 const SHIFT: usize = 4;
54 const MASK: u32 = 0b11;
55 const PE_ENDPOINT: u32 = 0b00;
56 const SEPID_INDEP: u32 = 0b01;
57 const SEPID_DEP: u32 = 0b10;
58 const AUX: u32 = 0b11;
59}
60
Balint Dobszaya5846852025-02-26 15:38:53 +010061/// Properties of a partition.
Balint Dobszay2338bd32024-12-19 19:00:14 +010062#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
63pub struct PartitionProperties {
Balint Dobszaya5846852025-02-26 15:38:53 +010064 /// The partition supports receipt of direct requests.
Balint Dobszay5bf492f2024-07-29 17:21:32 +020065 pub support_direct_req_rec: bool,
Balint Dobszaya5846852025-02-26 15:38:53 +010066 /// The partition can send direct requests.
Balint Dobszay5bf492f2024-07-29 17:21:32 +020067 pub support_direct_req_send: bool,
Balint Dobszayde0dc802025-02-28 14:16:52 +010068 /// The partition supports receipt of direct requests via the FFA_MSG_SEND_DIRECT_REQ2 ABI.
69 /// Added in FF-A v1.2
70 pub support_direct_req2_rec: Option<bool>,
71 /// The partition can send direct requests via the FFA_MSG_SEND_DIRECT_REQ2 ABI.
72 /// Added in FF-A v1.2
73 pub support_direct_req2_send: Option<bool>,
Balint Dobszaya5846852025-02-26 15:38:53 +010074 /// The partition can send and receive indirect messages.
Balint Dobszay5bf492f2024-07-29 17:21:32 +020075 pub support_indirect_msg: bool,
Balint Dobszaya5846852025-02-26 15:38:53 +010076 /// The partition supports receipt of notifications.
Balint Dobszay5bf492f2024-07-29 17:21:32 +020077 pub support_notif_rec: bool,
Balint Dobszaya5846852025-02-26 15:38:53 +010078 /// The partition must be informed about each VM that is created by the Hypervisor.
Balint Dobszay5bf492f2024-07-29 17:21:32 +020079 pub subscribe_vm_created: bool,
Balint Dobszaya5846852025-02-26 15:38:53 +010080 /// The partition must be informed about each VM that is destroyed by the Hypervisor.
Balint Dobszay5bf492f2024-07-29 17:21:32 +020081 pub subscribe_vm_destroyed: bool,
Balint Dobszaya5846852025-02-26 15:38:53 +010082 /// The partition runs in the AArch64 execution state.
Balint Dobszay5bf492f2024-07-29 17:21:32 +020083 pub is_aarch64: bool,
84}
85
Balint Dobszay2338bd32024-12-19 19:00:14 +010086impl PartitionProperties {
87 const SUPPORT_DIRECT_REQ_REC_SHIFT: usize = 0;
88 const SUPPORT_DIRECT_REQ_SEND_SHIFT: usize = 1;
89 const SUPPORT_INDIRECT_MSG_SHIFT: usize = 2;
90 const SUPPORT_NOTIF_REC_SHIFT: usize = 3;
91 const SUBSCRIBE_VM_CREATED_SHIFT: usize = 6;
92 const SUBSCRIBE_VM_DESTROYED_SHIFT: usize = 7;
93 const IS_AARCH64_SHIFT: usize = 8;
Balint Dobszayde0dc802025-02-28 14:16:52 +010094 const SUPPORT_DIRECT_REQ2_REC_SHIFT: usize = 9;
95 const SUPPORT_DIRECT_REQ2_SEND_SHIFT: usize = 10;
Balint Dobszay5bf492f2024-07-29 17:21:32 +020096}
97
Balint Dobszayde0dc802025-02-28 14:16:52 +010098fn create_partition_properties(
99 version: Version,
100 id_type: PartitionIdType,
101 properties: PartitionProperties,
102) -> (u32, u16) {
103 let exec_ctx_count_or_proxy_id = match id_type {
104 PartitionIdType::PeEndpoint {
105 execution_ctx_count,
106 } => execution_ctx_count,
107 PartitionIdType::SepidIndep => 0,
108 PartitionIdType::SepidDep { proxy_endpoint_id } => proxy_endpoint_id,
109 PartitionIdType::Aux => 0,
110 };
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200111
Balint Dobszayde0dc802025-02-28 14:16:52 +0100112 let mut prop_bits = match id_type {
113 PartitionIdType::PeEndpoint { .. } => {
114 let mut p = PartitionIdType::PE_ENDPOINT << PartitionIdType::SHIFT;
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200115
Balint Dobszayde0dc802025-02-28 14:16:52 +0100116 if properties.support_direct_req_rec {
117 p |= 1 << PartitionProperties::SUPPORT_DIRECT_REQ_REC_SHIFT;
118 if properties.subscribe_vm_created {
119 // TODO: how to handle if ABI is invoked at NS phys instance?
120 p |= 1 << PartitionProperties::SUBSCRIBE_VM_CREATED_SHIFT
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200121 }
Balint Dobszayde0dc802025-02-28 14:16:52 +0100122 if properties.subscribe_vm_destroyed {
123 // TODO: how to handle if ABI is invoked at NS phys instance?
124 p |= 1 << PartitionProperties::SUBSCRIBE_VM_DESTROYED_SHIFT
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200125 }
Balint Dobszay2338bd32024-12-19 19:00:14 +0100126 }
Balint Dobszay2338bd32024-12-19 19:00:14 +0100127
Balint Dobszayde0dc802025-02-28 14:16:52 +0100128 if properties.support_direct_req_send {
129 p |= 1 << PartitionProperties::SUPPORT_DIRECT_REQ_SEND_SHIFT
130 }
131
132 // For v1.2 and later it's mandatory to specify these properties
133 if version >= Version(1, 2) {
134 if properties.support_direct_req2_rec.unwrap() {
135 p |= 1 << PartitionProperties::SUPPORT_DIRECT_REQ2_REC_SHIFT
136 }
137
138 if properties.support_direct_req2_send.unwrap() {
139 p |= 1 << PartitionProperties::SUPPORT_DIRECT_REQ2_SEND_SHIFT
140 }
141 }
142
143 if properties.support_indirect_msg {
144 p |= 1 << PartitionProperties::SUPPORT_INDIRECT_MSG_SHIFT
145 }
146
147 if properties.support_notif_rec {
148 p |= 1 << PartitionProperties::SUPPORT_NOTIF_REC_SHIFT
149 }
150
151 p
Balint Dobszay2338bd32024-12-19 19:00:14 +0100152 }
Balint Dobszayde0dc802025-02-28 14:16:52 +0100153 PartitionIdType::SepidIndep => PartitionIdType::SEPID_INDEP << PartitionIdType::SHIFT,
154 PartitionIdType::SepidDep { .. } => PartitionIdType::SEPID_DEP << PartitionIdType::SHIFT,
155 PartitionIdType::Aux => PartitionIdType::AUX << PartitionIdType::SHIFT,
156 };
Balint Dobszay2338bd32024-12-19 19:00:14 +0100157
Balint Dobszayde0dc802025-02-28 14:16:52 +0100158 if properties.is_aarch64 {
159 prop_bits |= 1 << PartitionProperties::IS_AARCH64_SHIFT
Balint Dobszay2338bd32024-12-19 19:00:14 +0100160 }
Balint Dobszayde0dc802025-02-28 14:16:52 +0100161
162 (prop_bits, exec_ctx_count_or_proxy_id)
Balint Dobszay2338bd32024-12-19 19:00:14 +0100163}
164
Balint Dobszayde0dc802025-02-28 14:16:52 +0100165fn parse_partition_properties(
166 version: Version,
167 prop_bits: u32,
168 id_type: u16,
169) -> (PartitionIdType, PartitionProperties) {
170 let part_id_type = match (prop_bits >> PartitionIdType::SHIFT) & PartitionIdType::MASK {
171 PartitionIdType::PE_ENDPOINT => PartitionIdType::PeEndpoint {
172 execution_ctx_count: id_type,
173 },
174 PartitionIdType::SEPID_INDEP => PartitionIdType::SepidIndep,
175 PartitionIdType::SEPID_DEP => PartitionIdType::SepidDep {
176 proxy_endpoint_id: id_type,
177 },
178 PartitionIdType::AUX => PartitionIdType::Aux,
179 _ => panic!(), // The match is exhaustive for a 2-bit value
180 };
Balint Dobszay2338bd32024-12-19 19:00:14 +0100181
Balint Dobszayde0dc802025-02-28 14:16:52 +0100182 let mut part_props = PartitionProperties::default();
Balint Dobszay2338bd32024-12-19 19:00:14 +0100183
Balint Dobszayde0dc802025-02-28 14:16:52 +0100184 if matches!(part_id_type, PartitionIdType::PeEndpoint { .. }) {
185 if (prop_bits >> PartitionProperties::SUPPORT_DIRECT_REQ_REC_SHIFT) & 0b1 == 1 {
186 part_props.support_direct_req_rec = true;
Balint Dobszay2338bd32024-12-19 19:00:14 +0100187
Balint Dobszayde0dc802025-02-28 14:16:52 +0100188 if (prop_bits >> PartitionProperties::SUBSCRIBE_VM_CREATED_SHIFT) & 0b1 == 1 {
189 part_props.subscribe_vm_created = true;
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200190 }
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200191
Balint Dobszayde0dc802025-02-28 14:16:52 +0100192 if (prop_bits >> PartitionProperties::SUBSCRIBE_VM_DESTROYED_SHIFT) & 0b1 == 1 {
193 part_props.subscribe_vm_destroyed = true;
Balint Dobszay2338bd32024-12-19 19:00:14 +0100194 }
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200195 }
196
Balint Dobszayde0dc802025-02-28 14:16:52 +0100197 if (prop_bits >> PartitionProperties::SUPPORT_DIRECT_REQ_SEND_SHIFT) & 0b1 == 1 {
198 part_props.support_direct_req_send = true;
Balint Dobszay2338bd32024-12-19 19:00:14 +0100199 }
200
Balint Dobszayde0dc802025-02-28 14:16:52 +0100201 if version >= Version(1, 2) {
202 part_props.support_direct_req2_rec =
203 Some((prop_bits >> PartitionProperties::SUPPORT_DIRECT_REQ2_REC_SHIFT) & 0b1 == 1);
204 part_props.support_direct_req2_send =
205 Some((prop_bits >> PartitionProperties::SUPPORT_DIRECT_REQ2_SEND_SHIFT) & 0b1 == 1);
206 }
207
208 if (prop_bits >> PartitionProperties::SUPPORT_INDIRECT_MSG_SHIFT) & 0b1 == 1 {
209 part_props.support_indirect_msg = true;
210 }
211
212 if (prop_bits >> PartitionProperties::SUPPORT_NOTIF_REC_SHIFT) & 0b1 == 1 {
213 part_props.support_notif_rec = true;
214 }
Balint Dobszay2338bd32024-12-19 19:00:14 +0100215 }
Balint Dobszayde0dc802025-02-28 14:16:52 +0100216
217 if (prop_bits >> PartitionProperties::IS_AARCH64_SHIFT) & 0b1 == 1 {
218 part_props.is_aarch64 = true;
219 }
220
221 (part_id_type, part_props)
Balint Dobszay2338bd32024-12-19 19:00:14 +0100222}
223
Balint Dobszaya5846852025-02-26 15:38:53 +0100224/// Partition information descriptor, returned by the `FFA_PARTITION_INFO_GET` interface.
Balint Dobszay2338bd32024-12-19 19:00:14 +0100225#[derive(Clone, Copy, Debug, PartialEq, Eq)]
226pub struct PartitionInfo {
227 pub uuid: Uuid,
228 pub partition_id: u16,
229 pub partition_id_type: PartitionIdType,
230 pub props: PartitionProperties,
231}
232
233impl PartitionInfo {
Balint Dobszayde0dc802025-02-28 14:16:52 +0100234 pub const DESC_SIZE: usize = size_of::<partition_info_descriptor>();
Balint Dobszay2338bd32024-12-19 19:00:14 +0100235
Balint Dobszaya5846852025-02-26 15:38:53 +0100236 /// Serialize a list of partition information descriptors into a buffer. The `fill_uuid`
237 /// parameter controls whether the UUID field of the descriptor will be filled.
Balint Dobszayde0dc802025-02-28 14:16:52 +0100238 pub fn pack(version: Version, descriptors: &[PartitionInfo], buf: &mut [u8], fill_uuid: bool) {
239 assert!((Version(1, 1)..=Version(1, 2)).contains(&version));
240
Balint Dobszay2338bd32024-12-19 19:00:14 +0100241 let mut offset = 0;
242
243 for desc in descriptors {
244 let mut desc_raw = partition_info_descriptor {
245 partition_id: desc.partition_id,
246 ..Default::default()
247 };
248
249 (
250 desc_raw.partition_props,
251 desc_raw.exec_ctx_count_or_proxy_id,
Balint Dobszayde0dc802025-02-28 14:16:52 +0100252 ) = create_partition_properties(version, desc.partition_id_type, desc.props);
Balint Dobszay2338bd32024-12-19 19:00:14 +0100253
254 if fill_uuid {
255 desc_raw.uuid.copy_from_slice(desc.uuid.as_bytes());
256 }
257
258 desc_raw.write_to_prefix(&mut buf[offset..]).unwrap();
259 offset += Self::DESC_SIZE;
260 }
261 }
262}
263
Imre Kis61c34092025-04-10 14:14:38 +0200264/// `FFA_PARTITION_INFO_GET` specific success args structure.
265#[derive(Debug, Eq, PartialEq, Clone, Copy)]
266pub struct SuccessArgsPartitionInfoGet {
267 pub count: u32,
268 pub size: Option<u32>,
269}
270
271impl From<SuccessArgsPartitionInfoGet> for SuccessArgs {
272 fn from(value: SuccessArgsPartitionInfoGet) -> Self {
273 SuccessArgs::Args32([value.count, value.size.unwrap_or(0), 0, 0, 0, 0])
274 }
275}
276
277impl TryFrom<(PartitionInfoGetFlags, SuccessArgs)> for SuccessArgsPartitionInfoGet {
278 type Error = crate::Error;
279
280 fn try_from(value: (PartitionInfoGetFlags, SuccessArgs)) -> Result<Self, Self::Error> {
281 let (flags, value) = value;
282 let args = value.try_get_args32()?;
283
284 let size = if !flags.count_only {
285 Some(args[1])
286 } else {
287 None
288 };
289
290 Ok(Self {
291 count: args[0],
292 size,
293 })
294 }
295}
296
Imre Kis92b663e2025-04-10 14:15:05 +0200297/// `FFA_PARTITION_INFO_GET_REGS` specific success args structure.
298#[derive(Debug, Eq, PartialEq, Clone, Copy)]
299pub struct SuccessArgsPartitionInfoGetRegs {
300 pub last_index: u16,
301 pub current_index: u16,
302 pub info_tag: u16,
303 pub descriptor_data: [u8; Self::DESCRIPTOR_REG_COUNT * 8],
304}
305
306impl SuccessArgsPartitionInfoGetRegs {
307 const DESCRIPTOR_REG_COUNT: usize = 15;
308 const LAST_INDEX_SHIFT: usize = 0;
309 const CURRENT_INDEX_SHIFT: usize = 16;
310 const INFO_TAG_SHIFT: usize = 32;
311 const SIZE_SHIFT: usize = 48;
312}
313
314impl From<SuccessArgsPartitionInfoGetRegs> for SuccessArgs {
315 fn from(value: SuccessArgsPartitionInfoGetRegs) -> Self {
316 let mut args = [0; 16];
317
Balint Dobszayb2e9bed2025-04-15 12:57:36 +0200318 args[0] = ((value.last_index as u64) << SuccessArgsPartitionInfoGetRegs::LAST_INDEX_SHIFT)
Imre Kis92b663e2025-04-10 14:15:05 +0200319 | ((value.current_index as u64)
320 << SuccessArgsPartitionInfoGetRegs::CURRENT_INDEX_SHIFT)
321 | ((value.info_tag as u64) << SuccessArgsPartitionInfoGetRegs::INFO_TAG_SHIFT)
322 | ((PartitionInfo::DESC_SIZE as u64) << SuccessArgsPartitionInfoGetRegs::SIZE_SHIFT);
323
324 let descriptor_regs: [u64; SuccessArgsPartitionInfoGetRegs::DESCRIPTOR_REG_COUNT] =
325 transmute!(value.descriptor_data);
326 args[1..].copy_from_slice(&descriptor_regs);
327
328 Self::Args64_2(args)
329 }
330}
331
332impl TryFrom<SuccessArgs> for SuccessArgsPartitionInfoGetRegs {
333 type Error = crate::Error;
334
335 fn try_from(value: SuccessArgs) -> Result<Self, Self::Error> {
336 let args = value.try_get_args64_2()?;
337
338 // Validate size
339 let size = (args[0] >> Self::SIZE_SHIFT) as u16;
340 if size as usize != PartitionInfo::DESC_SIZE {
341 return Err(Self::Error::InvalidPartitionInfoGetRegsResponse);
342 }
343
344 // Validate inidices
345 let last_index = (args[0] >> Self::LAST_INDEX_SHIFT) as u16;
346 let current_index = (args[0] >> Self::CURRENT_INDEX_SHIFT) as u16;
347 if last_index < current_index {
348 return Err(Self::Error::InvalidPartitionInfoGetRegsResponse);
349 }
350
351 let info_tag = (args[0] >> Self::INFO_TAG_SHIFT) as u16;
352
353 // Convert registers into byte array
354 let descriptor_regs: [u64; SuccessArgsPartitionInfoGetRegs::DESCRIPTOR_REG_COUNT] =
355 args[1..].try_into().unwrap();
356 let descriptor_data = transmute!(descriptor_regs);
357
358 Ok(Self {
359 last_index,
360 current_index,
361 info_tag,
362 descriptor_data,
363 })
364 }
365}
366
Balint Dobszaya5846852025-02-26 15:38:53 +0100367/// Iterator of partition information descriptors.
Balint Dobszay2338bd32024-12-19 19:00:14 +0100368pub struct PartitionInfoIterator<'a> {
Balint Dobszayde0dc802025-02-28 14:16:52 +0100369 version: Version,
Balint Dobszay2338bd32024-12-19 19:00:14 +0100370 buf: &'a [u8],
371 offset: usize,
372 count: usize,
373}
374
375impl<'a> PartitionInfoIterator<'a> {
Balint Dobszaya5846852025-02-26 15:38:53 +0100376 /// Create an iterator of partition information descriptors from a buffer.
Balint Dobszayde0dc802025-02-28 14:16:52 +0100377 pub fn new(version: Version, buf: &'a [u8], count: usize) -> Result<Self, Error> {
378 assert!((Version(1, 1)..=Version(1, 2)).contains(&version));
379
Balint Dobszay2338bd32024-12-19 19:00:14 +0100380 let Some(total_size) = count.checked_mul(PartitionInfo::DESC_SIZE) else {
381 return Err(Error::InvalidBufferSize);
382 };
383
384 if buf.len() < total_size {
385 return Err(Error::InvalidBufferSize);
386 }
387
388 Ok(Self {
Balint Dobszayde0dc802025-02-28 14:16:52 +0100389 version,
Balint Dobszay2338bd32024-12-19 19:00:14 +0100390 buf,
391 offset: 0,
392 count,
393 })
394 }
395}
396
397impl Iterator for PartitionInfoIterator<'_> {
398 type Item = Result<PartitionInfo, Error>;
399
400 fn next(&mut self) -> Option<Self::Item> {
401 if self.count > 0 {
402 let offset = self.offset;
403 self.offset += PartitionInfo::DESC_SIZE;
404 self.count -= 1;
405
406 let Ok(desc_raw) = partition_info_descriptor::ref_from_bytes(
407 &self.buf[offset..offset + PartitionInfo::DESC_SIZE],
408 ) else {
409 return Some(Err(Error::MalformedDescriptor));
410 };
411
412 let partition_id = desc_raw.partition_id;
413
Balint Dobszayde0dc802025-02-28 14:16:52 +0100414 let (partition_id_type, props) = parse_partition_properties(
415 self.version,
Balint Dobszay2338bd32024-12-19 19:00:14 +0100416 desc_raw.partition_props,
417 desc_raw.exec_ctx_count_or_proxy_id,
Balint Dobszayde0dc802025-02-28 14:16:52 +0100418 );
Balint Dobszay2338bd32024-12-19 19:00:14 +0100419
420 let uuid = Uuid::from_bytes(desc_raw.uuid);
421
422 let desc = PartitionInfo {
423 uuid,
424 partition_id,
Balint Dobszayde0dc802025-02-28 14:16:52 +0100425 partition_id_type,
426 props,
Balint Dobszay2338bd32024-12-19 19:00:14 +0100427 };
428
429 return Some(Ok(desc));
430 }
431
432 None
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200433 }
434}
435
436#[cfg(test)]
437mod tests {
438 use super::*;
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200439 use uuid::uuid;
440
Balint Dobszay2338bd32024-12-19 19:00:14 +0100441 // TODO: add tests with a known correct partition info blob
442
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200443 #[test]
444 fn part_info() {
Balint Dobszay2338bd32024-12-19 19:00:14 +0100445 let desc1 = PartitionInfo {
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200446 uuid: uuid!("12345678-1234-1234-1234-123456789abc"),
Balint Dobszay2338bd32024-12-19 19:00:14 +0100447 partition_id: 0x8001,
448 partition_id_type: PartitionIdType::PeEndpoint {
449 execution_ctx_count: 1,
450 },
451 props: PartitionProperties {
452 support_direct_req_rec: true,
453 support_direct_req_send: true,
454 support_indirect_msg: false,
455 support_notif_rec: false,
456 subscribe_vm_created: true,
457 subscribe_vm_destroyed: true,
458 is_aarch64: true,
Balint Dobszayde0dc802025-02-28 14:16:52 +0100459 support_direct_req2_rec: Some(true),
460 support_direct_req2_send: Some(true),
Balint Dobszay2338bd32024-12-19 19:00:14 +0100461 },
462 };
463
464 let desc2 = PartitionInfo {
465 uuid: uuid!("abcdef00-abcd-dcba-1234-abcdef012345"),
466 partition_id: 0x8002,
467 partition_id_type: PartitionIdType::SepidIndep,
468 props: PartitionProperties {
469 support_direct_req_rec: false,
470 support_direct_req_send: false,
471 support_indirect_msg: false,
472 support_notif_rec: false,
473 subscribe_vm_created: false,
474 subscribe_vm_destroyed: false,
475 is_aarch64: true,
Balint Dobszayde0dc802025-02-28 14:16:52 +0100476 support_direct_req2_rec: None,
477 support_direct_req2_send: None,
Balint Dobszay2338bd32024-12-19 19:00:14 +0100478 },
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200479 };
480
481 let mut buf = [0u8; 0xff];
Balint Dobszayde0dc802025-02-28 14:16:52 +0100482 PartitionInfo::pack(Version(1, 2), &[desc1, desc2], &mut buf, true);
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200483
Balint Dobszayde0dc802025-02-28 14:16:52 +0100484 let mut descriptors = PartitionInfoIterator::new(Version(1, 2), &buf, 2).unwrap();
Balint Dobszay2338bd32024-12-19 19:00:14 +0100485 let desc1_check = descriptors.next().unwrap().unwrap();
486 let desc2_check = descriptors.next().unwrap().unwrap();
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200487
Balint Dobszay2338bd32024-12-19 19:00:14 +0100488 assert_eq!(desc1, desc1_check);
489 assert_eq!(desc2, desc2_check);
Balint Dobszay5bf492f2024-07-29 17:21:32 +0200490 }
491}