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 TEE_Result rtc_pta_get_time(uint32_t types, 31 TEE_Param params[TEE_NUM_PARAMS]) 32 { 33 TEE_Result res = TEE_ERROR_GENERIC; 34 struct optee_rtc_time time = { }; 35 struct pta_rtc_time *pta_time = NULL; 36 37 if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT, 38 TEE_PARAM_TYPE_NONE, 39 TEE_PARAM_TYPE_NONE, 40 TEE_PARAM_TYPE_NONE)) 41 return TEE_ERROR_BAD_PARAMETERS; 42 43 if (!IS_ALIGNED_WITH_TYPE(params[0].memref.buffer, typeof(*pta_time))) 44 return TEE_ERROR_BAD_PARAMETERS; 45 46 pta_time = params[0].memref.buffer; 47 if (!pta_time || params[0].memref.size != sizeof(*pta_time)) 48 return TEE_ERROR_BAD_PARAMETERS; 49 50 res = rtc_get_time(&time); 51 if (res) 52 return res; 53 54 rtc_pta_copy_time_from_optee(pta_time, &time); 55 56 return TEE_SUCCESS; 57 } 58 59 static TEE_Result rtc_pta_set_time(uint32_t types, 60 TEE_Param params[TEE_NUM_PARAMS]) 61 { 62 struct optee_rtc_time time = { }; 63 struct pta_rtc_time *pta_time = NULL; 64 65 if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, 66 TEE_PARAM_TYPE_NONE, 67 TEE_PARAM_TYPE_NONE, 68 TEE_PARAM_TYPE_NONE)) 69 return TEE_ERROR_BAD_PARAMETERS; 70 71 if (!IS_ALIGNED_WITH_TYPE(params[0].memref.buffer, typeof(*pta_time))) 72 return TEE_ERROR_BAD_PARAMETERS; 73 74 pta_time = params[0].memref.buffer; 75 if (!pta_time || params[0].memref.size != sizeof(*pta_time)) 76 return TEE_ERROR_BAD_PARAMETERS; 77 78 time.tm_sec = pta_time->tm_sec; 79 time.tm_min = pta_time->tm_min; 80 time.tm_hour = pta_time->tm_hour; 81 time.tm_mday = pta_time->tm_mday; 82 time.tm_mon = pta_time->tm_mon; 83 time.tm_year = pta_time->tm_year; 84 time.tm_wday = pta_time->tm_wday; 85 86 return rtc_set_time(&time); 87 } 88 89 static TEE_Result rtc_pta_set_offset(uint32_t types, 90 TEE_Param params[TEE_NUM_PARAMS]) 91 { 92 if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 93 TEE_PARAM_TYPE_NONE, 94 TEE_PARAM_TYPE_NONE, 95 TEE_PARAM_TYPE_NONE)) 96 return TEE_ERROR_BAD_PARAMETERS; 97 98 return rtc_set_offset((int32_t)params[0].value.a); 99 } 100 101 static TEE_Result rtc_pta_get_offset(uint32_t types, 102 TEE_Param params[TEE_NUM_PARAMS]) 103 { 104 TEE_Result res = TEE_ERROR_GENERIC; 105 long offset = 0; 106 107 if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT, 108 TEE_PARAM_TYPE_NONE, 109 TEE_PARAM_TYPE_NONE, 110 TEE_PARAM_TYPE_NONE)) 111 return TEE_ERROR_BAD_PARAMETERS; 112 113 res = rtc_get_offset(&offset); 114 if (res) 115 return res; 116 117 if (offset > INT32_MAX || offset < INT32_MIN) 118 return TEE_ERROR_OVERFLOW; 119 120 params[0].value.a = (uint32_t)offset; 121 122 return res; 123 } 124 125 static TEE_Result rtc_pta_get_info(uint32_t types, 126 TEE_Param params[TEE_NUM_PARAMS]) 127 { 128 TEE_Result res = TEE_ERROR_GENERIC; 129 struct pta_rtc_info *info = NULL; 130 struct optee_rtc_time range_min = { }; 131 struct optee_rtc_time range_max = { }; 132 uint64_t features = 0; 133 134 if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT, 135 TEE_PARAM_TYPE_NONE, 136 TEE_PARAM_TYPE_NONE, 137 TEE_PARAM_TYPE_NONE)) 138 return TEE_ERROR_BAD_PARAMETERS; 139 140 if (!IS_ALIGNED_WITH_TYPE(params[0].memref.buffer, typeof(*info))) 141 return TEE_ERROR_BAD_PARAMETERS; 142 143 info = params[0].memref.buffer; 144 if (!info || params[0].memref.size != sizeof(*info)) 145 return TEE_ERROR_BAD_PARAMETERS; 146 147 memset(info, 0, sizeof(*info)); 148 149 res = rtc_get_info(&features, &range_min, &range_max); 150 if (res) 151 return res; 152 153 info->version = PTA_RTC_INFO_VERSION; 154 155 if (features & RTC_CORRECTION_FEATURE) 156 info->features |= PTA_RTC_FEATURE_CORRECTION; 157 158 rtc_pta_copy_time_from_optee(&info->range_min, &range_min); 159 rtc_pta_copy_time_from_optee(&info->range_max, &range_max); 160 161 return TEE_SUCCESS; 162 } 163 164 static TEE_Result open_session(uint32_t ptypes __unused, 165 TEE_Param par[TEE_NUM_PARAMS] __unused, 166 void **session __unused) 167 { 168 struct ts_session *ts = ts_get_current_session(); 169 struct tee_ta_session *ta_session = to_ta_session(ts); 170 171 /* Only REE kernel is allowed to access RTC */ 172 if (ta_session->clnt_id.login != TEE_LOGIN_REE_KERNEL) 173 return TEE_ERROR_ACCESS_DENIED; 174 175 return TEE_SUCCESS; 176 } 177 178 static TEE_Result invoke_command(void *session __unused, 179 uint32_t cmd, uint32_t ptypes, 180 TEE_Param params[TEE_NUM_PARAMS]) 181 { 182 switch (cmd) { 183 case PTA_CMD_RTC_GET_INFO: 184 return rtc_pta_get_info(ptypes, params); 185 case PTA_CMD_RTC_GET_TIME: 186 return rtc_pta_get_time(ptypes, params); 187 case PTA_CMD_RTC_SET_TIME: 188 return rtc_pta_set_time(ptypes, params); 189 case PTA_CMD_RTC_GET_OFFSET: 190 return rtc_pta_get_offset(ptypes, params); 191 case PTA_CMD_RTC_SET_OFFSET: 192 return rtc_pta_set_offset(ptypes, params); 193 default: 194 break; 195 } 196 197 return TEE_ERROR_NOT_IMPLEMENTED; 198 } 199 200 pseudo_ta_register(.uuid = PTA_RTC_UUID, .name = PTA_NAME, 201 .flags = PTA_DEFAULT_FLAGS | TA_FLAG_CONCURRENT | 202 TA_FLAG_DEVICE_ENUM, 203 .open_session_entry_point = open_session, 204 .invoke_command_entry_point = invoke_command); 205