1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2014, STMicroelectronics International N.V.
4  * All rights reserved.
5  */
6 
7 #include <ta_sims.h>
8 #include <tee_api.h>
9 
10 #define TA_SIMS_MAX_STORAGE 4
11 
12 struct sims_bucket {
13 	uint32_t size;
14 	void *data;
15 };
16 
17 struct sims_session {
18 	TEE_TASessionHandle sess;
19 	uint32_t counter;
20 	uint32_t array[2048];
21 };
22 
23 static struct sims_bucket storage[TA_SIMS_MAX_STORAGE] = { {0} };
24 
25 static uint32_t counter;
26 
sims_open_ta_session(void * session_context,uint32_t param_types,TEE_Param params[4])27 TEE_Result sims_open_ta_session(void *session_context, uint32_t param_types,
28 				TEE_Param params[4])
29 {
30 	TEE_UUID *uuid = NULL;
31 	TEE_Result res = TEE_SUCCESS;
32 	TEE_TASessionHandle sess = TEE_HANDLE_NULL;
33 	uint32_t ret_orig = 0;
34 	struct sims_session *ctx = (struct sims_session *)session_context;
35 
36 	if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
37 					   TEE_PARAM_TYPE_NONE,
38 					   TEE_PARAM_TYPE_NONE,
39 					   TEE_PARAM_TYPE_NONE))
40 		return TEE_ERROR_BAD_PARAMETERS;
41 
42 	if (params[0].memref.size != sizeof(*uuid))
43 		return TEE_ERROR_BAD_PARAMETERS;
44 
45 	uuid = TEE_Malloc(sizeof(*uuid), TEE_MALLOC_FILL_ZERO);
46 	if (!uuid)
47 		return TEE_ERROR_OUT_OF_MEMORY;
48 
49 	TEE_MemMove(uuid, params[0].memref.buffer, params[0].memref.size);
50 
51 	res = TEE_OpenTASession(uuid, TEE_TIMEOUT_INFINITE, 0, NULL,
52 				&sess, &ret_orig);
53 	TEE_Free(uuid);
54 	if (res != TEE_SUCCESS)
55 		return res;
56 
57 	ctx->sess = sess;
58 	ctx->counter++;
59 
60 	return TEE_SUCCESS;
61 }
62 
sims_open_session(void ** ctx)63 TEE_Result sims_open_session(void **ctx)
64 {
65 	struct sims_session *context =
66 	    TEE_Malloc(sizeof(struct sims_session), TEE_MALLOC_FILL_ZERO);
67 
68 	if (context == NULL)
69 		return TEE_ERROR_OUT_OF_MEMORY;
70 
71 	context->sess = TEE_HANDLE_NULL;
72 	context->counter = counter;
73 	*ctx = context;
74 
75 	counter++;
76 
77 	return TEE_SUCCESS;
78 }
79 
sims_close_session(void * ctx)80 void sims_close_session(void *ctx)
81 {
82 	TEE_TASessionHandle sess = ((struct sims_session *)ctx)->sess;
83 
84 	if (sess != TEE_HANDLE_NULL)
85 		TEE_CloseTASession(sess);
86 
87 	TEE_Free(ctx);
88 }
89 
sims_read(uint32_t param_types,TEE_Param params[4])90 TEE_Result sims_read(uint32_t param_types, TEE_Param params[4])
91 {
92 	uint32_t index = 0;
93 	void *p = NULL;
94 
95 	if (param_types !=
96 	    TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
97 			    TEE_PARAM_TYPE_MEMREF_OUTPUT, 0, 0))
98 		return TEE_ERROR_BAD_PARAMETERS;
99 
100 	index = params[0].value.a;
101 	if (index >= TA_SIMS_MAX_STORAGE)
102 		return TEE_ERROR_BAD_PARAMETERS;
103 
104 	if (storage[index].size > params[1].memref.size)
105 		return TEE_ERROR_OVERFLOW;
106 
107 	p = TEE_Malloc(16000, 0);
108 	if (p == NULL)
109 		return TEE_ERROR_OUT_OF_MEMORY;
110 
111 	TEE_MemMove(params[1].memref.buffer, storage[index].data,
112 		    params[1].memref.size);
113 
114 	TEE_Free(p);
115 
116 	return TEE_SUCCESS;
117 }
118 
sims_write(uint32_t param_types,TEE_Param params[4])119 TEE_Result sims_write(uint32_t param_types, TEE_Param params[4])
120 {
121 	uint32_t index = 0;
122 
123 	if (param_types !=
124 	    TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
125 			    TEE_PARAM_TYPE_MEMREF_INPUT, 0, 0))
126 		return TEE_ERROR_BAD_PARAMETERS;
127 
128 	index = params[0].value.a;
129 	if (index >= TA_SIMS_MAX_STORAGE)
130 		return TEE_ERROR_BAD_PARAMETERS;
131 
132 	if (storage[index].data != NULL)
133 		TEE_Free(storage[index].data);
134 
135 	storage[index].data = TEE_Malloc(params[1].memref.size, 0);
136 	if (storage[index].data == NULL) {
137 		storage[index].size = 0;
138 		return TEE_ERROR_OUT_OF_MEMORY;
139 	}
140 	storage[index].size = params[1].memref.size;
141 
142 	TEE_MemMove(storage[index].data, params[1].memref.buffer,
143 		    params[1].memref.size);
144 
145 	return TEE_SUCCESS;
146 }
147 
sims_get_counter(void * session_context,uint32_t param_types,TEE_Param params[4])148 TEE_Result sims_get_counter(void *session_context, uint32_t param_types,
149 			    TEE_Param params[4])
150 {
151 	struct sims_session *ctx = (struct sims_session *)session_context;
152 
153 	if (param_types !=
154 	    TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, 0, 0, 0))
155 		return TEE_ERROR_BAD_PARAMETERS;
156 
157 	params[0].value.a = ctx->counter;
158 
159 	return TEE_SUCCESS;
160 }
161 
sims_entry_panic(void * session_context,uint32_t param_types,TEE_Param params[4])162 TEE_Result sims_entry_panic(void *session_context, uint32_t param_types,
163 			    TEE_Param params[4])
164 {
165 	uint32_t ret_orig = 0;
166 	TEE_Result res = TEE_SUCCESS;
167 	struct sims_session *ctx = (struct sims_session *)session_context;
168 
169 	if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
170 					   TEE_PARAM_TYPE_NONE,
171 					   TEE_PARAM_TYPE_NONE,
172 					   TEE_PARAM_TYPE_NONE))
173 		return TEE_ERROR_BAD_PARAMETERS;
174 
175 	if (params[0].memref.buffer && params[0].memref.size) {
176 		res = sims_open_ta_session(session_context,
177 					   param_types, params);
178 		if (res != TEE_SUCCESS)
179 			return res;
180 
181 		params[0].memref.buffer = NULL;
182 		params[0].memref.size = 0;
183 
184 		/* Trigger panic to remote TA */
185 		(void)TEE_InvokeTACommand(ctx->sess, TEE_TIMEOUT_INFINITE,
186 					  TA_SIMS_CMD_PANIC,
187 					  param_types, params,
188 					  &ret_orig);
189 	} else {
190 		TEE_Panic(0xbeef); /* Trigger panic to current TA */
191 	}
192 
193 	return TEE_SUCCESS;
194 }
195