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