• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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