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