1 /*
2 * Copyright (C) 2022 Huawei Technologies Co., Ltd.
3 * Licensed under the Mulan PSL v2.
4 * You can use this software according to the terms and conditions of the Mulan PSL v2.
5 * You may obtain a copy of Mulan PSL v2 at:
6 * http://license.coscl.org.cn/MulanPSL2
7 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
8 * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
9 * PURPOSE.
10 * See the Mulan PSL v2 for more details.
11 */
12 #include <sys_timer.h>
13 #include <tee_log.h>
14 #include <tee_time_adapt.h>
15 #include <tee_misc.h>
16 #include <time.h>
17 #include <tee_time_sys.h>
18
19 #define is_leap_year(year) ((((year) % 4 == 0) && ((year) % 100 != 0)) || ((year) % 400 == 0))
20 #define leap_days_get(year) (((year) / 4) - ((year) / 100) + ((year) / 400))
21
22 static const uint32_t g_mon_lengths[][MONSPERYEAR] = {
23 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
24 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
25 };
26 static const uint32_t g_year_lengths[] = { DAYSPERNYEAR, DAYSPERLYEAR };
27
tee_timer_init(void)28 int tee_timer_init(void)
29 {
30 struct timer_ops_t *time_ops = NULL;
31 time_ops = get_time_ops();
32 if (time_ops == NULL || time_ops->tee_timer_init == NULL)
33 return TMR_OK;
34
35 return time_ops->tee_timer_init();
36 }
37
increment_overflow(uint32_t * year,uint32_t carry)38 static uint32_t increment_overflow(uint32_t *year, uint32_t carry)
39 {
40 if (carry > (UINT_MAX - *year)) {
41 tloge("overflow, year=%u, carry=%u\n", *year, carry);
42 return TMR_ERR;
43 }
44
45 *year += carry;
46 return TMR_OK;
47 }
48
get_days_and_year(uint32_t * days,uint32_t * year)49 static uint32_t get_days_and_year(uint32_t *days, uint32_t *year)
50 {
51 uint32_t ret;
52 uint32_t new_year;
53 uint32_t leap_days;
54 uint32_t carry_over;
55
56 while (*days >= g_year_lengths[is_leap_year(*year)]) {
57 carry_over = *days / DAYSPERLYEAR;
58 if (carry_over == 0)
59 carry_over = 1;
60
61 new_year = *year;
62 ret = increment_overflow(&new_year, carry_over);
63 if (ret != TMR_OK)
64 return TMR_ERR;
65
66 leap_days = leap_days_get(new_year - 1) - leap_days_get(*year - 1);
67 if (new_year < *year)
68 return TMR_ERR;
69 *days -= (new_year - *year) * DAYSPERNYEAR;
70 *days -= leap_days;
71 *year = new_year;
72 }
73
74 return TMR_OK;
75 }
76
gen_sys_date_time(const uint32_t rtc_time,struct tee_date_t * time)77 void gen_sys_date_time(const uint32_t rtc_time, struct tee_date_t *time)
78 {
79 uint32_t seconds;
80 uint32_t tdays;
81 uint32_t idays;
82 uint32_t rem_secs;
83 uint32_t year;
84 const uint32_t *ip = NULL;
85 uint32_t ret;
86
87 if (time == NULL) {
88 tloge("Error:time is null\n");
89 return;
90 }
91
92 seconds = rtc_time;
93 year = EPOCH_YEAR;
94 tdays = seconds / SECSPERDAY;
95 rem_secs = seconds - tdays * SECSPERDAY;
96
97 ret = get_days_and_year(&tdays, &year);
98 if (ret != TMR_OK) {
99 tloge("failed to get the day and year\n");
100 return;
101 }
102
103 time->month = 0;
104 idays = tdays;
105 time->year = (int32_t)year;
106 time->hour = (int32_t)(rem_secs / SECSPERHOUR);
107 rem_secs %= SECSPERHOUR;
108 time->min = (int32_t)(rem_secs / SECSPERMIN);
109 time->seconds = (int32_t)(rem_secs % SECSPERMIN);
110 ip = g_mon_lengths[is_leap_year(year)];
111
112 for (int i = 0; i < MONSPERYEAR; i++) {
113 time->month++;
114 if (idays < ip[i])
115 break;
116 idays -= ip[i];
117 }
118
119 time->day = (int32_t)(idays + 1);
120 }
121
tee_localtime_r(const time_t * restrict t,struct tm * restrict value)122 struct tm *tee_localtime_r(const time_t *restrict t, struct tm *restrict value)
123 {
124 tee_date_time_kernel date_time;
125
126 if ((value == NULL) || (t == NULL))
127 return NULL;
128
129 gen_sys_date_time((uint32_t)*t, &date_time);
130
131 /*
132 * Shift tee_date_time_kernel to libc struct tm
133 * tm_year: Year - 1900, that's why we minus 1900 here.
134 * tm_mon: Month (0-11), that's why we minus 1 here.
135 * tm_wday: Days of the week, has not implemented yet(could not get from date_time).
136 * tm_yday: Days in the year, has not implemented yet(could not get from date_time).
137 */
138 if (date_time.year == 0 || date_time.month == 0) {
139 tloge("invalid parameters, please check\n");
140 return NULL;
141 }
142
143 value->tm_year = date_time.year - 1900; /* start year 1900 */
144 value->tm_mon = date_time.month - 1;
145 value->tm_mday = date_time.day;
146 value->tm_hour = date_time.hour;
147 value->tm_min = date_time.min;
148 value->tm_sec = date_time.seconds;
149 value->tm_wday = 0;
150 value->tm_yday = 0;
151 value->tm_isdst = 0;
152 value->__tm_gmtoff = 0;
153 value->__tm_zone = NULL;
154
155 return value;
156 }
157
__localtime_r(const time_t * restrict t,struct tm * restrict value)158 struct tm *__localtime_r(const time_t *restrict t, struct tm *restrict value)
159 {
160 struct tm *tmp = NULL;
161 #ifdef __LP64__
162 /*
163 * Reject time_t values whose year would overflow int because
164 * __secs_to_zone cannot safely handle them.
165 */
166 if ((t != NULL) && ((*t < INT_MIN * MAX_SECONDS_PER_YEAR) || (*t > INT_MAX * MAX_SECONDS_PER_YEAR)))
167 return NULL;
168 #endif
169
170 if (t == NULL || value == NULL)
171 return NULL;
172
173 tmp = tee_localtime_r(t, value);
174 if (tmp == NULL) {
175 tloge("localtime: get value is NULL\n");
176 return NULL;
177 }
178 return value;
179 }
180
localtime(const time_t * t)181 struct tm *localtime(const time_t *t)
182 {
183 static struct tm value;
184 return __localtime_r(t, &value);
185 }
186
get_sys_rtc_time(TEE_Time * time)187 void get_sys_rtc_time(TEE_Time *time)
188 {
189 struct timer_ops_t *time_ops = NULL;
190 if (time == NULL) {
191 tloge("invalid param\n");
192 return;
193 }
194
195 time_ops = get_time_ops();
196 if (time_ops == NULL)
197 return;
198
199 time_ops->get_sys_rtc_time(time);
200 }
201
get_sys_date_time(tee_date_time_kernel * time_date)202 void get_sys_date_time(tee_date_time_kernel *time_date)
203 {
204 TEE_Time time;
205 get_sys_rtc_time(&time);
206 time.seconds += TIME_ZONE_EIGHT * SECSPERHOUR; /* CST */
207 if (time_date != NULL) {
208 gen_sys_date_time(time.seconds, time_date);
209 time_date->millis = time.millis;
210 }
211 }
212
adjust_sys_time(const struct tee_time_t * time)213 uint32_t adjust_sys_time(const struct tee_time_t *time)
214 {
215 struct timer_ops_t *time_ops = NULL;
216 if (time == NULL) {
217 tloge("invalid param\n");
218 return TMR_ERR;
219 }
220
221 time_ops = get_time_ops();
222 if (time_ops == NULL)
223 return TMR_OK;
224
225 return time_ops->adjust_sys_time(time);
226 }
227
release_timer_event(const TEE_UUID * uuid)228 void release_timer_event(const TEE_UUID *uuid)
229 {
230 struct timer_ops_t *time_ops = NULL;
231 if (uuid == NULL) {
232 tloge("invalid param\n");
233 return;
234 }
235
236 time_ops = get_time_ops();
237 if (time_ops == NULL)
238 return;
239
240 return time_ops->release_timer_event(uuid);
241 }
242
set_ta_timer_permission(const TEE_UUID * uuid,uint64_t permission)243 int32_t set_ta_timer_permission(const TEE_UUID *uuid, uint64_t permission)
244 {
245 struct timer_ops_t *time_ops = NULL;
246 if (uuid == NULL) {
247 tloge("invalid param\n");
248 return TMR_ERR;
249 }
250
251 time_ops = get_time_ops();
252 if (time_ops == NULL)
253 return TMR_ERR;
254
255 return time_ops->set_ta_timer_permission(uuid, permission);
256 }
257
get_ree_time_str(char * time_str,uint32_t time_str_len)258 void get_ree_time_str(char *time_str, uint32_t time_str_len)
259 {
260 int32_t ret;
261
262 if ((time_str == NULL) || (time_str_len == 0)) {
263 tloge("invalid param\n");
264 return;
265 }
266
267 ret = get_time_of_data(NULL, NULL, time_str, time_str_len);
268 if (ret != TMR_OK)
269 tloge("get time of data failed\n");
270 }
271
tee_read_time_stamp(void)272 uint64_t tee_read_time_stamp(void)
273 {
274 struct timer_ops_t *time_ops = NULL;
275 time_ops = get_time_ops();
276 if (time_ops == NULL)
277 return TMR_ERR;
278
279 return time_ops->read_time_stamp();
280 }
281