Balint Dobszay | 5bf492f | 2024-07-29 17:21:32 +0200 | [diff] [blame] | 1 | // 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 Dobszay | a584685 | 2025-02-26 15:38:53 +0100 | [diff] [blame] | 4 | //! Implementation of FF-A partition discovery data structures. |
| 5 | |
Balint Dobszay | 2338bd3 | 2024-12-19 19:00:14 +0100 | [diff] [blame] | 6 | use thiserror::Error; |
Balint Dobszay | 5bf492f | 2024-07-29 17:21:32 +0200 | [diff] [blame] | 7 | use uuid::Uuid; |
Imre Kis | 92b663e | 2025-04-10 14:15:05 +0200 | [diff] [blame] | 8 | use zerocopy::{transmute, FromBytes, IntoBytes}; |
Balint Dobszay | 5bf492f | 2024-07-29 17:21:32 +0200 | [diff] [blame] | 9 | |
Balint Dobszay | de0dc80 | 2025-02-28 14:16:52 +0100 | [diff] [blame] | 10 | // 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 Kis | 61c3409 | 2025-04-10 14:14:38 +0200 | [diff] [blame] | 13 | use crate::{ffa_v1_1::partition_info_descriptor, PartitionInfoGetFlags, SuccessArgs, Version}; |
Balint Dobszay | de0dc80 | 2025-02-28 14:16:52 +0100 | [diff] [blame] | 14 | |
| 15 | // Sanity check to catch if the descriptor format is changed. |
| 16 | const _: () = assert!( |
| 17 | size_of::<crate::ffa_v1_1::partition_info_descriptor>() |
| 18 | == size_of::<crate::ffa_v1_2::partition_info_descriptor>() |
| 19 | ); |
| 20 | |
Balint Dobszay | a584685 | 2025-02-26 15:38:53 +0100 | [diff] [blame] | 21 | /// Rich error types returned by this module. Should be converted to [`crate::FfaError`] when used |
| 22 | /// with the `FFA_ERROR` interface. |
Balint Dobszay | 2338bd3 | 2024-12-19 19:00:14 +0100 | [diff] [blame] | 23 | #[derive(Debug, Error)] |
| 24 | pub enum Error { |
| 25 | #[error("Invalid buffer size")] |
| 26 | InvalidBufferSize, |
| 27 | #[error("Malformed descriptor")] |
| 28 | MalformedDescriptor, |
| 29 | } |
| 30 | |
| 31 | impl From<Error> for crate::FfaError { |
| 32 | fn from(_value: Error) -> Self { |
| 33 | Self::InvalidParameters |
| 34 | } |
| 35 | } |
| 36 | |
Balint Dobszay | a584685 | 2025-02-26 15:38:53 +0100 | [diff] [blame] | 37 | /// Type of partition identified by the partition ID. |
Balint Dobszay | 2338bd3 | 2024-12-19 19:00:14 +0100 | [diff] [blame] | 38 | #[derive(Clone, Copy, Debug, PartialEq, Eq)] |
Balint Dobszay | 5bf492f | 2024-07-29 17:21:32 +0200 | [diff] [blame] | 39 | pub enum PartitionIdType { |
Balint Dobszay | a584685 | 2025-02-26 15:38:53 +0100 | [diff] [blame] | 40 | /// Partition ID is a PE endpoint ID. Contains the number of execution contexts implemented by |
| 41 | /// this partition. |
Balint Dobszay | 2338bd3 | 2024-12-19 19:00:14 +0100 | [diff] [blame] | 42 | PeEndpoint { execution_ctx_count: u16 }, |
Balint Dobszay | a584685 | 2025-02-26 15:38:53 +0100 | [diff] [blame] | 43 | /// Partition ID is a SEPID for an independent peripheral device. |
Balint Dobszay | 5bf492f | 2024-07-29 17:21:32 +0200 | [diff] [blame] | 44 | SepidIndep, |
Balint Dobszay | a584685 | 2025-02-26 15:38:53 +0100 | [diff] [blame] | 45 | /// Partition ID is a SEPID for an dependent peripheral device. Contains the ID of the proxy |
| 46 | /// endpoint for a dependent peripheral device. |
Balint Dobszay | 2338bd3 | 2024-12-19 19:00:14 +0100 | [diff] [blame] | 47 | SepidDep { proxy_endpoint_id: u16 }, |
Balint Dobszay | a584685 | 2025-02-26 15:38:53 +0100 | [diff] [blame] | 48 | /// Partition ID is an auxiliary ID. |
Balint Dobszay | 5bf492f | 2024-07-29 17:21:32 +0200 | [diff] [blame] | 49 | Aux, |
| 50 | } |
| 51 | |
Balint Dobszay | 2338bd3 | 2024-12-19 19:00:14 +0100 | [diff] [blame] | 52 | impl 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 Dobszay | a584685 | 2025-02-26 15:38:53 +0100 | [diff] [blame] | 61 | /// Properties of a partition. |
Balint Dobszay | 2338bd3 | 2024-12-19 19:00:14 +0100 | [diff] [blame] | 62 | #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] |
| 63 | pub struct PartitionProperties { |
Balint Dobszay | a584685 | 2025-02-26 15:38:53 +0100 | [diff] [blame] | 64 | /// The partition supports receipt of direct requests. |
Balint Dobszay | 5bf492f | 2024-07-29 17:21:32 +0200 | [diff] [blame] | 65 | pub support_direct_req_rec: bool, |
Balint Dobszay | a584685 | 2025-02-26 15:38:53 +0100 | [diff] [blame] | 66 | /// The partition can send direct requests. |
Balint Dobszay | 5bf492f | 2024-07-29 17:21:32 +0200 | [diff] [blame] | 67 | pub support_direct_req_send: bool, |
Balint Dobszay | de0dc80 | 2025-02-28 14:16:52 +0100 | [diff] [blame] | 68 | /// 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 Dobszay | a584685 | 2025-02-26 15:38:53 +0100 | [diff] [blame] | 74 | /// The partition can send and receive indirect messages. |
Balint Dobszay | 5bf492f | 2024-07-29 17:21:32 +0200 | [diff] [blame] | 75 | pub support_indirect_msg: bool, |
Balint Dobszay | a584685 | 2025-02-26 15:38:53 +0100 | [diff] [blame] | 76 | /// The partition supports receipt of notifications. |
Balint Dobszay | 5bf492f | 2024-07-29 17:21:32 +0200 | [diff] [blame] | 77 | pub support_notif_rec: bool, |
Balint Dobszay | a584685 | 2025-02-26 15:38:53 +0100 | [diff] [blame] | 78 | /// The partition must be informed about each VM that is created by the Hypervisor. |
Balint Dobszay | 5bf492f | 2024-07-29 17:21:32 +0200 | [diff] [blame] | 79 | pub subscribe_vm_created: bool, |
Balint Dobszay | a584685 | 2025-02-26 15:38:53 +0100 | [diff] [blame] | 80 | /// The partition must be informed about each VM that is destroyed by the Hypervisor. |
Balint Dobszay | 5bf492f | 2024-07-29 17:21:32 +0200 | [diff] [blame] | 81 | pub subscribe_vm_destroyed: bool, |
Balint Dobszay | a584685 | 2025-02-26 15:38:53 +0100 | [diff] [blame] | 82 | /// The partition runs in the AArch64 execution state. |
Balint Dobszay | 5bf492f | 2024-07-29 17:21:32 +0200 | [diff] [blame] | 83 | pub is_aarch64: bool, |
| 84 | } |
| 85 | |
Balint Dobszay | 2338bd3 | 2024-12-19 19:00:14 +0100 | [diff] [blame] | 86 | impl 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 Dobszay | de0dc80 | 2025-02-28 14:16:52 +0100 | [diff] [blame] | 94 | const SUPPORT_DIRECT_REQ2_REC_SHIFT: usize = 9; |
| 95 | const SUPPORT_DIRECT_REQ2_SEND_SHIFT: usize = 10; |
Balint Dobszay | 5bf492f | 2024-07-29 17:21:32 +0200 | [diff] [blame] | 96 | } |
| 97 | |
Balint Dobszay | de0dc80 | 2025-02-28 14:16:52 +0100 | [diff] [blame] | 98 | fn 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 Dobszay | 5bf492f | 2024-07-29 17:21:32 +0200 | [diff] [blame] | 111 | |
Balint Dobszay | de0dc80 | 2025-02-28 14:16:52 +0100 | [diff] [blame] | 112 | let mut prop_bits = match id_type { |
| 113 | PartitionIdType::PeEndpoint { .. } => { |
| 114 | let mut p = PartitionIdType::PE_ENDPOINT << PartitionIdType::SHIFT; |
Balint Dobszay | 5bf492f | 2024-07-29 17:21:32 +0200 | [diff] [blame] | 115 | |
Balint Dobszay | de0dc80 | 2025-02-28 14:16:52 +0100 | [diff] [blame] | 116 | 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 Dobszay | 5bf492f | 2024-07-29 17:21:32 +0200 | [diff] [blame] | 121 | } |
Balint Dobszay | de0dc80 | 2025-02-28 14:16:52 +0100 | [diff] [blame] | 122 | 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 Dobszay | 5bf492f | 2024-07-29 17:21:32 +0200 | [diff] [blame] | 125 | } |
Balint Dobszay | 2338bd3 | 2024-12-19 19:00:14 +0100 | [diff] [blame] | 126 | } |
Balint Dobszay | 2338bd3 | 2024-12-19 19:00:14 +0100 | [diff] [blame] | 127 | |
Balint Dobszay | de0dc80 | 2025-02-28 14:16:52 +0100 | [diff] [blame] | 128 | 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 Dobszay | 2338bd3 | 2024-12-19 19:00:14 +0100 | [diff] [blame] | 152 | } |
Balint Dobszay | de0dc80 | 2025-02-28 14:16:52 +0100 | [diff] [blame] | 153 | PartitionIdType::SepidIndep => PartitionIdType::SEPID_INDEP << PartitionIdType::SHIFT, |
| 154 | PartitionIdType::SepidDep { .. } => PartitionIdType::SEPID_DEP << PartitionIdType::SHIFT, |
| 155 | PartitionIdType::Aux => PartitionIdType::AUX << PartitionIdType::SHIFT, |
| 156 | }; |
Balint Dobszay | 2338bd3 | 2024-12-19 19:00:14 +0100 | [diff] [blame] | 157 | |
Balint Dobszay | de0dc80 | 2025-02-28 14:16:52 +0100 | [diff] [blame] | 158 | if properties.is_aarch64 { |
| 159 | prop_bits |= 1 << PartitionProperties::IS_AARCH64_SHIFT |
Balint Dobszay | 2338bd3 | 2024-12-19 19:00:14 +0100 | [diff] [blame] | 160 | } |
Balint Dobszay | de0dc80 | 2025-02-28 14:16:52 +0100 | [diff] [blame] | 161 | |
| 162 | (prop_bits, exec_ctx_count_or_proxy_id) |
Balint Dobszay | 2338bd3 | 2024-12-19 19:00:14 +0100 | [diff] [blame] | 163 | } |
| 164 | |
Balint Dobszay | de0dc80 | 2025-02-28 14:16:52 +0100 | [diff] [blame] | 165 | fn 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 Dobszay | 2338bd3 | 2024-12-19 19:00:14 +0100 | [diff] [blame] | 181 | |
Balint Dobszay | de0dc80 | 2025-02-28 14:16:52 +0100 | [diff] [blame] | 182 | let mut part_props = PartitionProperties::default(); |
Balint Dobszay | 2338bd3 | 2024-12-19 19:00:14 +0100 | [diff] [blame] | 183 | |
Balint Dobszay | de0dc80 | 2025-02-28 14:16:52 +0100 | [diff] [blame] | 184 | 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 Dobszay | 2338bd3 | 2024-12-19 19:00:14 +0100 | [diff] [blame] | 187 | |
Balint Dobszay | de0dc80 | 2025-02-28 14:16:52 +0100 | [diff] [blame] | 188 | if (prop_bits >> PartitionProperties::SUBSCRIBE_VM_CREATED_SHIFT) & 0b1 == 1 { |
| 189 | part_props.subscribe_vm_created = true; |
Balint Dobszay | 5bf492f | 2024-07-29 17:21:32 +0200 | [diff] [blame] | 190 | } |
Balint Dobszay | 5bf492f | 2024-07-29 17:21:32 +0200 | [diff] [blame] | 191 | |
Balint Dobszay | de0dc80 | 2025-02-28 14:16:52 +0100 | [diff] [blame] | 192 | if (prop_bits >> PartitionProperties::SUBSCRIBE_VM_DESTROYED_SHIFT) & 0b1 == 1 { |
| 193 | part_props.subscribe_vm_destroyed = true; |
Balint Dobszay | 2338bd3 | 2024-12-19 19:00:14 +0100 | [diff] [blame] | 194 | } |
Balint Dobszay | 5bf492f | 2024-07-29 17:21:32 +0200 | [diff] [blame] | 195 | } |
| 196 | |
Balint Dobszay | de0dc80 | 2025-02-28 14:16:52 +0100 | [diff] [blame] | 197 | if (prop_bits >> PartitionProperties::SUPPORT_DIRECT_REQ_SEND_SHIFT) & 0b1 == 1 { |
| 198 | part_props.support_direct_req_send = true; |
Balint Dobszay | 2338bd3 | 2024-12-19 19:00:14 +0100 | [diff] [blame] | 199 | } |
| 200 | |
Balint Dobszay | de0dc80 | 2025-02-28 14:16:52 +0100 | [diff] [blame] | 201 | 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 Dobszay | 2338bd3 | 2024-12-19 19:00:14 +0100 | [diff] [blame] | 215 | } |
Balint Dobszay | de0dc80 | 2025-02-28 14:16:52 +0100 | [diff] [blame] | 216 | |
| 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 Dobszay | 2338bd3 | 2024-12-19 19:00:14 +0100 | [diff] [blame] | 222 | } |
| 223 | |
Balint Dobszay | a584685 | 2025-02-26 15:38:53 +0100 | [diff] [blame] | 224 | /// Partition information descriptor, returned by the `FFA_PARTITION_INFO_GET` interface. |
Balint Dobszay | 2338bd3 | 2024-12-19 19:00:14 +0100 | [diff] [blame] | 225 | #[derive(Clone, Copy, Debug, PartialEq, Eq)] |
| 226 | pub struct PartitionInfo { |
| 227 | pub uuid: Uuid, |
| 228 | pub partition_id: u16, |
| 229 | pub partition_id_type: PartitionIdType, |
| 230 | pub props: PartitionProperties, |
| 231 | } |
| 232 | |
| 233 | impl PartitionInfo { |
Balint Dobszay | de0dc80 | 2025-02-28 14:16:52 +0100 | [diff] [blame] | 234 | pub const DESC_SIZE: usize = size_of::<partition_info_descriptor>(); |
Balint Dobszay | 2338bd3 | 2024-12-19 19:00:14 +0100 | [diff] [blame] | 235 | |
Balint Dobszay | a584685 | 2025-02-26 15:38:53 +0100 | [diff] [blame] | 236 | /// 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 Dobszay | de0dc80 | 2025-02-28 14:16:52 +0100 | [diff] [blame] | 238 | 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 Dobszay | 2338bd3 | 2024-12-19 19:00:14 +0100 | [diff] [blame] | 241 | 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 Dobszay | de0dc80 | 2025-02-28 14:16:52 +0100 | [diff] [blame] | 252 | ) = create_partition_properties(version, desc.partition_id_type, desc.props); |
Balint Dobszay | 2338bd3 | 2024-12-19 19:00:14 +0100 | [diff] [blame] | 253 | |
| 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 Kis | 61c3409 | 2025-04-10 14:14:38 +0200 | [diff] [blame] | 264 | /// `FFA_PARTITION_INFO_GET` specific success args structure. |
| 265 | #[derive(Debug, Eq, PartialEq, Clone, Copy)] |
| 266 | pub struct SuccessArgsPartitionInfoGet { |
| 267 | pub count: u32, |
| 268 | pub size: Option<u32>, |
| 269 | } |
| 270 | |
| 271 | impl 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 | |
| 277 | impl 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 Kis | 92b663e | 2025-04-10 14:15:05 +0200 | [diff] [blame] | 297 | /// `FFA_PARTITION_INFO_GET_REGS` specific success args structure. |
| 298 | #[derive(Debug, Eq, PartialEq, Clone, Copy)] |
| 299 | pub 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 | |
| 306 | impl 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 | |
| 314 | impl From<SuccessArgsPartitionInfoGetRegs> for SuccessArgs { |
| 315 | fn from(value: SuccessArgsPartitionInfoGetRegs) -> Self { |
| 316 | let mut args = [0; 16]; |
| 317 | |
Balint Dobszay | b2e9bed | 2025-04-15 12:57:36 +0200 | [diff] [blame] | 318 | args[0] = ((value.last_index as u64) << SuccessArgsPartitionInfoGetRegs::LAST_INDEX_SHIFT) |
Imre Kis | 92b663e | 2025-04-10 14:15:05 +0200 | [diff] [blame] | 319 | | ((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 | |
| 332 | impl 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 Dobszay | a584685 | 2025-02-26 15:38:53 +0100 | [diff] [blame] | 367 | /// Iterator of partition information descriptors. |
Balint Dobszay | 2338bd3 | 2024-12-19 19:00:14 +0100 | [diff] [blame] | 368 | pub struct PartitionInfoIterator<'a> { |
Balint Dobszay | de0dc80 | 2025-02-28 14:16:52 +0100 | [diff] [blame] | 369 | version: Version, |
Balint Dobszay | 2338bd3 | 2024-12-19 19:00:14 +0100 | [diff] [blame] | 370 | buf: &'a [u8], |
| 371 | offset: usize, |
| 372 | count: usize, |
| 373 | } |
| 374 | |
| 375 | impl<'a> PartitionInfoIterator<'a> { |
Balint Dobszay | a584685 | 2025-02-26 15:38:53 +0100 | [diff] [blame] | 376 | /// Create an iterator of partition information descriptors from a buffer. |
Balint Dobszay | de0dc80 | 2025-02-28 14:16:52 +0100 | [diff] [blame] | 377 | 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 Dobszay | 2338bd3 | 2024-12-19 19:00:14 +0100 | [diff] [blame] | 380 | 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 Dobszay | de0dc80 | 2025-02-28 14:16:52 +0100 | [diff] [blame] | 389 | version, |
Balint Dobszay | 2338bd3 | 2024-12-19 19:00:14 +0100 | [diff] [blame] | 390 | buf, |
| 391 | offset: 0, |
| 392 | count, |
| 393 | }) |
| 394 | } |
| 395 | } |
| 396 | |
| 397 | impl 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 Dobszay | de0dc80 | 2025-02-28 14:16:52 +0100 | [diff] [blame] | 414 | let (partition_id_type, props) = parse_partition_properties( |
| 415 | self.version, |
Balint Dobszay | 2338bd3 | 2024-12-19 19:00:14 +0100 | [diff] [blame] | 416 | desc_raw.partition_props, |
| 417 | desc_raw.exec_ctx_count_or_proxy_id, |
Balint Dobszay | de0dc80 | 2025-02-28 14:16:52 +0100 | [diff] [blame] | 418 | ); |
Balint Dobszay | 2338bd3 | 2024-12-19 19:00:14 +0100 | [diff] [blame] | 419 | |
| 420 | let uuid = Uuid::from_bytes(desc_raw.uuid); |
| 421 | |
| 422 | let desc = PartitionInfo { |
| 423 | uuid, |
| 424 | partition_id, |
Balint Dobszay | de0dc80 | 2025-02-28 14:16:52 +0100 | [diff] [blame] | 425 | partition_id_type, |
| 426 | props, |
Balint Dobszay | 2338bd3 | 2024-12-19 19:00:14 +0100 | [diff] [blame] | 427 | }; |
| 428 | |
| 429 | return Some(Ok(desc)); |
| 430 | } |
| 431 | |
| 432 | None |
Balint Dobszay | 5bf492f | 2024-07-29 17:21:32 +0200 | [diff] [blame] | 433 | } |
| 434 | } |
| 435 | |
| 436 | #[cfg(test)] |
| 437 | mod tests { |
| 438 | use super::*; |
Balint Dobszay | 5bf492f | 2024-07-29 17:21:32 +0200 | [diff] [blame] | 439 | use uuid::uuid; |
| 440 | |
Balint Dobszay | 2338bd3 | 2024-12-19 19:00:14 +0100 | [diff] [blame] | 441 | // TODO: add tests with a known correct partition info blob |
| 442 | |
Balint Dobszay | 5bf492f | 2024-07-29 17:21:32 +0200 | [diff] [blame] | 443 | #[test] |
| 444 | fn part_info() { |
Balint Dobszay | 2338bd3 | 2024-12-19 19:00:14 +0100 | [diff] [blame] | 445 | let desc1 = PartitionInfo { |
Balint Dobszay | 5bf492f | 2024-07-29 17:21:32 +0200 | [diff] [blame] | 446 | uuid: uuid!("12345678-1234-1234-1234-123456789abc"), |
Balint Dobszay | 2338bd3 | 2024-12-19 19:00:14 +0100 | [diff] [blame] | 447 | 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 Dobszay | de0dc80 | 2025-02-28 14:16:52 +0100 | [diff] [blame] | 459 | support_direct_req2_rec: Some(true), |
| 460 | support_direct_req2_send: Some(true), |
Balint Dobszay | 2338bd3 | 2024-12-19 19:00:14 +0100 | [diff] [blame] | 461 | }, |
| 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 Dobszay | de0dc80 | 2025-02-28 14:16:52 +0100 | [diff] [blame] | 476 | support_direct_req2_rec: None, |
| 477 | support_direct_req2_send: None, |
Balint Dobszay | 2338bd3 | 2024-12-19 19:00:14 +0100 | [diff] [blame] | 478 | }, |
Balint Dobszay | 5bf492f | 2024-07-29 17:21:32 +0200 | [diff] [blame] | 479 | }; |
| 480 | |
| 481 | let mut buf = [0u8; 0xff]; |
Balint Dobszay | de0dc80 | 2025-02-28 14:16:52 +0100 | [diff] [blame] | 482 | PartitionInfo::pack(Version(1, 2), &[desc1, desc2], &mut buf, true); |
Balint Dobszay | 5bf492f | 2024-07-29 17:21:32 +0200 | [diff] [blame] | 483 | |
Balint Dobszay | de0dc80 | 2025-02-28 14:16:52 +0100 | [diff] [blame] | 484 | let mut descriptors = PartitionInfoIterator::new(Version(1, 2), &buf, 2).unwrap(); |
Balint Dobszay | 2338bd3 | 2024-12-19 19:00:14 +0100 | [diff] [blame] | 485 | let desc1_check = descriptors.next().unwrap().unwrap(); |
| 486 | let desc2_check = descriptors.next().unwrap().unwrap(); |
Balint Dobszay | 5bf492f | 2024-07-29 17:21:32 +0200 | [diff] [blame] | 487 | |
Balint Dobszay | 2338bd3 | 2024-12-19 19:00:14 +0100 | [diff] [blame] | 488 | assert_eq!(desc1, desc1_check); |
| 489 | assert_eq!(desc2, desc2_check); |
Balint Dobszay | 5bf492f | 2024-07-29 17:21:32 +0200 | [diff] [blame] | 490 | } |
| 491 | } |