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