xref: /optee_os/core/pta/rtc.c (revision 4853708302832b19541c9b9ae4b79171319a3f39)
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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
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
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 
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 
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 
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