1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. 4 */ 5 6 #include <linux/delay.h> 7 #include "qcomtee.h" 8 9 /** 10 * DOC: Primordial Object 11 * 12 * After boot, the kernel provides a static object of type 13 * %QCOMTEE_OBJECT_TYPE_CB called the primordial object. This object is used 14 * for native kernel services or privileged operations. 15 * 16 * We support: 17 * - %QCOMTEE_OBJECT_OP_MAP_REGION to map a memory object and return mapping 18 * object and mapping information (see qcomtee_mem_object_map()). 19 * - %QCOMTEE_OBJECT_OP_YIELD to yield by the thread running in QTEE. 20 * - %QCOMTEE_OBJECT_OP_SLEEP to wait for a period of time. 21 */ 22 23 #define QCOMTEE_OBJECT_OP_MAP_REGION 0 24 #define QCOMTEE_OBJECT_OP_YIELD 1 25 #define QCOMTEE_OBJECT_OP_SLEEP 2 26 27 /* Mapping information format as expected by QTEE. */ 28 struct qcomtee_mapping_info { 29 u64 paddr; 30 u64 len; 31 u32 perms; 32 } __packed; 33 34 static int 35 qcomtee_primordial_obj_dispatch(struct qcomtee_object_invoke_ctx *oic, 36 struct qcomtee_object *primordial_object_unused, 37 u32 op, struct qcomtee_arg *args) 38 { 39 struct qcomtee_mapping_info *map_info; 40 struct qcomtee_object *mem_object; 41 struct qcomtee_object *map_object; 42 int err = 0; 43 44 switch (op) { 45 case QCOMTEE_OBJECT_OP_YIELD: 46 cond_resched(); 47 /* No output object. */ 48 oic->data = NULL; 49 50 break; 51 case QCOMTEE_OBJECT_OP_SLEEP: 52 /* Check message format matched QCOMTEE_OBJECT_OP_SLEEP op. */ 53 if (qcomtee_args_len(args) != 1 || 54 args[0].type != QCOMTEE_ARG_TYPE_IB || 55 args[0].b.size < sizeof(u32)) 56 return -EINVAL; 57 58 msleep(*(u32 *)(args[0].b.addr)); 59 /* No output object. */ 60 oic->data = NULL; 61 62 break; 63 case QCOMTEE_OBJECT_OP_MAP_REGION: 64 if (qcomtee_args_len(args) != 3 || 65 args[0].type != QCOMTEE_ARG_TYPE_OB || 66 args[1].type != QCOMTEE_ARG_TYPE_IO || 67 args[2].type != QCOMTEE_ARG_TYPE_OO || 68 args[0].b.size < sizeof(struct qcomtee_mapping_info)) 69 return -EINVAL; 70 71 map_info = args[0].b.addr; 72 mem_object = args[1].o; 73 74 qcomtee_mem_object_map(mem_object, &map_object, 75 &map_info->paddr, &map_info->len, 76 &map_info->perms); 77 78 args[2].o = map_object; 79 /* One output object; pass it for cleanup to notify. */ 80 oic->data = map_object; 81 82 qcomtee_object_put(mem_object); 83 84 break; 85 default: 86 err = -EINVAL; 87 } 88 89 return err; 90 } 91 92 /* Called after submitting the callback response. */ 93 static void qcomtee_primordial_obj_notify(struct qcomtee_object_invoke_ctx *oic, 94 struct qcomtee_object *unused, 95 int err) 96 { 97 struct qcomtee_object *object = oic->data; 98 99 /* If err, QTEE did not obtain mapping object. Drop it. */ 100 if (object && err) 101 qcomtee_object_put(object); 102 } 103 104 static struct qcomtee_object_operations qcomtee_primordial_obj_ops = { 105 .dispatch = qcomtee_primordial_obj_dispatch, 106 .notify = qcomtee_primordial_obj_notify, 107 }; 108 109 struct qcomtee_object qcomtee_primordial_object = { 110 .name = "primordial", 111 .object_type = QCOMTEE_OBJECT_TYPE_CB, 112 .ops = &qcomtee_primordial_obj_ops 113 }; 114