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