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 | |
| 4 | use uuid::Uuid; |
| 5 | |
| 6 | pub enum PartitionIdType { |
| 7 | PeEndpoint(u16), |
| 8 | SepidIndep, |
| 9 | SepidDep(u16), |
| 10 | Aux, |
| 11 | } |
| 12 | |
| 13 | pub struct PartInfoDesc { |
| 14 | pub partition_id: u16, |
| 15 | pub uuid: Uuid, |
| 16 | pub id_type: PartitionIdType, |
| 17 | pub support_direct_req_rec: bool, |
| 18 | pub support_direct_req_send: bool, |
| 19 | pub support_indirect_msg: bool, |
| 20 | pub support_notif_rec: bool, |
| 21 | pub subscribe_vm_created: bool, |
| 22 | pub subscribe_vm_destroyed: bool, |
| 23 | pub is_aarch64: bool, |
| 24 | } |
| 25 | |
| 26 | impl PartInfoDesc { |
| 27 | pub const SIZE: usize = 24; |
| 28 | } |
| 29 | |
| 30 | pub fn create_partition_info(buf: &mut [u8], descriptors: &[PartInfoDesc], fill_uuid: bool) { |
| 31 | let mut offset = 0; |
| 32 | |
| 33 | for desc in descriptors { |
| 34 | // Offset 0, length 2: 16-bit ID of the partition, stream or auxiliary endpoint. |
| 35 | buf[offset..offset + 2].copy_from_slice(&desc.partition_id.to_le_bytes()); |
| 36 | |
| 37 | // Offset 2, length 2: Execution context count or Proxy partition ID |
| 38 | match desc.id_type { |
| 39 | PartitionIdType::PeEndpoint(exec_ctx_cnt) => { |
| 40 | buf[offset + 2..offset + 4].copy_from_slice(&exec_ctx_cnt.to_le_bytes()) |
| 41 | } |
| 42 | PartitionIdType::SepidDep(id) => { |
| 43 | buf[offset + 2..offset + 4].copy_from_slice(&id.to_le_bytes()) |
| 44 | } |
| 45 | _ => buf[offset + 2..offset + 4].fill(0), |
| 46 | } |
| 47 | |
| 48 | // Offset 4, length 4: Flags to determine partition properties. |
| 49 | let mut props = 0u32; |
| 50 | match desc.id_type { |
| 51 | PartitionIdType::PeEndpoint(_) => { |
| 52 | if desc.support_direct_req_rec { |
| 53 | props |= 0b1; |
| 54 | if desc.subscribe_vm_created { |
| 55 | // TODO: check NS phys instance |
| 56 | props |= 0b1 << 6 |
| 57 | } |
| 58 | if desc.subscribe_vm_destroyed { |
| 59 | // TODO: check NS phys instance |
| 60 | props |= 0b1 << 7 |
| 61 | } |
| 62 | } |
| 63 | if desc.support_direct_req_send { |
| 64 | props |= 0b1 << 1 |
| 65 | } |
| 66 | if desc.support_indirect_msg { |
| 67 | props |= 0b1 << 2 |
| 68 | } |
| 69 | if desc.support_notif_rec { |
| 70 | props |= 0b1 << 3 |
| 71 | } |
| 72 | } |
| 73 | PartitionIdType::SepidIndep => props |= 0b01 << 4, |
| 74 | PartitionIdType::SepidDep(_) => props |= 0b10 << 4, |
| 75 | PartitionIdType::Aux => props |= 0b11 << 4, |
| 76 | } |
| 77 | if desc.is_aarch64 { |
| 78 | props |= 0b1 << 8 |
| 79 | } |
| 80 | buf[offset + 4..offset + 8].copy_from_slice(&props.to_le_bytes()); |
| 81 | |
| 82 | // Offset 8, length 16: Partition UUID if the Nil UUID was specified. Reserved (MBZ) otherwise |
| 83 | if fill_uuid { |
| 84 | buf[offset + 8..offset + 24].copy_from_slice(desc.uuid.as_bytes()); |
| 85 | } else { |
| 86 | buf[offset + 8..offset + 24].fill(0); |
| 87 | } |
| 88 | |
| 89 | offset += PartInfoDesc::SIZE; |
| 90 | } |
| 91 | } |
| 92 | |
| 93 | #[cfg(test)] |
| 94 | mod tests { |
| 95 | use super::*; |
| 96 | |
| 97 | use uuid::uuid; |
| 98 | |
| 99 | #[test] |
| 100 | fn part_info() { |
| 101 | let desc = PartInfoDesc { |
| 102 | partition_id: 0x8001, |
| 103 | uuid: uuid!("12345678-1234-1234-1234-123456789abc"), |
| 104 | id_type: PartitionIdType::PeEndpoint(1), |
| 105 | support_direct_req_rec: true, |
| 106 | support_direct_req_send: true, |
| 107 | support_indirect_msg: false, |
| 108 | support_notif_rec: false, |
| 109 | subscribe_vm_created: true, |
| 110 | subscribe_vm_destroyed: true, |
| 111 | is_aarch64: true, |
| 112 | }; |
| 113 | |
| 114 | let mut buf = [0u8; 0xff]; |
| 115 | create_partition_info(&mut buf, &[desc], true); |
| 116 | |
| 117 | println!("{:#x?}", &buf[0..0x0f]); |
| 118 | |
| 119 | assert_eq!(0x8001_u16, u16::from_le_bytes([buf[0], buf[1]])); |
| 120 | } |
| 121 | } |