Skip to content

Commit 457c806

Browse files
authored
Merge pull request #15 from qc-azarrabi/mem-object
Mem object
2 parents 1b11dfb + 34c0076 commit 457c806

File tree

12 files changed

+570
-196
lines changed

12 files changed

+570
-196
lines changed

libqcomtee/CMakeLists.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@ include_directories(${QCBOR_INCLUDE_DIRS})
2020
# ''Source files''.
2121

2222
set(SRC
23-
src/qcomtee_object.c
24-
src/objects/credentials_obj.c
23+
src/qcomtee_object.c
24+
src/objects/credentials_obj.c
25+
src/objects/mem_obj.c
2526
)
2627

2728
add_library(qcomtee ${SRC})

libqcomtee/include/qcomtee_object.h

Lines changed: 46 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,23 @@ typedef uint32_t qcomtee_op_t;
2323
* @{
2424
*/
2525

26+
/**
27+
* @def QCOMTEE_OBJREF_TEE
28+
* @brief It indicates that the object is hosted in QTEE.
29+
*/
30+
#define QCOMTEE_OBJREF_TEE (1 << 0)
31+
2632
/**
2733
* @def QCOMTEE_OBJREF_USER
2834
* @brief It indicates that the object is hosted in userspace.
2935
*/
30-
#define QCOMTEE_OBJREF_USER (1 << 0)
36+
#define QCOMTEE_OBJREF_USER (1 << 1)
37+
38+
/**
39+
* @def QCOMTEE_OBJREF_MEM
40+
* @brief It indicates that the object is a memory object.
41+
*/
42+
#define QCOMTEE_OBJREF_MEM (1 << 2)
3143

3244
/** @} */ // end of ObjRefFlags
3345

@@ -44,7 +56,7 @@ typedef uint32_t qcomtee_op_t;
4456
* @brief Release object.
4557
*
4658
*/
47-
#define QCOMTEE_OBJREF_OP_RELEASE ((qcomtee_op_t)(65536))
59+
#define QCOMTEE_OBJREF_OP_RELEASE ((qcomtee_op_t)(65535))
4860

4961
/** @} */ // end of ObjRefOperations
5062

@@ -130,6 +142,7 @@ typedef enum {
130142
QCOMTEE_OBJECT_TYPE_TEE, /**< It is an object hosted in QTEE. */
131143
QCOMTEE_OBJECT_TYPE_ROOT, /**< It is a root object. */
132144
QCOMTEE_OBJECT_TYPE_CB, /**< It is a callback object. */
145+
QCOMTEE_OBJECT_TYPE_MEMORY, /**< It is a memory object. */
133146
} qcomtee_object_type_t;
134147

135148
/**
@@ -195,6 +208,7 @@ struct qcomtee_object_ops {
195208
struct qcomtee_object {
196209
atomic_int refs; /**< Number of references to this object. */
197210
uint64_t object_id; /**< ID assigned to this object. */
211+
uint64_t tee_object_id; /**< ID assigned to this object for QTEE. */
198212
qcomtee_object_type_t object_type; /**< Object Type. */
199213

200214
/**
@@ -244,10 +258,23 @@ qcomtee_object_typeof(struct qcomtee_object *object)
244258
/**
245259
* @brief Increase object reference count.
246260
* @param object The object being incremented.
261+
* @return On success, returns 0;
262+
* Otherwise, returns -1.
247263
*/
248-
static inline void qcomtee_object_refs_inc(struct qcomtee_object *object)
264+
static inline int qcomtee_object_refs_inc(struct qcomtee_object *object)
249265
{
250-
atomic_fetch_add(&object->refs, 1);
266+
int old;
267+
268+
if (object == QCOMTEE_OBJECT_NULL)
269+
return -1;
270+
271+
old = atomic_load(&object->refs);
272+
do {
273+
if (old == 0)
274+
return -1;
275+
} while (!atomic_compare_exchange_weak(&object->refs, &old, old + 1));
276+
277+
return 0;
251278
}
252279

253280
/**
@@ -256,9 +283,16 @@ static inline void qcomtee_object_refs_inc(struct qcomtee_object *object)
256283
*/
257284
void qcomtee_object_refs_dec(struct qcomtee_object *object);
258285

286+
#ifdef __GLIBC__
287+
typedef int (*tee_call_t)(int, unsigned long, ...);
288+
#else
289+
typedef int (*tee_call_t)(int, int, ...);
290+
#endif
291+
259292
/**
260293
* @brief Create a root object.
261294
* @param dev TEE device file pathname.
295+
* @param tee_call API to call to TEE driver (e.g. ioctl()).
262296
* @param release Called on destruction of this root object.
263297
* @param arg Argument passed to release.
264298
*
@@ -268,8 +302,10 @@ void qcomtee_object_refs_dec(struct qcomtee_object *object);
268302
* @return On success, returns the object;
269303
* Otherwise, returns @ref QCOMTEE_OBJECT_NULL.
270304
*/
271-
struct qcomtee_object *
272-
qcomtee_object_root_init(const char *dev, void (*release)(void *), void *arg);
305+
struct qcomtee_object *qcomtee_object_root_init(const char *dev,
306+
tee_call_t tee_call,
307+
void (*release)(void *),
308+
void *arg);
273309

274310
/**
275311
* @brief Initialize a callback objet.
@@ -282,12 +318,6 @@ int qcomtee_object_cb_init(struct qcomtee_object *object,
282318
struct qcomtee_object_ops *ops,
283319
struct qcomtee_object *root);
284320

285-
#ifdef __GLIBC__
286-
typedef int (*tee_call_t)(int, unsigned long, ...);
287-
#else
288-
typedef int (*tee_call_t)(int, int, ...);
289-
#endif
290-
291321
/**
292322
* @brief Invoke an Object.
293323
*
@@ -299,12 +329,11 @@ typedef int (*tee_call_t)(int, int, ...);
299329
* @param params Input parameter array to the requested operation.
300330
* @param num_params Number of parameter in the input array.
301331
* @param result Result of operation.
302-
* @param tee_call Submit request to kernel driver.
303332
* @return On success, 0; Otherwise, returns -1.
304333
*/
305334
int qcomtee_object_invoke(struct qcomtee_object *object, qcomtee_op_t op,
306335
struct qcomtee_param *params, int num_params,
307-
qcomtee_result_t *result, tee_call_t tee_call);
336+
qcomtee_result_t *result);
308337

309338
/**
310339
* @brief Process single request.
@@ -317,15 +346,13 @@ int qcomtee_object_invoke(struct qcomtee_object *object, qcomtee_op_t op,
317346
* operation. Therefore, if it is being executed by a pthread, it is not
318347
* safe to use PTHREAD_CANCEL_ASYNCHRONOUS.
319348
*
320-
* The tee_call function should implement support for reading a new request
321-
* (i.e., TEE_IOC_SUPPL_RECV) and submitting the response
349+
* The @ref qcomtee_object::tee_call function should implement support for
350+
* reading a new request (i.e., TEE_IOC_SUPPL_RECV) and submitting the response
322351
* (i.e., TEE_IOC_SUPPL_SEND).
323352
*
324353
* @param root The root object for which the request queue is checked.
325-
* @param tee_call Read a request and submit response to kernel driver.
326354
* @return On success, 0; Otherwise, returns -1.
327355
*/
328-
int qcomtee_object_process_one(struct qcomtee_object *root,
329-
tee_call_t tee_call);
356+
int qcomtee_object_process_one(struct qcomtee_object *root);
330357

331358
#endif // _QCOMTEE_OBJECT_H

libqcomtee/include/qcomtee_object_types.h

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,67 @@
88

99
/**
1010
* @brief Get a credentials object.
11-
* @param root_object The root object to which this object belongs.
11+
* @param root The root object to which this object belongs.
1212
* @param object Credentials object.
1313
* @return On success returns @ref QCOMTEE_OK;
1414
* Otherwise @ref QCOMTEE_ERROR_MEM.
1515
*/
1616
qcomtee_result_t
17-
qcomtee_object_credentials_init(struct qcomtee_object *root_object,
17+
qcomtee_object_credentials_init(struct qcomtee_object *root,
1818
struct qcomtee_object **object);
1919

20+
/* Select qcomtee_memory_object_alloc vs. qcomtee_memory_object_register. */
21+
#define qcomtee_memory_object_tee_api_select(a, b, c, d, fun, ...) fun
22+
23+
/**
24+
* @brief Allocate a memory object.
25+
*
26+
* Memory object is owned by the caller and should be released using
27+
* @ref qcomtee_memory_object_release.
28+
*
29+
* If sent to QTEE, a copy of the object is made and the owner keep their copy.
30+
* In most usecases, the object owner needs to share memory with QTEE rather
31+
* to donating it.
32+
*
33+
* For instance, if the memory object sent to QTEE in two different invocations,
34+
* their would be three copies of the object:
35+
* - The owner copy.
36+
* - The two copies sent to QTEE in the invocations.
37+
* Owner should release their copy using @ref qcomtee_memory_object_release.
38+
* QTEE will release its two copies.
39+
*
40+
* If the owner wants to donate the memory they can release their copy
41+
* @ref qcomtee_memory_object_release after the invocation to send the object.
42+
*
43+
* QTEE can only reference the memory objects that user owns. If the owner
44+
* releases the object (so they hold no copy), they can not receive it
45+
* back from QTEE.
46+
*
47+
* - If the owner donates a memory object to QTEE, they can not receive
48+
* it from QTEE as @ref QCOMTEE_OBJREF_OUTPUT.
49+
* - If the owner shared a memory object to QTEE, they can receive it
50+
* from QTEE (a copy of the object is made and should be release
51+
* separately using @ref qcomtee_memory_object_release by the receiver).
52+
*
53+
* At any time, the owner can call @ref qcomtee_object_refs_inc to create a
54+
* copy of the object. This copy should be released using
55+
* @ref qcomtee_memory_object_release.
56+
*
57+
* @param size Size of the memory object.
58+
* @param root The root object to which this object belongs.
59+
* @param object Memory object.
60+
* @return On success, returns 0; Otherwise, returns -1.
61+
*/
62+
int qcomtee_memory_object_alloc(size_t size, struct qcomtee_object *root,
63+
struct qcomtee_object **object);
64+
65+
void *qcomtee_memory_object_addr(struct qcomtee_object *object);
66+
size_t qcomtee_memory_object_size(struct qcomtee_object *object);
67+
68+
/**
69+
* @brief Release a memory object.
70+
* @param object The object being released.
71+
*/
72+
void qcomtee_memory_object_release(struct qcomtee_object *object);
73+
2074
#endif // _QCOMTEE_OBJECT_TYPES_H

libqcomtee/src/objects/credentials_obj.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ static struct qcomtee_object_ops ops = {
140140
};
141141

142142
qcomtee_result_t
143-
qcomtee_object_credentials_init(struct qcomtee_object *root_object,
143+
qcomtee_object_credentials_init(struct qcomtee_object *root,
144144
struct qcomtee_object **object)
145145
{
146146
struct qcomtee_credentials *qcomtee_cred;
@@ -149,7 +149,7 @@ qcomtee_object_credentials_init(struct qcomtee_object *root_object,
149149
if (!qcomtee_cred)
150150
return QCOMTEE_ERROR_MEM;
151151

152-
qcomtee_object_cb_init(&qcomtee_cred->object, &ops, root_object);
152+
qcomtee_object_cb_init(&qcomtee_cred->object, &ops, root);
153153
/* INIT the credentials buffer. */
154154
if (credentials_init(&qcomtee_cred->ubuf)) {
155155
free(qcomtee_cred);

libqcomtee/src/objects/mem_obj.c

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
// Copyright (c) 2025, Qualcomm Innovation Center, Inc. All rights reserved.
2+
// SPDX-License-Identifier: BSD-3-Clause
3+
4+
#include <stdlib.h>
5+
#include <unistd.h>
6+
#include <sys/mman.h>
7+
#include <linux/tee.h>
8+
#include <qcomtee_object_types.h>
9+
#include <qcomtee_object_private.h>
10+
11+
/* Which TEE API was used to prepare the memory object: */
12+
enum qcomtee_memory_type {
13+
QCOMTEE_MEMORY_TEE_ALLOC = 1,
14+
QCOMTEE_MEMORY_TEE_REGISTER
15+
};
16+
17+
/**
18+
* @brief Structure representing a memory object in TEE diver.
19+
*
20+
* This structure encapsulates information about a memory object
21+
* used in TEE driver.
22+
*/
23+
struct qcomtee_memory {
24+
struct qcomtee_object object;
25+
enum qcomtee_memory_type type;
26+
int fd; /**< File descriptor for TEE driver shm. */
27+
struct {
28+
void *addr; /**< mmaped address. */
29+
size_t size; /**< size of memory. */
30+
} mem_info;
31+
};
32+
33+
#define MEMORY(o) container_of((o), struct qcomtee_memory, object)
34+
35+
static void qcomtee_memory_release(struct qcomtee_object *object)
36+
{
37+
struct qcomtee_memory *qcomtee_mem = MEMORY(object);
38+
39+
if (qcomtee_mem->type == QCOMTEE_MEMORY_TEE_ALLOC)
40+
munmap(qcomtee_mem->mem_info.addr, qcomtee_mem->mem_info.size);
41+
42+
/* Release TEE shm. */
43+
if (qcomtee_mem->fd != -1)
44+
close(qcomtee_mem->fd);
45+
46+
free(qcomtee_mem);
47+
}
48+
49+
/**
50+
* @brief Allocate and initialize an empty memory object.
51+
*
52+
* The object has no physical memory assigned to it.
53+
*
54+
* @return On success, returns @ref qcomtee_memory; Otherwise, NULL.
55+
*/
56+
static struct qcomtee_memory *qcomtee_memory_alloc(void)
57+
{
58+
struct qcomtee_memory *qcomtee_mem;
59+
static struct qcomtee_object_ops ops = {
60+
.release = qcomtee_memory_release,
61+
};
62+
63+
qcomtee_mem = calloc(1, sizeof(*qcomtee_mem));
64+
if (qcomtee_mem) {
65+
QCOMTEE_OBJECT_INIT(&qcomtee_mem->object,
66+
QCOMTEE_OBJECT_TYPE_MEMORY);
67+
qcomtee_mem->object.ops = &ops;
68+
/* TEE shm not assigned yet. */
69+
qcomtee_mem->fd = -1;
70+
}
71+
72+
return qcomtee_mem;
73+
}
74+
75+
int qcomtee_memory_object_alloc(size_t size, struct qcomtee_object *root,
76+
struct qcomtee_object **object)
77+
{
78+
struct root_object *root_object = ROOT_OBJECT(root);
79+
struct tee_ioctl_shm_alloc_data data;
80+
struct qcomtee_memory *qcomtee_mem;
81+
void *addr;
82+
int fd;
83+
84+
qcomtee_mem = qcomtee_memory_alloc();
85+
if (!qcomtee_mem)
86+
return -1;
87+
88+
data.size = size;
89+
data.flags = 0;
90+
data.id = 0;
91+
fd = root_object->tee_call(root_object->fd, TEE_IOC_SHM_ALLOC, &data);
92+
if (fd < 0)
93+
goto err_release;
94+
95+
/* Assign TEE shm. */
96+
qcomtee_mem->object.tee_object_id = data.id;
97+
qcomtee_mem->fd = fd;
98+
99+
addr = mmap(NULL, data.size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
100+
if (addr == MAP_FAILED)
101+
goto err_release;
102+
103+
/* INIT the memory object. */
104+
qcomtee_mem->mem_info.addr = addr;
105+
qcomtee_mem->mem_info.size = data.size;
106+
qcomtee_mem->type = QCOMTEE_MEMORY_TEE_ALLOC;
107+
/* Keep a copy of root object; released in qcomtee_object_refs_dec. */
108+
qcomtee_object_refs_inc(root);
109+
qcomtee_mem->object.root = root;
110+
111+
*object = &qcomtee_mem->object;
112+
113+
return 0;
114+
115+
err_release:
116+
qcomtee_memory_object_release(&qcomtee_mem->object);
117+
118+
return -1;
119+
}
120+
121+
void *qcomtee_memory_object_addr(struct qcomtee_object *object)
122+
{
123+
return MEMORY(object)->mem_info.addr;
124+
}
125+
126+
size_t qcomtee_memory_object_size(struct qcomtee_object *object)
127+
{
128+
return MEMORY(object)->mem_info.size;
129+
}
130+
131+
void qcomtee_memory_object_release(struct qcomtee_object *object)
132+
{
133+
qcomtee_object_refs_dec(object);
134+
}

0 commit comments

Comments
 (0)