xref: /linux/drivers/tee/qcomtee/primordial_obj.c (revision 38057e323657695ec8f814aff0cdd1c7e00d3e9b)
10f7bfdcbSAmirreza Zarrabi // SPDX-License-Identifier: GPL-2.0-only
20f7bfdcbSAmirreza Zarrabi /*
30f7bfdcbSAmirreza Zarrabi  * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
40f7bfdcbSAmirreza Zarrabi  */
50f7bfdcbSAmirreza Zarrabi 
60f7bfdcbSAmirreza Zarrabi #include <linux/delay.h>
70f7bfdcbSAmirreza Zarrabi #include "qcomtee.h"
80f7bfdcbSAmirreza Zarrabi 
90f7bfdcbSAmirreza Zarrabi /**
100f7bfdcbSAmirreza Zarrabi  * DOC: Primordial Object
110f7bfdcbSAmirreza Zarrabi  *
120f7bfdcbSAmirreza Zarrabi  * After boot, the kernel provides a static object of type
130f7bfdcbSAmirreza Zarrabi  * %QCOMTEE_OBJECT_TYPE_CB called the primordial object. This object is used
140f7bfdcbSAmirreza Zarrabi  * for native kernel services or privileged operations.
150f7bfdcbSAmirreza Zarrabi  *
160f7bfdcbSAmirreza Zarrabi  * We support:
17*87ab676dSAmirreza Zarrabi  *  - %QCOMTEE_OBJECT_OP_MAP_REGION to map a memory object and return mapping
18*87ab676dSAmirreza Zarrabi  *    object and mapping information (see qcomtee_mem_object_map()).
190f7bfdcbSAmirreza Zarrabi  *  - %QCOMTEE_OBJECT_OP_YIELD to yield by the thread running in QTEE.
200f7bfdcbSAmirreza Zarrabi  *  - %QCOMTEE_OBJECT_OP_SLEEP to wait for a period of time.
210f7bfdcbSAmirreza Zarrabi  */
220f7bfdcbSAmirreza Zarrabi 
23*87ab676dSAmirreza Zarrabi #define QCOMTEE_OBJECT_OP_MAP_REGION 0
240f7bfdcbSAmirreza Zarrabi #define QCOMTEE_OBJECT_OP_YIELD 1
250f7bfdcbSAmirreza Zarrabi #define QCOMTEE_OBJECT_OP_SLEEP 2
260f7bfdcbSAmirreza Zarrabi 
27*87ab676dSAmirreza Zarrabi /* Mapping information format as expected by QTEE. */
28*87ab676dSAmirreza Zarrabi struct qcomtee_mapping_info {
29*87ab676dSAmirreza Zarrabi 	u64 paddr;
30*87ab676dSAmirreza Zarrabi 	u64 len;
31*87ab676dSAmirreza Zarrabi 	u32 perms;
32*87ab676dSAmirreza Zarrabi } __packed;
33*87ab676dSAmirreza Zarrabi 
340f7bfdcbSAmirreza Zarrabi static int
350f7bfdcbSAmirreza Zarrabi qcomtee_primordial_obj_dispatch(struct qcomtee_object_invoke_ctx *oic,
360f7bfdcbSAmirreza Zarrabi 				struct qcomtee_object *primordial_object_unused,
370f7bfdcbSAmirreza Zarrabi 				u32 op, struct qcomtee_arg *args)
380f7bfdcbSAmirreza Zarrabi {
39*87ab676dSAmirreza Zarrabi 	struct qcomtee_mapping_info *map_info;
40*87ab676dSAmirreza Zarrabi 	struct qcomtee_object *mem_object;
41*87ab676dSAmirreza Zarrabi 	struct qcomtee_object *map_object;
420f7bfdcbSAmirreza Zarrabi 	int err = 0;
430f7bfdcbSAmirreza Zarrabi 
440f7bfdcbSAmirreza Zarrabi 	switch (op) {
450f7bfdcbSAmirreza Zarrabi 	case QCOMTEE_OBJECT_OP_YIELD:
460f7bfdcbSAmirreza Zarrabi 		cond_resched();
470f7bfdcbSAmirreza Zarrabi 		/* No output object. */
480f7bfdcbSAmirreza Zarrabi 		oic->data = NULL;
49*87ab676dSAmirreza Zarrabi 
500f7bfdcbSAmirreza Zarrabi 		break;
510f7bfdcbSAmirreza Zarrabi 	case QCOMTEE_OBJECT_OP_SLEEP:
520f7bfdcbSAmirreza Zarrabi 		/* Check message format matched QCOMTEE_OBJECT_OP_SLEEP op. */
530f7bfdcbSAmirreza Zarrabi 		if (qcomtee_args_len(args) != 1 ||
540f7bfdcbSAmirreza Zarrabi 		    args[0].type != QCOMTEE_ARG_TYPE_IB ||
550f7bfdcbSAmirreza Zarrabi 		    args[0].b.size < sizeof(u32))
560f7bfdcbSAmirreza Zarrabi 			return -EINVAL;
570f7bfdcbSAmirreza Zarrabi 
580f7bfdcbSAmirreza Zarrabi 		msleep(*(u32 *)(args[0].b.addr));
590f7bfdcbSAmirreza Zarrabi 		/* No output object. */
600f7bfdcbSAmirreza Zarrabi 		oic->data = NULL;
61*87ab676dSAmirreza Zarrabi 
62*87ab676dSAmirreza Zarrabi 		break;
63*87ab676dSAmirreza Zarrabi 	case QCOMTEE_OBJECT_OP_MAP_REGION:
64*87ab676dSAmirreza Zarrabi 		if (qcomtee_args_len(args) != 3 ||
65*87ab676dSAmirreza Zarrabi 		    args[0].type != QCOMTEE_ARG_TYPE_OB ||
66*87ab676dSAmirreza Zarrabi 		    args[1].type != QCOMTEE_ARG_TYPE_IO ||
67*87ab676dSAmirreza Zarrabi 		    args[2].type != QCOMTEE_ARG_TYPE_OO ||
68*87ab676dSAmirreza Zarrabi 		    args[0].b.size < sizeof(struct qcomtee_mapping_info))
69*87ab676dSAmirreza Zarrabi 			return -EINVAL;
70*87ab676dSAmirreza Zarrabi 
71*87ab676dSAmirreza Zarrabi 		map_info = args[0].b.addr;
72*87ab676dSAmirreza Zarrabi 		mem_object = args[1].o;
73*87ab676dSAmirreza Zarrabi 
74*87ab676dSAmirreza Zarrabi 		qcomtee_mem_object_map(mem_object, &map_object,
75*87ab676dSAmirreza Zarrabi 				       &map_info->paddr, &map_info->len,
76*87ab676dSAmirreza Zarrabi 				       &map_info->perms);
77*87ab676dSAmirreza Zarrabi 
78*87ab676dSAmirreza Zarrabi 		args[2].o = map_object;
79*87ab676dSAmirreza Zarrabi 		/* One output object; pass it for cleanup to notify. */
80*87ab676dSAmirreza Zarrabi 		oic->data = map_object;
81*87ab676dSAmirreza Zarrabi 
82*87ab676dSAmirreza Zarrabi 		qcomtee_object_put(mem_object);
83*87ab676dSAmirreza Zarrabi 
840f7bfdcbSAmirreza Zarrabi 		break;
850f7bfdcbSAmirreza Zarrabi 	default:
860f7bfdcbSAmirreza Zarrabi 		err = -EINVAL;
870f7bfdcbSAmirreza Zarrabi 	}
880f7bfdcbSAmirreza Zarrabi 
890f7bfdcbSAmirreza Zarrabi 	return err;
900f7bfdcbSAmirreza Zarrabi }
910f7bfdcbSAmirreza Zarrabi 
92*87ab676dSAmirreza Zarrabi /* Called after submitting the callback response. */
93*87ab676dSAmirreza Zarrabi static void qcomtee_primordial_obj_notify(struct qcomtee_object_invoke_ctx *oic,
94*87ab676dSAmirreza Zarrabi 					  struct qcomtee_object *unused,
95*87ab676dSAmirreza Zarrabi 					  int err)
96*87ab676dSAmirreza Zarrabi {
97*87ab676dSAmirreza Zarrabi 	struct qcomtee_object *object = oic->data;
98*87ab676dSAmirreza Zarrabi 
99*87ab676dSAmirreza Zarrabi 	/* If err, QTEE did not obtain mapping object. Drop it. */
100*87ab676dSAmirreza Zarrabi 	if (object && err)
101*87ab676dSAmirreza Zarrabi 		qcomtee_object_put(object);
102*87ab676dSAmirreza Zarrabi }
103*87ab676dSAmirreza Zarrabi 
1040f7bfdcbSAmirreza Zarrabi static struct qcomtee_object_operations qcomtee_primordial_obj_ops = {
1050f7bfdcbSAmirreza Zarrabi 	.dispatch = qcomtee_primordial_obj_dispatch,
106*87ab676dSAmirreza Zarrabi 	.notify = qcomtee_primordial_obj_notify,
1070f7bfdcbSAmirreza Zarrabi };
1080f7bfdcbSAmirreza Zarrabi 
1090f7bfdcbSAmirreza Zarrabi struct qcomtee_object qcomtee_primordial_object = {
1100f7bfdcbSAmirreza Zarrabi 	.name = "primordial",
1110f7bfdcbSAmirreza Zarrabi 	.object_type = QCOMTEE_OBJECT_TYPE_CB,
1120f7bfdcbSAmirreza Zarrabi 	.ops = &qcomtee_primordial_obj_ops
1130f7bfdcbSAmirreza Zarrabi };
114