at v6.19 113 lines 3.0 kB view raw
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. */ 28struct qcomtee_mapping_info { 29 u64 paddr; 30 u64 len; 31 u32 perms; 32} __packed; 33 34static int 35qcomtee_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. */ 93static 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 104static struct qcomtee_object_operations qcomtee_primordial_obj_ops = { 105 .dispatch = qcomtee_primordial_obj_dispatch, 106 .notify = qcomtee_primordial_obj_notify, 107}; 108 109struct qcomtee_object qcomtee_primordial_object = { 110 .name = "primordial", 111 .object_type = QCOMTEE_OBJECT_TYPE_CB, 112 .ops = &qcomtee_primordial_obj_ops 113};