1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2018, Linaro Limited
4  */
5 
6 #include <common.h>
7 #include <log.h>
8 #include <malloc.h>
9 #include <tee.h>
10 #include <linux/types.h>
11 
12 #include "optee_msg.h"
13 #include "optee_msg_supplicant.h"
14 #include "optee_private.h"
15 #include "optee_smc.h"
16 
cmd_shm_alloc(struct udevice * dev,struct optee_msg_arg * arg,void ** page_list)17 static void cmd_shm_alloc(struct udevice *dev, struct optee_msg_arg *arg,
18 			  void **page_list)
19 {
20 	int rc;
21 	struct tee_shm *shm;
22 	void *pl;
23 	u64 ph_ptr;
24 
25 	arg->ret_origin = TEE_ORIGIN_COMMS;
26 
27 	if (arg->num_params != 1 ||
28 	    arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_VALUE_INPUT) {
29 		arg->ret = TEE_ERROR_BAD_PARAMETERS;
30 		return;
31 	}
32 
33 	rc = __tee_shm_add(dev, 0, NULL, arg->params[0].u.value.b,
34 			   TEE_SHM_REGISTER | TEE_SHM_ALLOC, &shm);
35 	if (rc) {
36 		if (rc == -ENOMEM)
37 			arg->ret = TEE_ERROR_OUT_OF_MEMORY;
38 		else
39 			arg->ret = TEE_ERROR_GENERIC;
40 		return;
41 	}
42 
43 	pl = optee_alloc_and_init_page_list(shm->addr, shm->size, &ph_ptr);
44 	if (!pl) {
45 		arg->ret = TEE_ERROR_OUT_OF_MEMORY;
46 		tee_shm_free(shm);
47 		return;
48 	}
49 
50 	*page_list = pl;
51 	arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT |
52 			      OPTEE_MSG_ATTR_NONCONTIG;
53 	arg->params[0].u.tmem.buf_ptr = ph_ptr;
54 	arg->params[0].u.tmem.size = shm->size;
55 	arg->params[0].u.tmem.shm_ref = (ulong)shm;
56 	arg->ret = TEE_SUCCESS;
57 }
58 
cmd_shm_free(struct optee_msg_arg * arg)59 static void cmd_shm_free(struct optee_msg_arg *arg)
60 {
61 	arg->ret_origin = TEE_ORIGIN_COMMS;
62 
63 	if (arg->num_params != 1 ||
64 	    arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_VALUE_INPUT) {
65 		arg->ret = TEE_ERROR_BAD_PARAMETERS;
66 		return;
67 	}
68 
69 	tee_shm_free((struct tee_shm *)(ulong)arg->params[0].u.value.b);
70 	arg->ret = TEE_SUCCESS;
71 }
72 
optee_suppl_cmd(struct udevice * dev,struct tee_shm * shm_arg,void ** page_list)73 void optee_suppl_cmd(struct udevice *dev, struct tee_shm *shm_arg,
74 		     void **page_list)
75 {
76 	struct optee_msg_arg *arg = shm_arg->addr;
77 
78 	switch (arg->cmd) {
79 	case OPTEE_MSG_RPC_CMD_SHM_ALLOC:
80 		cmd_shm_alloc(dev, arg, page_list);
81 		break;
82 	case OPTEE_MSG_RPC_CMD_SHM_FREE:
83 		cmd_shm_free(arg);
84 		break;
85 	case OPTEE_MSG_RPC_CMD_FS:
86 		debug("REE FS storage isn't available\n");
87 		arg->ret = TEE_ERROR_STORAGE_NOT_AVAILABLE;
88 		break;
89 	case OPTEE_MSG_RPC_CMD_RPMB:
90 		optee_suppl_cmd_rpmb(dev, arg);
91 		break;
92 	case OPTEE_MSG_RPC_CMD_I2C_TRANSFER:
93 		optee_suppl_cmd_i2c_transfer(arg);
94 		break;
95 	default:
96 		arg->ret = TEE_ERROR_NOT_IMPLEMENTED;
97 	}
98 
99 	arg->ret_origin = TEE_ORIGIN_COMMS;
100 }
101