1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright (C) 2018, Linaro Limited
4 * Copyright (c) 2021, EPAM Systems. All rights reserved.
5 * Copyright (c) 2022, Microchip
6 *
7 */
8
9 #include <drivers/rtc.h>
10 #include <kernel/pseudo_ta.h>
11 #include <pta_rtc.h>
12 #include <string.h>
13 #include <tee_api_defines.h>
14 #include <tee_api_defines_extensions.h>
15
16 #define PTA_NAME "rtc.pta"
17
rtc_pta_copy_time_from_optee(struct pta_rtc_time * pta_time,struct optee_rtc_time * optee_time)18 static void rtc_pta_copy_time_from_optee(struct pta_rtc_time *pta_time,
19 struct optee_rtc_time *optee_time)
20 {
21 pta_time->tm_sec = optee_time->tm_sec;
22 pta_time->tm_min = optee_time->tm_min;
23 pta_time->tm_hour = optee_time->tm_hour;
24 pta_time->tm_mday = optee_time->tm_mday;
25 pta_time->tm_mon = optee_time->tm_mon;
26 pta_time->tm_year = optee_time->tm_year;
27 pta_time->tm_wday = optee_time->tm_wday;
28 }
29
rtc_pta_copy_time_to_optee(struct optee_rtc_time * optee_time,struct pta_rtc_time * pta_time)30 static void rtc_pta_copy_time_to_optee(struct optee_rtc_time *optee_time,
31 struct pta_rtc_time *pta_time)
32 {
33 optee_time->tm_sec = pta_time->tm_sec;
34 optee_time->tm_min = pta_time->tm_min;
35 optee_time->tm_hour = pta_time->tm_hour;
36 optee_time->tm_mday = pta_time->tm_mday;
37 optee_time->tm_mon = pta_time->tm_mon;
38 optee_time->tm_year = pta_time->tm_year;
39 optee_time->tm_wday = pta_time->tm_wday;
40 }
41
rtc_pta_copy_alarm_from_optee(struct pta_rtc_alarm * pta_alarm,struct optee_rtc_alarm * optee_alarm)42 static void rtc_pta_copy_alarm_from_optee(struct pta_rtc_alarm *pta_alarm,
43 struct optee_rtc_alarm *optee_alarm)
44 {
45 pta_alarm->enabled = optee_alarm->enabled;
46 pta_alarm->pending = optee_alarm->pending;
47 rtc_pta_copy_time_from_optee(&pta_alarm->time,
48 &optee_alarm->time);
49 }
50
rtc_pta_copy_alarm_to_optee(struct optee_rtc_alarm * optee_alarm,struct pta_rtc_alarm * pta_alarm)51 static void rtc_pta_copy_alarm_to_optee(struct optee_rtc_alarm *optee_alarm,
52 struct pta_rtc_alarm *pta_alarm)
53 {
54 optee_alarm->enabled = pta_alarm->enabled;
55 optee_alarm->pending = pta_alarm->pending;
56 rtc_pta_copy_time_to_optee(&optee_alarm->time,
57 &pta_alarm->time);
58 }
59
rtc_pta_get_time(uint32_t types,TEE_Param params[TEE_NUM_PARAMS])60 static TEE_Result rtc_pta_get_time(uint32_t types,
61 TEE_Param params[TEE_NUM_PARAMS])
62 {
63 TEE_Result res = TEE_ERROR_GENERIC;
64 struct optee_rtc_time time = { };
65 struct pta_rtc_time *pta_time = NULL;
66
67 if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT,
68 TEE_PARAM_TYPE_NONE,
69 TEE_PARAM_TYPE_NONE,
70 TEE_PARAM_TYPE_NONE))
71 return TEE_ERROR_BAD_PARAMETERS;
72
73 if (!IS_ALIGNED_WITH_TYPE(params[0].memref.buffer, typeof(*pta_time)))
74 return TEE_ERROR_BAD_PARAMETERS;
75
76 pta_time = params[0].memref.buffer;
77 if (!pta_time || params[0].memref.size != sizeof(*pta_time))
78 return TEE_ERROR_BAD_PARAMETERS;
79
80 res = rtc_get_time(&time);
81 if (res)
82 return res;
83
84 rtc_pta_copy_time_from_optee(pta_time, &time);
85
86 return TEE_SUCCESS;
87 }
88
rtc_pta_set_time(uint32_t types,TEE_Param params[TEE_NUM_PARAMS])89 static TEE_Result rtc_pta_set_time(uint32_t types,
90 TEE_Param params[TEE_NUM_PARAMS])
91 {
92 struct optee_rtc_time time = { };
93 struct pta_rtc_time *pta_time = NULL;
94
95 if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
96 TEE_PARAM_TYPE_NONE,
97 TEE_PARAM_TYPE_NONE,
98 TEE_PARAM_TYPE_NONE))
99 return TEE_ERROR_BAD_PARAMETERS;
100
101 if (!IS_ALIGNED_WITH_TYPE(params[0].memref.buffer, typeof(*pta_time)))
102 return TEE_ERROR_BAD_PARAMETERS;
103
104 pta_time = params[0].memref.buffer;
105 if (!pta_time || params[0].memref.size != sizeof(*pta_time))
106 return TEE_ERROR_BAD_PARAMETERS;
107
108 rtc_pta_copy_time_to_optee(&time, pta_time);
109
110 return rtc_set_time(&time);
111 }
112
rtc_pta_set_offset(uint32_t types,TEE_Param params[TEE_NUM_PARAMS])113 static TEE_Result rtc_pta_set_offset(uint32_t types,
114 TEE_Param params[TEE_NUM_PARAMS])
115 {
116 if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
117 TEE_PARAM_TYPE_NONE,
118 TEE_PARAM_TYPE_NONE,
119 TEE_PARAM_TYPE_NONE))
120 return TEE_ERROR_BAD_PARAMETERS;
121
122 return rtc_set_offset((int32_t)params[0].value.a);
123 }
124
rtc_pta_get_offset(uint32_t types,TEE_Param params[TEE_NUM_PARAMS])125 static TEE_Result rtc_pta_get_offset(uint32_t types,
126 TEE_Param params[TEE_NUM_PARAMS])
127 {
128 TEE_Result res = TEE_ERROR_GENERIC;
129 long offset = 0;
130
131 if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT,
132 TEE_PARAM_TYPE_NONE,
133 TEE_PARAM_TYPE_NONE,
134 TEE_PARAM_TYPE_NONE))
135 return TEE_ERROR_BAD_PARAMETERS;
136
137 res = rtc_get_offset(&offset);
138 if (res)
139 return res;
140
141 if (offset > INT32_MAX || offset < INT32_MIN)
142 return TEE_ERROR_OVERFLOW;
143
144 params[0].value.a = (uint32_t)offset;
145
146 return res;
147 }
148
rtc_pta_read_alarm(uint32_t types,TEE_Param params[TEE_NUM_PARAMS])149 static TEE_Result rtc_pta_read_alarm(uint32_t types,
150 TEE_Param params[TEE_NUM_PARAMS])
151 {
152 TEE_Result res = TEE_ERROR_GENERIC;
153 struct optee_rtc_alarm alarm = { };
154 struct pta_rtc_alarm *pta_alarm = NULL;
155
156 if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT,
157 TEE_PARAM_TYPE_NONE,
158 TEE_PARAM_TYPE_NONE,
159 TEE_PARAM_TYPE_NONE))
160 return TEE_ERROR_BAD_PARAMETERS;
161
162 if (!IS_ALIGNED_WITH_TYPE(params[0].memref.buffer, typeof(*pta_alarm)))
163 return TEE_ERROR_BAD_PARAMETERS;
164
165 pta_alarm = params[0].memref.buffer;
166 if (!pta_alarm || params[0].memref.size != sizeof(*pta_alarm))
167 return TEE_ERROR_BAD_PARAMETERS;
168
169 res = rtc_read_alarm(&alarm);
170 if (!res)
171 rtc_pta_copy_alarm_from_optee(pta_alarm, &alarm);
172
173 return res;
174 }
175
rtc_pta_set_alarm(uint32_t types,TEE_Param params[TEE_NUM_PARAMS])176 static TEE_Result rtc_pta_set_alarm(uint32_t types,
177 TEE_Param params[TEE_NUM_PARAMS])
178 {
179 struct optee_rtc_alarm alarm = { };
180 struct pta_rtc_alarm *pta_alarm = NULL;
181
182 if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
183 TEE_PARAM_TYPE_NONE,
184 TEE_PARAM_TYPE_NONE,
185 TEE_PARAM_TYPE_NONE))
186 return TEE_ERROR_BAD_PARAMETERS;
187
188 if (!IS_ALIGNED_WITH_TYPE(params[0].memref.buffer, typeof(*pta_alarm)))
189 return TEE_ERROR_BAD_PARAMETERS;
190
191 pta_alarm = params[0].memref.buffer;
192 if (!pta_alarm || params[0].memref.size != sizeof(*pta_alarm))
193 return TEE_ERROR_BAD_PARAMETERS;
194
195 rtc_pta_copy_alarm_to_optee(&alarm, pta_alarm);
196
197 return rtc_set_alarm(&alarm);
198 }
199
rtc_pta_enable_alarm(uint32_t types,TEE_Param params[TEE_NUM_PARAMS])200 static TEE_Result rtc_pta_enable_alarm(uint32_t types,
201 TEE_Param params[TEE_NUM_PARAMS])
202 {
203 if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
204 TEE_PARAM_TYPE_NONE,
205 TEE_PARAM_TYPE_NONE,
206 TEE_PARAM_TYPE_NONE))
207 return TEE_ERROR_BAD_PARAMETERS;
208
209 if (params[0].value.a != 0 && params[0].value.a != 1)
210 return TEE_ERROR_BAD_PARAMETERS;
211
212 return rtc_enable_alarm((bool)params[0].value.a);
213 }
214
rtc_pta_wait_alarm(uint32_t types,TEE_Param params[TEE_NUM_PARAMS])215 static TEE_Result rtc_pta_wait_alarm(uint32_t types,
216 TEE_Param params[TEE_NUM_PARAMS])
217 {
218 TEE_Result res = TEE_ERROR_GENERIC;
219 enum rtc_wait_alarm_status alarm_status = RTC_WAIT_ALARM_RESET;
220
221 if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT,
222 TEE_PARAM_TYPE_NONE,
223 TEE_PARAM_TYPE_NONE,
224 TEE_PARAM_TYPE_NONE))
225 return TEE_ERROR_BAD_PARAMETERS;
226
227 res = rtc_wait_alarm(&alarm_status);
228 if (!res)
229 params[0].value.a = alarm_status;
230
231 return res;
232 }
233
234 static TEE_Result
rtc_pta_cancel_wait_alarm(uint32_t types,TEE_Param params[TEE_NUM_PARAMS]__unused)235 rtc_pta_cancel_wait_alarm(uint32_t types,
236 TEE_Param params[TEE_NUM_PARAMS] __unused)
237 {
238 if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE,
239 TEE_PARAM_TYPE_NONE,
240 TEE_PARAM_TYPE_NONE,
241 TEE_PARAM_TYPE_NONE))
242 return TEE_ERROR_BAD_PARAMETERS;
243
244 return rtc_cancel_wait_alarm();
245 }
246
247 static TEE_Result
rtc_pta_set_alarm_wakeup_status(uint32_t types,TEE_Param params[TEE_NUM_PARAMS])248 rtc_pta_set_alarm_wakeup_status(uint32_t types,
249 TEE_Param params[TEE_NUM_PARAMS])
250 {
251 if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
252 TEE_PARAM_TYPE_NONE,
253 TEE_PARAM_TYPE_NONE,
254 TEE_PARAM_TYPE_NONE))
255 return TEE_ERROR_BAD_PARAMETERS;
256
257 if (params[0].value.a != 0 && params[0].value.a != 1)
258 return TEE_ERROR_BAD_PARAMETERS;
259
260 return rtc_set_alarm_wakeup_status((bool)params[0].value.a);
261 }
262
rtc_pta_get_info(uint32_t types,TEE_Param params[TEE_NUM_PARAMS])263 static TEE_Result rtc_pta_get_info(uint32_t types,
264 TEE_Param params[TEE_NUM_PARAMS])
265 {
266 TEE_Result res = TEE_ERROR_GENERIC;
267 struct pta_rtc_info *info = NULL;
268 struct optee_rtc_time range_min = { };
269 struct optee_rtc_time range_max = { };
270 uint64_t features = 0;
271
272 if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT,
273 TEE_PARAM_TYPE_NONE,
274 TEE_PARAM_TYPE_NONE,
275 TEE_PARAM_TYPE_NONE))
276 return TEE_ERROR_BAD_PARAMETERS;
277
278 if (!IS_ALIGNED_WITH_TYPE(params[0].memref.buffer, typeof(*info)))
279 return TEE_ERROR_BAD_PARAMETERS;
280
281 info = params[0].memref.buffer;
282 if (!info || params[0].memref.size != sizeof(*info))
283 return TEE_ERROR_BAD_PARAMETERS;
284
285 memset(info, 0, sizeof(*info));
286
287 res = rtc_get_info(&features, &range_min, &range_max);
288 if (res)
289 return res;
290
291 info->version = PTA_RTC_INFO_VERSION;
292
293 if (features & RTC_CORRECTION_FEATURE)
294 info->features |= PTA_RTC_FEATURE_CORRECTION;
295 if (features & RTC_ALARM_FEATURE)
296 info->features |= PTA_RTC_FEATURE_ALARM;
297 if (features & RTC_WAKEUP_ALARM)
298 info->features |= PTA_RTC_FEATURE_WAKEUP_ALARM;
299
300 rtc_pta_copy_time_from_optee(&info->range_min, &range_min);
301 rtc_pta_copy_time_from_optee(&info->range_max, &range_max);
302
303 return TEE_SUCCESS;
304 }
305
open_session(uint32_t ptypes __unused,TEE_Param par[TEE_NUM_PARAMS]__unused,void ** session __unused)306 static TEE_Result open_session(uint32_t ptypes __unused,
307 TEE_Param par[TEE_NUM_PARAMS] __unused,
308 void **session __unused)
309 {
310 struct ts_session *ts = ts_get_current_session();
311 struct tee_ta_session *ta_session = to_ta_session(ts);
312
313 /* Only REE kernel is allowed to access RTC */
314 if (ta_session->clnt_id.login != TEE_LOGIN_REE_KERNEL)
315 return TEE_ERROR_ACCESS_DENIED;
316
317 return TEE_SUCCESS;
318 }
319
invoke_command(void * session __unused,uint32_t cmd,uint32_t ptypes,TEE_Param params[TEE_NUM_PARAMS])320 static TEE_Result invoke_command(void *session __unused,
321 uint32_t cmd, uint32_t ptypes,
322 TEE_Param params[TEE_NUM_PARAMS])
323 {
324 switch (cmd) {
325 case PTA_CMD_RTC_GET_INFO:
326 return rtc_pta_get_info(ptypes, params);
327 case PTA_CMD_RTC_GET_TIME:
328 return rtc_pta_get_time(ptypes, params);
329 case PTA_CMD_RTC_SET_TIME:
330 return rtc_pta_set_time(ptypes, params);
331 case PTA_CMD_RTC_GET_OFFSET:
332 return rtc_pta_get_offset(ptypes, params);
333 case PTA_CMD_RTC_SET_OFFSET:
334 return rtc_pta_set_offset(ptypes, params);
335 case PTA_CMD_RTC_READ_ALARM:
336 return rtc_pta_read_alarm(ptypes, params);
337 case PTA_CMD_RTC_SET_ALARM:
338 return rtc_pta_set_alarm(ptypes, params);
339 case PTA_CMD_RTC_ENABLE_ALARM:
340 return rtc_pta_enable_alarm(ptypes, params);
341 case PTA_CMD_RTC_WAIT_ALARM:
342 return rtc_pta_wait_alarm(ptypes, params);
343 case PTA_CMD_RTC_CANCEL_WAIT_ALARM:
344 return rtc_pta_cancel_wait_alarm(ptypes, params);
345 case PTA_CMD_RTC_SET_WAKE_ALARM_STATUS:
346 return rtc_pta_set_alarm_wakeup_status(ptypes, params);
347 default:
348 break;
349 }
350
351 return TEE_ERROR_NOT_IMPLEMENTED;
352 }
353
354 pseudo_ta_register(.uuid = PTA_RTC_UUID, .name = PTA_NAME,
355 .flags = PTA_DEFAULT_FLAGS | TA_FLAG_CONCURRENT |
356 TA_FLAG_DEVICE_ENUM,
357 .open_session_entry_point = open_session,
358 .invoke_command_entry_point = invoke_command);
359