Initial version
Add some common FF-A functionality. Supported features (roughly):
- define FF-A function IDs and error codes
- create boot info descriptor
- create partition info descriptor
- create and parse memory transaction descriptor
- parse memory relinquish descriptor
- parse console log message
Limitations apply, code quality is not production ready.
Signed-off-by: Balint Dobszay <balint.dobszay@arm.com>
Change-Id: Ibb3fde9d4c0d0d9b8823bb84cdcf23eb3f9d087a
diff --git a/src/partition_info.rs b/src/partition_info.rs
new file mode 100644
index 0000000..5301cb7
--- /dev/null
+++ b/src/partition_info.rs
@@ -0,0 +1,121 @@
+// 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]]));
+ }
+}