[PATCH RFC 06/10] firmware: riscv: rpmi-tee: parse system information tables
Amirreza Zarrabi
amirreza.zarrabi at oss.qualcomm.com
Mon Sep 28 20:16:57 PDT 2026
Add parsing for the RPMI TEE descriptor-table SYSINFO format used
during discovery. Validate the V1 header, the table directory, each
table's byte range, endpoint role flags, and endpoint-to-service
ownership before any record is trusted.
Support both the Self SYSINFO response, which identifies the local
REE endpoint, and the Whole-system SYSINFO response, which enumerates
the physical TEE endpoints and their service UUIDs.
Signed-off-by: Amirreza Zarrabi <amirreza.zarrabi at oss.qualcomm.com>
---
drivers/firmware/riscv_rpmi_tee/Makefile | 2 +-
drivers/firmware/riscv_rpmi_tee/sysinfo.c | 385 ++++++++++++++++++++++++++++++
drivers/firmware/riscv_rpmi_tee/sysinfo.h | 244 +++++++++++++++++++
3 files changed, 630 insertions(+), 1 deletion(-)
diff --git a/drivers/firmware/riscv_rpmi_tee/Makefile b/drivers/firmware/riscv_rpmi_tee/Makefile
index 8984127535ed..90cc6c39b273 100644
--- a/drivers/firmware/riscv_rpmi_tee/Makefile
+++ b/drivers/firmware/riscv_rpmi_tee/Makefile
@@ -3,6 +3,6 @@
rpmi-tee-bus-y = bus.o
rpmi-tee-core-objs := $(rpmi-tee-bus-y)
obj-$(CONFIG_RISCV_RPMI_TEE_TRANSPORT) = rpmi-tee-core.o
-rpmi-tee-driver-y = driver.o
+rpmi-tee-driver-y = driver.o sysinfo.o
rpmi-tee-module-objs := $(rpmi-tee-driver-y)
obj-$(CONFIG_RISCV_RPMI_TEE_TRANSPORT) += rpmi-tee-module.o
diff --git a/drivers/firmware/riscv_rpmi_tee/sysinfo.c b/drivers/firmware/riscv_rpmi_tee/sysinfo.c
new file mode 100644
index 000000000000..5829ab6db042
--- /dev/null
+++ b/drivers/firmware/riscv_rpmi_tee/sysinfo.c
@@ -0,0 +1,385 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ *
+ * RPMI TEE system-information descriptor table parsing
+ */
+
+#include <linux/errno.h>
+#include <linux/overflow.h>
+#include <linux/string.h>
+#include <linux/unaligned.h>
+
+#include "sysinfo.h"
+
+struct rpmi_tee_sysinfo_table {
+ const u8 *data;
+ u32 count;
+ u16 desc_size;
+ bool present;
+};
+
+/**
+ * struct rpmi_tee_sysinfo - Validated SYSINFO descriptor-table state
+ * @data: Start of the complete SYSINFO response buffer.
+ * @len: Size of @data in bytes.
+ * @tables: Table views indexed by &enum rpmi_tee_sysinfo_table_type.
+ *
+ * Each table view is populated only after the header, directory, table
+ * range, and descriptor size have been validated.
+ */
+struct rpmi_tee_sysinfo {
+ const u8 *data;
+ size_t len;
+ struct rpmi_tee_sysinfo_table tables[RPMI_TEE_SYSINFO_TABLE_MAX];
+};
+
+/* Assign table record @i in @t to a typed pointer @ptr. */
+#define rpmi_tee_sysinfo_entry_at(t, i, ptr) \
+ do { \
+ typeof(t) table = (t); \
+ (ptr) = (typeof(ptr))(table->data + \
+ (size_t)(i) * table->desc_size); \
+ } while (0)
+
+/**
+ * rpmi_tee_sysinfo_buffer_range() - Validate a serialized SYSINFO range
+ * @total: Total SYSINFO buffer size in bytes.
+ * @offset: Byte offset of the first record.
+ * @count: Number of records.
+ * @size: Size of one record in bytes.
+ * @start: Optional returned byte offset of the range.
+ *
+ * Check that @count records of @size bytes beginning at @offset neither
+ * overflow nor extend beyond @total. If non-NULL, @start receives the byte
+ * offset of the validated range.
+ *
+ * Return: 0 on success or -EINVAL if the range is invalid.
+ */
+static int rpmi_tee_sysinfo_buffer_range(size_t total, u32 offset, u32 count,
+ u16 size, size_t *start)
+{
+ size_t bytes, end;
+
+ if (check_mul_overflow((size_t)count, (size_t)size, &bytes) ||
+ check_add_overflow((size_t)offset, bytes, &end) || end > total)
+ return -EINVAL;
+
+ if (start)
+ *start = offset;
+
+ return 0;
+}
+
+/* Validate a directory descriptor and record its table range in @info. */
+static int rpmi_tee_sysinfo_get_table(struct rpmi_tee_sysinfo *info,
+ const struct rpmi_tee_sysinfo_table_desc *desc)
+{
+ u16 desc_size = get_unaligned_le16(&desc->desc_size);
+ u32 offset = get_unaligned_le32(&desc->offset);
+ u32 count = get_unaligned_le32(&desc->count);
+ u16 type = get_unaligned_le16(&desc->type);
+ struct rpmi_tee_sysinfo_table *table;
+ size_t start;
+
+ /* Validate table buffer. */
+ if (rpmi_tee_sysinfo_buffer_range(info->len, offset, count, desc_size,
+ &start))
+ return -EINVAL;
+
+ switch (type) {
+ case RPMI_TEE_SYSINFO_TABLE_ENDPOINT:
+ if (desc_size < sizeof(struct rpmi_tee_sysinfo_endpoint))
+ return -EINVAL;
+ break;
+ case RPMI_TEE_SYSINFO_TABLE_SERVICE:
+ if (desc_size < sizeof(struct rpmi_tee_sysinfo_service))
+ return -EINVAL;
+ break;
+ case RPMI_TEE_SYSINFO_TABLE_PARCEL:
+ if (desc_size < sizeof(struct rpmi_tee_sysinfo_parcel))
+ return -EINVAL;
+ break;
+ case RPMI_TEE_SYSINFO_TABLE_PARCEL_RECEIVER:
+ if (desc_size < sizeof(struct rpmi_tee_sysinfo_parcel_receiver))
+ return -EINVAL;
+ break;
+ case RPMI_TEE_SYSINFO_TABLE_MEMORY_BLOCK:
+ if (desc_size < sizeof(struct rpmi_tee_sysinfo_memory_block))
+ return -EINVAL;
+ break;
+ case RPMI_TEE_SYSINFO_TABLE_BLOB:
+ /* BLOB table is defined as raw bytes. */
+ if (desc_size != 1)
+ return -EINVAL;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ table = &info->tables[type];
+ if (table->present)
+ return -EINVAL;
+
+ table->data = info->data + start;
+ table->count = count;
+ table->desc_size = desc_size;
+ table->present = true;
+
+ return 0;
+}
+
+/* Validate the header and directory, then populate table views. */
+static int rpmi_tee_sysinfo_init(struct rpmi_tee_sysinfo *info,
+ const void *data, size_t len)
+{
+ const struct rpmi_tee_sysinfo_header *header = data;
+ u32 i, table_count, dir_off;
+ u16 header_size, dir_size;
+
+ memset(info, 0, sizeof(*info));
+
+ if (len < sizeof(struct rpmi_tee_sysinfo_header))
+ return -EINVAL;
+
+ if (get_unaligned_le32(&header->magic) != RPMI_TEE_SYSINFO_MAGIC ||
+ get_unaligned_le16(&header->major) != RPMI_TEE_SYSINFO_VERSION_MAJOR ||
+ get_unaligned_le32(&header->total_size) != len)
+ return -EINVAL;
+
+ header_size = get_unaligned_le16(&header->header_size);
+ dir_size = get_unaligned_le16(&header->table_desc_size);
+ table_count = get_unaligned_le32(&header->table_count);
+ dir_off = get_unaligned_le32(&header->table_dir_offset);
+
+ if (header_size < sizeof(struct rpmi_tee_sysinfo_header) ||
+ dir_size < sizeof(struct rpmi_tee_sysinfo_table_desc) ||
+ /* Directory can not overlap with the header. */
+ dir_off < header_size)
+ return -EINVAL;
+
+ /* Validate directory buffer. */
+ if (rpmi_tee_sysinfo_buffer_range(len, dir_off, table_count, dir_size,
+ NULL))
+ return -EINVAL;
+
+ info->data = data;
+ info->len = len;
+ for (i = 0; i < table_count; i++) {
+ const struct rpmi_tee_sysinfo_table_desc *desc;
+ int ret;
+
+ desc = rpmi_tee_sysinfo_desc_at(header, i);
+ ret = rpmi_tee_sysinfo_get_table(info, desc);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * rpmi_tee_sysinfo_table_check() - Check a table index range
+ * @table: Validated table view.
+ * @offset: First record index, or first byte index for a BLOB table.
+ * @count: Number of records, or bytes for a BLOB table.
+ *
+ * An empty range @count = 0 is valid.
+ * A non-empty range must fit wholly within @table.
+ *
+ * Return: %true if the range is valid or %false otherwise.
+ */
+static bool
+rpmi_tee_sysinfo_table_check(const struct rpmi_tee_sysinfo_table *table,
+ u32 offset, u32 count)
+{
+ size_t end;
+
+ if (!count)
+ return true;
+ /* For table->present = false or empty table, table->count is zero. */
+ return !check_add_overflow((size_t)offset, (size_t)count, &end) &&
+ end <= table->count;
+}
+
+/* Validate endpoint records and their service ranges. */
+static int rpmi_tee_sysinfo_validate_endpoints(struct rpmi_tee_sysinfo *info,
+ bool require_single_ree,
+ u32 *self_ep_id)
+{
+ const struct rpmi_tee_sysinfo_table *service_table;
+ const struct rpmi_tee_sysinfo_table *ep_table;
+ const struct rpmi_tee_sysinfo_endpoint *ep;
+ u32 ree_count = 0, ep_idx;
+
+ ep_table = &info->tables[RPMI_TEE_SYSINFO_TABLE_ENDPOINT];
+ service_table = &info->tables[RPMI_TEE_SYSINFO_TABLE_SERVICE];
+ /* Endpoint table should exist and not empty; service table can be empty. */
+ if (!ep_table->present || !ep_table->count || !service_table->present)
+ return -EINVAL;
+
+ for (ep_idx = 0; ep_idx < ep_table->count; ep_idx++) {
+ rpmi_tee_sysinfo_entry_at(ep_table, ep_idx, ep);
+
+ /* struct rpmi_tee_sysinfo_endpoint. */
+ u32 ep_id = get_unaligned_le32(&ep->id);
+ u32 parent_id = get_unaligned_le32(&ep->parent_id);
+ u32 ep_flags = get_unaligned_le32(&ep->flags);
+ u32 service_first = get_unaligned_le32(&ep->service_first);
+ u32 service_range_count =
+ get_unaligned_le32(&ep->service_count);
+
+ bool is_physical =
+ ep_flags & RPMI_TEE_SYSINFO_ENDPOINT_F_PHYSICAL;
+ bool is_ree = ep_flags & RPMI_TEE_SYSINFO_ENDPOINT_F_REE;
+ /* Require exactly one endpoint location and security role. */
+ if (is_physical ==
+ !!(ep_flags & RPMI_TEE_SYSINFO_ENDPOINT_F_PROXIED) ||
+ is_ree == !!(ep_flags & RPMI_TEE_SYSINFO_ENDPOINT_F_TEE) ||
+ ep_flags & ~RPMI_TEE_SYSINFO_ENDPOINT_F_MASK)
+ return -EINVAL;
+
+ if (!rpmi_tee_sysinfo_table_check(service_table, service_first,
+ service_range_count))
+ return -EINVAL;
+
+ if (is_physical) {
+ if (parent_id != RPMI_TEE_SYSINFO_ENDPOINT_NO_PARENT)
+ return -EINVAL;
+
+ if (is_ree) {
+ ree_count++;
+ if (self_ep_id)
+ *self_ep_id = ep_id;
+ }
+ }
+ }
+
+ if (require_single_ree && ree_count != 1)
+ return -EINVAL;
+
+ return 0;
+}
+
+/**
+ * rpmi_tee_sysinfo_parse_self() - Parse a Self SYSINFO table
+ * @data: SYSINFO response buffer.
+ * @len: Size of @data in bytes.
+ * @self_ep_id: Returned local REE endpoint identifier.
+ *
+ * Return: 0 on success or a negative error code.
+ */
+int rpmi_tee_sysinfo_parse_self(const void *data, size_t len, u32 *self_ep_id)
+{
+ struct rpmi_tee_sysinfo info;
+ int ret;
+
+ if (!self_ep_id)
+ return -EINVAL;
+
+ ret = rpmi_tee_sysinfo_init(&info, data, len);
+ if (ret)
+ return ret;
+ /* Expect single endpoint in a self SYSINFO response. */
+ if (info.tables[RPMI_TEE_SYSINFO_TABLE_ENDPOINT].count != 1)
+ return -EINVAL;
+
+ return rpmi_tee_sysinfo_validate_endpoints(&info, true, self_ep_id);
+}
+
+/**
+ * rpmi_tee_sysinfo_parse_system() - Parse a Whole-system SYSINFO table
+ * @data: SYSINFO response buffer.
+ * @len: Size of @data in bytes.
+ * @self_ep_id: Local REE endpoint identifier from the Self table.
+ * @system: Caller-provided discovery-result storage and returned counts.
+ *
+ * The parser records the number of required endpoint and service entries in
+ * @system. If either caller-provided array is too small, it fills the entries
+ * that fit, returns -ENOSPC, and reports the required counts. The caller may
+ * then allocate the reported capacities and call this function again.
+ *
+ * Return: 0 on success, -ENOSPC if an output array is too small, or a
+ * negative error code.
+ */
+int rpmi_tee_sysinfo_parse_system(const void *data, size_t len, u32 self_ep_id,
+ struct rpmi_tee_sysinfo_system *system)
+{
+ const struct rpmi_tee_sysinfo_table *service_table;
+ const struct rpmi_tee_sysinfo_table *ep_table;
+ const struct rpmi_tee_sysinfo_endpoint *ep;
+ size_t ep_count = 0, service_count = 0;
+ struct rpmi_tee_sysinfo info;
+ bool self_ep_found = false;
+ u32 ep_idx, service_idx;
+ int ret;
+
+ if ((system->ep_capacity && !system->eps) ||
+ (system->service_capacity && !system->services))
+ return -EINVAL;
+
+ ret = rpmi_tee_sysinfo_init(&info, data, len);
+ if (ret)
+ return ret;
+
+ ret = rpmi_tee_sysinfo_validate_endpoints(&info, false, NULL);
+ if (ret)
+ return ret;
+
+ ep_table = &info->tables[RPMI_TEE_SYSINFO_TABLE_ENDPOINT];
+ service_table = &info->tables[RPMI_TEE_SYSINFO_TABLE_SERVICE];
+
+ for (ep_idx = 0; ep_idx < ep_table->count; ep_idx++) {
+ rpmi_tee_sysinfo_entry_at(ep_table, ep_idx, ep);
+
+ /* struct rpmi_tee_sysinfo_endpoint. */
+ u32 ep_flags = get_unaligned_le32(&ep->flags);
+ u32 ep_id = get_unaligned_le32(&ep->id);
+ u32 service_first = get_unaligned_le32(&ep->service_first);
+ u32 service_range_count =
+ get_unaligned_le32(&ep->service_count);
+
+ /* Make sure self_ep_id exists in the list of endpoints. */
+ if ((ep_flags & (RPMI_TEE_SYSINFO_ENDPOINT_F_PHYSICAL |
+ RPMI_TEE_SYSINFO_ENDPOINT_F_REE)) ==
+ (RPMI_TEE_SYSINFO_ENDPOINT_F_PHYSICAL |
+ RPMI_TEE_SYSINFO_ENDPOINT_F_REE) && ep_id == self_ep_id)
+ self_ep_found = true;
+
+ if (!(ep_flags & RPMI_TEE_SYSINFO_ENDPOINT_F_PHYSICAL) ||
+ !(ep_flags & RPMI_TEE_SYSINFO_ENDPOINT_F_TEE))
+ continue;
+
+ if (ep_count < system->ep_capacity)
+ system->eps[ep_count].endpoint_id = ep_id;
+
+ ep_count++;
+
+ /* Extract per-endpoint services. */
+ for (service_idx = service_first;
+ service_idx < service_first + service_range_count;
+ service_idx++) {
+ const struct rpmi_tee_sysinfo_service *service;
+
+ if (service_count < system->service_capacity) {
+ rpmi_tee_sysinfo_entry_at(service_table,
+ service_idx, service);
+ system->services[service_count].endpoint_id = ep_id;
+ import_uuid(&system->services[service_count].uuid,
+ service->uuid);
+ }
+
+ if (check_add_overflow(service_count, 1, &service_count))
+ return -EOVERFLOW;
+ }
+ }
+
+ system->ep_count = ep_count;
+ system->service_count = service_count;
+
+ if (!self_ep_found)
+ return -EINVAL;
+
+ return ep_count > system->ep_capacity ||
+ service_count > system->service_capacity ? -ENOSPC : 0;
+}
diff --git a/drivers/firmware/riscv_rpmi_tee/sysinfo.h b/drivers/firmware/riscv_rpmi_tee/sysinfo.h
new file mode 100644
index 000000000000..f275a612f720
--- /dev/null
+++ b/drivers/firmware/riscv_rpmi_tee/sysinfo.h
@@ -0,0 +1,244 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#ifndef __RISC_V_RPMI_TEE_SYSINFO_H__
+#define __RISC_V_RPMI_TEE_SYSINFO_H__
+
+#include <linux/bitops.h>
+#include <linux/limits.h>
+#include <linux/types.h>
+#include <linux/unaligned.h>
+#include <linux/uuid.h>
+
+/* RPMI_TEE_FEATURE_SYSINFO_FORMAT. */
+#define RPMI_TEE_SYSINFO_FORMAT_CBOR BIT(31) /* CBOR format. */
+#define RPMI_TEE_SYSINFO_FORMAT_TABLE BIT(30) /* Descriptor-table format. */
+
+/* "SYSINFO descriptor-table format". */
+
+#define RPMI_TEE_SYSINFO_MAGIC 0x49535452 /* Table magic ("RTSI"). */
+#define RPMI_TEE_SYSINFO_VERSION_MAJOR 1 /* Supported major version. */
+
+/**
+ * struct rpmi_tee_sysinfo_header - SYSINFO descriptor-table header
+ * @magic: RPMI_TEE_SYSINFO_MAGIC.
+ * @major: Major format version.
+ * @minor: Minor format version.
+ * @header_size: Header size, including compatible extensions.
+ * @table_desc_size: Size of one table-directory descriptor.
+ * @total_size: Total response size in bytes.
+ * @table_count: Number of table-directory descriptors.
+ * @table_dir_offset: Byte offset of the table directory.
+ * @flags: Ignored by version 1 Linux.
+ * @reserved: Ignored by version 1 Linux.
+ */
+struct rpmi_tee_sysinfo_header {
+ __le32 magic;
+ __le16 major;
+ __le16 minor;
+ __le16 header_size;
+ __le16 table_desc_size;
+ __le32 total_size;
+ __le32 table_count;
+ __le32 table_dir_offset;
+ __le32 flags;
+ __le32 reserved;
+} __packed;
+
+enum rpmi_tee_sysinfo_table_type {
+ RPMI_TEE_SYSINFO_TABLE_ENDPOINT = 0, /* Endpoint records. */
+ RPMI_TEE_SYSINFO_TABLE_SERVICE, /* Service UUID records. */
+ RPMI_TEE_SYSINFO_TABLE_PARCEL, /* Memory parcel records. */
+ RPMI_TEE_SYSINFO_TABLE_PARCEL_RECEIVER, /* Parcel receiver records. */
+ RPMI_TEE_SYSINFO_TABLE_MEMORY_BLOCK, /* Memory block records. */
+ RPMI_TEE_SYSINFO_TABLE_BLOB, /* Arbitrary byte data. */
+ RPMI_TEE_SYSINFO_TABLE_MAX, /* One past the last table type. */
+};
+
+/**
+ * struct rpmi_tee_sysinfo_table_desc - SYSINFO table-directory descriptor
+ * @type: Table type from &enum rpmi_tee_sysinfo_table_type.
+ * @desc_size: Size of one record in this table.
+ * @count: Number of records in the table.
+ * @offset: Byte offset of the first record.
+ * @flags: Ignored by version 1 Linux.
+ */
+struct rpmi_tee_sysinfo_table_desc {
+ __le16 type;
+ __le16 desc_size;
+ __le32 count;
+ __le32 offset;
+ __le32 flags;
+} __packed;
+
+/**
+ * rpmi_tee_sysinfo_desc_at() - Get a table-directory descriptor
+ * @header: SYSINFO response header at the start of the response buffer.
+ * @index: Table-directory descriptor index.
+ *
+ * The caller must validate the table-directory range and @index before using
+ * the returned descriptor.
+ *
+ * Return: Pointer to the descriptor's known prefix.
+ */
+static inline const struct rpmi_tee_sysinfo_table_desc *
+rpmi_tee_sysinfo_desc_at(const struct rpmi_tee_sysinfo_header *header,
+ u32 index)
+{
+ u32 offset = get_unaligned_le32(&header->table_dir_offset);
+ u16 stride = get_unaligned_le16(&header->table_desc_size);
+
+ return (const void *)((const u8 *)header + offset +
+ (size_t)index * stride);
+}
+
+/* Records. */
+
+#define RPMI_TEE_SYSINFO_ENDPOINT_NO_PARENT U32_MAX /* No parent endpoint. */
+
+#define RPMI_TEE_SYSINFO_ENDPOINT_F_PHYSICAL BIT(0) /* Physical endpoint. */
+#define RPMI_TEE_SYSINFO_ENDPOINT_F_PROXIED BIT(1) /* Proxied endpoint. */
+#define RPMI_TEE_SYSINFO_ENDPOINT_F_REE BIT(2) /* REE endpoint. */
+#define RPMI_TEE_SYSINFO_ENDPOINT_F_TEE BIT(3) /* TEE endpoint. */
+#define RPMI_TEE_SYSINFO_ENDPOINT_F_PERSISTENT BIT(4) /* Persistent endpoint. */
+#define RPMI_TEE_SYSINFO_ENDPOINT_F_MASK \
+ (RPMI_TEE_SYSINFO_ENDPOINT_F_PHYSICAL | \
+ RPMI_TEE_SYSINFO_ENDPOINT_F_PROXIED | \
+ RPMI_TEE_SYSINFO_ENDPOINT_F_REE | \
+ RPMI_TEE_SYSINFO_ENDPOINT_F_TEE | \
+ RPMI_TEE_SYSINFO_ENDPOINT_F_PERSISTENT)
+
+/**
+ * struct rpmi_tee_sysinfo_endpoint - Endpoint table record
+ * @id: Endpoint identifier.
+ * @parent_id: Parent endpoint identifier, if proxied.
+ * @flags: RPMI_TEE_SYSINFO_ENDPOINT_F_* flags.
+ * @service_first: First service record owned by the endpoint.
+ * @service_count: Number of service records owned by the endpoint.
+ * @parcel_first: First parcel record owned by the endpoint.
+ * @parcel_count: Number of parcel records owned by the endpoint.
+ * @name_offset: Byte offset of the endpoint name in the blob table.
+ * @name_length: Endpoint name length in bytes.
+ * @metadata_offset: Byte offset of endpoint metadata in the blob table.
+ * @metadata_length: Endpoint metadata length in bytes.
+ */
+struct rpmi_tee_sysinfo_endpoint {
+ __le32 id;
+ __le32 parent_id;
+ __le32 flags;
+ __le32 service_first;
+ __le32 service_count;
+ __le32 parcel_first;
+ __le32 parcel_count;
+ __le32 name_offset;
+ __le32 name_length;
+ __le32 metadata_offset;
+ __le32 metadata_length;
+} __packed;
+
+/**
+ * struct rpmi_tee_sysinfo_service - Service table record
+ * @uuid: Service UUID.
+ */
+struct rpmi_tee_sysinfo_service {
+ u8 uuid[16];
+} __packed;
+
+/**
+ * struct rpmi_tee_sysinfo_parcel - Memory parcel table record
+ * @id: Parcel identifier.
+ * @residual_access: Residual access permissions after relinquish.
+ * @receiver_first: First parcel receiver record.
+ * @receiver_count: Number of parcel receiver records.
+ * @block_first: First memory block record.
+ * @block_count: Number of memory block records.
+ * @label_offset: Byte offset of the parcel label in the blob table.
+ * @label_length: Parcel label length in bytes.
+ * @flags: Parcel flags.
+ * @reserved: Must be zero.
+ */
+struct rpmi_tee_sysinfo_parcel {
+ __le32 id;
+ __le32 residual_access;
+ __le32 receiver_first;
+ __le32 receiver_count;
+ __le32 block_first;
+ __le32 block_count;
+ __le32 label_offset;
+ __le32 label_length;
+ __le32 flags;
+ __le32 reserved;
+} __packed;
+
+/**
+ * struct rpmi_tee_sysinfo_parcel_receiver - Parcel receiver table record
+ * @endpoint_id: Receiver endpoint identifier.
+ * @access: Access permissions granted to the receiver.
+ * @flags: Receiver flags.
+ * @reserved: Must be zero.
+ */
+struct rpmi_tee_sysinfo_parcel_receiver {
+ __le32 endpoint_id;
+ __le32 access;
+ __le32 flags;
+ __le32 reserved;
+} __packed;
+
+/**
+ * struct rpmi_tee_sysinfo_memory_block - Memory block table record
+ * @address: Physical base address.
+ * @size: Block size in bytes.
+ */
+struct rpmi_tee_sysinfo_memory_block {
+ __le64 address;
+ __le64 size;
+} __packed;
+
+/**
+ * struct rpmi_tee_sysinfo_service_info - Discovered TEE service
+ * @endpoint_id: Owning TEE endpoint identifier.
+ * @uuid: Service UUID.
+ */
+struct rpmi_tee_sysinfo_service_info {
+ u32 endpoint_id;
+ uuid_t uuid;
+};
+
+/**
+ * struct rpmi_tee_sysinfo_endpoint_info - Discovered physical TEE endpoint
+ * @endpoint_id: TEE endpoint identifier.
+ */
+struct rpmi_tee_sysinfo_endpoint_info {
+ u32 endpoint_id;
+};
+
+/**
+ * struct rpmi_tee_sysinfo_system - Parsed Whole-system discovery result
+ * @eps: Caller-provided array of physical TEE endpoints.
+ * @ep_capacity: Number of entries available in @eps.
+ * @ep_count: Number of discovered physical TEE endpoints.
+ * @services: Caller-provided array of TEE services.
+ * @service_capacity: Number of entries available in @services.
+ * @service_count: Number of discovered TEE services.
+ *
+ * The caller supplies storage and capacities. A sizing call with zero
+ * capacities reports the required counts and returns -ENOSPC for a nonempty
+ * result.
+ */
+struct rpmi_tee_sysinfo_system {
+ struct rpmi_tee_sysinfo_endpoint_info *eps;
+ size_t ep_capacity;
+ size_t ep_count;
+ struct rpmi_tee_sysinfo_service_info *services;
+ size_t service_capacity;
+ size_t service_count;
+};
+
+int rpmi_tee_sysinfo_parse_self(const void *data, size_t len, u32 *self_ep_id);
+int rpmi_tee_sysinfo_parse_system(const void *data, size_t len,
+ u32 self_ep_id,
+ struct rpmi_tee_sysinfo_system *system);
+
+#endif /* __RISC_V_RPMI_TEE_SYSINFO_H__ */
--
2.34.1
More information about the linux-riscv
mailing list