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@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__ */