blob: 5301cb7c29fd2d79c5684446d07565a8b92fd8fb [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
4use uuid::Uuid;
5
6pub enum PartitionIdType {
7 PeEndpoint(u16),
8 SepidIndep,
9 SepidDep(u16),
10 Aux,
11}
12
13pub 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
26impl PartInfoDesc {
27 pub const SIZE: usize = 24;
28}
29
30pub 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)]
94mod 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}