arm64: dts: rk3399-mid: rk818 enabled boost_otg fix ota vcc5v poweroff when susppend
[firefly-linux-kernel-4.4.55.git] / security / optee_linuxdriver / core / tee_kernel_api.c
1 /*
2  * Copyright (c) 2014, STMicroelectronics International N.V.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License Version 2 as
6  * published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  */
13 #include <linux/module.h>
14 #include <linux/device.h>
15 #include <linux/miscdevice.h>
16 #include <linux/io.h>
17 #include <linux/vmalloc.h>
18
19 #include "linux/tee_kernel_api.h"
20 #include "linux/tee_core.h"
21 #include "linux/tee_ioc.h"
22
23 #include "tee_core_priv.h"
24 #include "tee_shm.h"
25 #include "tee_supp_com.h"
26
27 #define TEE_TZ_DEVICE_NAME      "opteearmtz00"
28
29 static void reset_tee_cmd(struct tee_cmd_io *cmd)
30 {
31         memset(cmd, 0, sizeof(struct tee_cmd_io));
32         cmd->fd_sess = -1;
33         cmd->cmd = 0;
34         cmd->uuid = NULL;
35         cmd->origin = TEEC_ORIGIN_API;
36         cmd->err = TEEC_SUCCESS;
37         cmd->data = NULL;
38         cmd->data_size = 0;
39         cmd->op = NULL;
40 }
41
42 TEEC_Result TEEC_InitializeContext(const char *name, TEEC_Context *context)
43 {
44         struct tee *tee;
45         struct tee_context *ctx;
46         pr_cont("%s: > name=\"%s\"\n", __func__, name);
47
48         if (!context)
49                 return TEEC_ERROR_BAD_PARAMETERS;
50
51         context->fd = 0;
52
53         if (name == NULL)
54                 strncpy(context->devname, TEE_TZ_DEVICE_NAME,
55                         sizeof(context->devname));
56         else
57                 strncpy(context->devname, name, sizeof(context->devname));
58
59         tee = tee_get_tee(context->devname);
60         if (!tee) {
61                 pr_err("%s - can't get device [%s]\n", __func__, name);
62                 return TEEC_ERROR_BAD_PARAMETERS;
63         }
64
65         ctx = tee_context_create(tee);
66         if (IS_ERR_OR_NULL(ctx))
67                 return TEEC_ERROR_BAD_PARAMETERS;
68
69         ctx->usr_client = 0;
70
71         /* TODO fixme will not work on 64-bit platform */
72         context->fd = (int)(uintptr_t)ctx;
73         BUG_ON(ctx != (struct tee_context *)(uintptr_t)context->fd);
74
75         pr_cont("%s: < ctx=%p is created\n", __func__, (void *)ctx);
76         return TEEC_SUCCESS;
77 }
78 EXPORT_SYMBOL(TEEC_InitializeContext);
79
80 void TEEC_FinalizeContext(TEEC_Context *context)
81 {
82         if (!context || !context->fd) {
83                 pr_err("%s - can't release context %p:[%s]\n", __func__,
84                        context, (context
85                                  && context->devname) ? context->devname : "");
86                 return;
87         }
88         /* TODO fixme will not work on 64-bit platform */
89         tee_context_destroy((struct tee_context *)(uintptr_t)context->fd);
90         return;
91 }
92 EXPORT_SYMBOL(TEEC_FinalizeContext);
93
94 TEEC_Result TEEC_OpenSession(TEEC_Context *context,
95                              TEEC_Session *session,
96                              const TEEC_UUID *destination,
97                              uint32_t connectionMethod,
98                              const void *connectionData,
99                              TEEC_Operation *operation,
100                              uint32_t *return_origin)
101 {
102         TEEC_Operation dummy_op;
103         struct tee_cmd_io cmd;
104         struct tee_session *sess;
105         struct tee_context *ctx;
106
107         if (!operation) {
108                 /*
109                  * The code here exist because Global Platform API states that
110                  * it is allowed to give operation as a NULL pointer.
111                  * In kernel and secure world we in most cases don't want
112                  * this to be NULL, hence we use this dummy operation when
113                  * a client doesn't provide any operation.
114                  */
115                 memset(&dummy_op, 0, sizeof(TEEC_Operation));
116                 operation = &dummy_op;
117         }
118
119         if (!context || !session || !destination || !operation
120             || !return_origin)
121                 return TEEC_ERROR_BAD_PARAMETERS;
122
123         session->fd = 0;
124
125         /* TODO fixme will not work on 64-bit platform */
126         ctx = (struct tee_context *)(uintptr_t)context->fd;
127         reset_tee_cmd(&cmd);
128         cmd.op = operation;
129         cmd.uuid = (TEEC_UUID *) destination;
130
131         sess = tee_session_create_and_open(ctx, &cmd);
132         if (IS_ERR_OR_NULL(sess)) {
133                 if (cmd.origin)
134                         *return_origin = cmd.origin;
135                 else
136                         *return_origin = TEEC_ORIGIN_COMMS;
137                 if (cmd.err)
138                         return cmd.err;
139                 else
140                         return TEEC_ERROR_COMMUNICATION;
141         } else {
142                 *return_origin = cmd.origin;
143                 /* TODO fixme will not work on 64-bit platform */
144                 session->fd = (int)(uintptr_t)sess;
145                 BUG_ON(sess != (struct tee_session *)(uintptr_t)session->fd);
146                 return cmd.err;
147         }
148 }
149 EXPORT_SYMBOL(TEEC_OpenSession);
150
151 void TEEC_CloseSession(TEEC_Session *session)
152 {
153         if (session && session->fd) {
154                 /* TODO fixme will not work on 64-bit platform */
155                 struct tee_session *sess =
156                         (struct tee_session *)(uintptr_t)session->fd;
157                 tee_session_close_and_destroy(sess);
158         }
159 }
160 EXPORT_SYMBOL(TEEC_CloseSession);
161
162 TEEC_Result TEEC_InvokeCommand(TEEC_Session *session,
163                                uint32_t commandID,
164                                TEEC_Operation *operation,
165                                uint32_t *return_origin)
166 {
167         int ret = 0;
168         struct tee_cmd_io cmd;
169         struct tee_session *sess;
170
171         if (!session || !operation || !return_origin || !session->fd)
172                 return TEEC_ERROR_BAD_PARAMETERS;
173
174         /* TODO fixme will not work on 64-bit platform */
175         sess = (struct tee_session *)(uintptr_t)session->fd;
176         reset_tee_cmd(&cmd);
177         cmd.cmd = commandID;
178         cmd.op = operation;
179
180         ret = tee_session_invoke_be(sess, &cmd);
181         if (ret) {
182                 if (cmd.origin)
183                         *return_origin = cmd.origin;
184                 else
185                         *return_origin = TEEC_ORIGIN_COMMS;
186                 if (cmd.err)
187                         return cmd.err;
188                 else
189                         return TEEC_ERROR_COMMUNICATION;
190         } else {
191                 *return_origin = cmd.origin;
192                 return cmd.err;
193         }
194 }
195 EXPORT_SYMBOL(TEEC_InvokeCommand);
196
197 TEEC_Result TEEC_RegisterSharedMemory(TEEC_Context *context,
198                                       TEEC_SharedMemory *sharedMem)
199 {
200         if (!sharedMem)
201                 return TEEC_ERROR_BAD_PARAMETERS;
202
203         sharedMem->registered = 1;
204         return TEEC_SUCCESS;
205 }
206 EXPORT_SYMBOL(TEEC_RegisterSharedMemory);
207
208 TEEC_Result TEEC_AllocateSharedMemory(TEEC_Context *context,
209                                       TEEC_SharedMemory *shared_memory)
210 {
211         struct tee_shm_io shm_io;
212         int ret;
213         struct tee_shm *shm;
214
215         if (!context || !context->ctx || !shared_memory)
216                 return TEEC_ERROR_BAD_PARAMETERS;
217
218         shm_io.size = shared_memory->size;
219         shm_io.flags = shared_memory->flags | TEEC_MEM_KAPI;
220         ret = tee_shm_alloc_io(context->ctx, &shm_io);
221         if (ret) {
222                 pr_err("%s: tee_shm_alloc_io(%zd) failed\n", __func__,
223                        shared_memory->size);
224                 return TEEC_ERROR_OUT_OF_MEMORY;
225         }
226
227         shared_memory->registered = 0;
228         shared_memory->flags = shm_io.flags;
229         shared_memory->d.fd = shm_io.fd_shm;
230
231         shm = (struct tee_shm *)(long)shm_io.fd_shm;
232         shared_memory->buffer = shm->kaddr;
233
234         pr_debug("%s(%d) => fd=%d, kaddr=%p\n", __func__,
235                  shm_io.size, shm_io.fd_shm, (void *)shared_memory->buffer);
236
237         return TEEC_SUCCESS;
238 }
239 EXPORT_SYMBOL(TEEC_AllocateSharedMemory);
240
241 void TEEC_ReleaseSharedMemory(TEEC_SharedMemory *shared_memory)
242 {
243         struct tee_shm *shm;
244
245         if (!shared_memory || shared_memory->registered)
246                 return;
247
248         pr_debug("%s (vaddr = %p)\n", __func__, shared_memory->buffer);
249
250         shm = (struct tee_shm *)(long)shared_memory->d.fd;
251         tee_shm_free_io(shm);
252
253         shared_memory->buffer = NULL;
254         shared_memory->d.fd = 0;
255 }
256 EXPORT_SYMBOL(TEEC_ReleaseSharedMemory);