blob: 5301cb7c29fd2d79c5684446d07565a8b92fd8fb [file] [log] [blame]
// SPDX-FileCopyrightText: Copyright 2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
// SPDX-License-Identifier: MIT OR Apache-2.0
use uuid::Uuid;
pub enum PartitionIdType {
PeEndpoint(u16),
SepidIndep,
SepidDep(u16),
Aux,
}
pub struct PartInfoDesc {
pub partition_id: u16,
pub uuid: Uuid,
pub id_type: PartitionIdType,
pub support_direct_req_rec: bool,
pub support_direct_req_send: bool,
pub support_indirect_msg: bool,
pub support_notif_rec: bool,
pub subscribe_vm_created: bool,
pub subscribe_vm_destroyed: bool,
pub is_aarch64: bool,
}
impl PartInfoDesc {
pub const SIZE: usize = 24;
}
pub fn create_partition_info(buf: &mut [u8], descriptors: &[PartInfoDesc], fill_uuid: bool) {
let mut offset = 0;
for desc in descriptors {
// Offset 0, length 2: 16-bit ID of the partition, stream or auxiliary endpoint.
buf[offset..offset + 2].copy_from_slice(&desc.partition_id.to_le_bytes());
// Offset 2, length 2: Execution context count or Proxy partition ID
match desc.id_type {
PartitionIdType::PeEndpoint(exec_ctx_cnt) => {
buf[offset + 2..offset + 4].copy_from_slice(&exec_ctx_cnt.to_le_bytes())
}
PartitionIdType::SepidDep(id) => {
buf[offset + 2..offset + 4].copy_from_slice(&id.to_le_bytes())
}
_ => buf[offset + 2..offset + 4].fill(0),
}
// Offset 4, length 4: Flags to determine partition properties.
let mut props = 0u32;
match desc.id_type {
PartitionIdType::PeEndpoint(_) => {
if desc.support_direct_req_rec {
props |= 0b1;
if desc.subscribe_vm_created {
// TODO: check NS phys instance
props |= 0b1 << 6
}
if desc.subscribe_vm_destroyed {
// TODO: check NS phys instance
props |= 0b1 << 7
}
}
if desc.support_direct_req_send {
props |= 0b1 << 1
}
if desc.support_indirect_msg {
props |= 0b1 << 2
}
if desc.support_notif_rec {
props |= 0b1 << 3
}
}
PartitionIdType::SepidIndep => props |= 0b01 << 4,
PartitionIdType::SepidDep(_) => props |= 0b10 << 4,
PartitionIdType::Aux => props |= 0b11 << 4,
}
if desc.is_aarch64 {
props |= 0b1 << 8
}
buf[offset + 4..offset + 8].copy_from_slice(&props.to_le_bytes());
// Offset 8, length 16: Partition UUID if the Nil UUID was specified. Reserved (MBZ) otherwise
if fill_uuid {
buf[offset + 8..offset + 24].copy_from_slice(desc.uuid.as_bytes());
} else {
buf[offset + 8..offset + 24].fill(0);
}
offset += PartInfoDesc::SIZE;
}
}
#[cfg(test)]
mod tests {
use super::*;
use uuid::uuid;
#[test]
fn part_info() {
let desc = PartInfoDesc {
partition_id: 0x8001,
uuid: uuid!("12345678-1234-1234-1234-123456789abc"),
id_type: PartitionIdType::PeEndpoint(1),
support_direct_req_rec: true,
support_direct_req_send: true,
support_indirect_msg: false,
support_notif_rec: false,
subscribe_vm_created: true,
subscribe_vm_destroyed: true,
is_aarch64: true,
};
let mut buf = [0u8; 0xff];
create_partition_info(&mut buf, &[desc], true);
println!("{:#x?}", &buf[0..0x0f]);
assert_eq!(0x8001_u16, u16::from_le_bytes([buf[0], buf[1]]));
}
}