1*1bb92983SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause
2b0104773SPascal Brand /*
3b0104773SPascal Brand * Copyright (c) 2014, STMicroelectronics International N.V.
4b0104773SPascal Brand */
5b0104773SPascal Brand
6889dbbbfSVictor Chong #include <kernel/panic.h>
7889dbbbfSVictor Chong #include <kernel/tee_time.h>
8b0104773SPascal Brand #include <string.h>
9b0104773SPascal Brand #include <stdlib.h>
10b0104773SPascal Brand #include <utee_defines.h>
11b0104773SPascal Brand
12b0104773SPascal Brand struct tee_ta_time_offs {
13b0104773SPascal Brand TEE_UUID uuid;
14b0104773SPascal Brand TEE_Time offs;
15b0104773SPascal Brand bool positive;
16b0104773SPascal Brand };
17b0104773SPascal Brand
18b0104773SPascal Brand static struct tee_ta_time_offs *tee_time_offs;
19b0104773SPascal Brand static size_t tee_time_num_offs;
20b0104773SPascal Brand
tee_time_ta_get_offs(const TEE_UUID * uuid,const TEE_Time ** offs,bool * positive)21b0104773SPascal Brand static TEE_Result tee_time_ta_get_offs(const TEE_UUID *uuid,
22b0104773SPascal Brand const TEE_Time **offs, bool *positive)
23b0104773SPascal Brand {
24b0104773SPascal Brand size_t n;
25b0104773SPascal Brand
26b0104773SPascal Brand for (n = 0; n < tee_time_num_offs; n++) {
27b0104773SPascal Brand if (memcmp(uuid, &tee_time_offs[n].uuid, sizeof(TEE_UUID))
28b0104773SPascal Brand == 0) {
29b0104773SPascal Brand *offs = &tee_time_offs[n].offs;
30b0104773SPascal Brand *positive = tee_time_offs[n].positive;
31b0104773SPascal Brand return TEE_SUCCESS;
32b0104773SPascal Brand }
33b0104773SPascal Brand }
34b0104773SPascal Brand return TEE_ERROR_TIME_NOT_SET;
35b0104773SPascal Brand }
36b0104773SPascal Brand
tee_time_ta_set_offs(const TEE_UUID * uuid,const TEE_Time * offs,bool positive)37b0104773SPascal Brand static TEE_Result tee_time_ta_set_offs(const TEE_UUID *uuid,
38b0104773SPascal Brand const TEE_Time *offs, bool positive)
39b0104773SPascal Brand {
40b0104773SPascal Brand size_t n;
41b0104773SPascal Brand struct tee_ta_time_offs *o;
42b0104773SPascal Brand
43b0104773SPascal Brand for (n = 0; n < tee_time_num_offs; n++) {
44b0104773SPascal Brand if (memcmp(uuid, &tee_time_offs[n].uuid, sizeof(TEE_UUID))
45b0104773SPascal Brand == 0) {
46b0104773SPascal Brand tee_time_offs[n].offs = *offs;
47b0104773SPascal Brand tee_time_offs[n].positive = positive;
48b0104773SPascal Brand return TEE_SUCCESS;
49b0104773SPascal Brand }
50b0104773SPascal Brand }
51b0104773SPascal Brand
52b0104773SPascal Brand n = tee_time_num_offs + 1;
53592631d9SJens Wiklander o = realloc(tee_time_offs, n * sizeof(struct tee_ta_time_offs));
54592631d9SJens Wiklander if (!o)
55b0104773SPascal Brand return TEE_ERROR_OUT_OF_MEMORY;
56b0104773SPascal Brand tee_time_offs = o;
57b0104773SPascal Brand tee_time_offs[tee_time_num_offs].uuid = *uuid;
58b0104773SPascal Brand tee_time_offs[tee_time_num_offs].offs = *offs;
59b0104773SPascal Brand tee_time_offs[tee_time_num_offs].positive = positive;
60b0104773SPascal Brand tee_time_num_offs = n;
61b0104773SPascal Brand return TEE_SUCCESS;
62b0104773SPascal Brand }
63b0104773SPascal Brand
tee_time_get_ta_time(const TEE_UUID * uuid,TEE_Time * time)64b0104773SPascal Brand TEE_Result tee_time_get_ta_time(const TEE_UUID *uuid, TEE_Time *time)
65b0104773SPascal Brand {
66b0104773SPascal Brand TEE_Result res;
67b0104773SPascal Brand const TEE_Time *offs;
68b0104773SPascal Brand bool positive;
69b0104773SPascal Brand TEE_Time t;
70b0104773SPascal Brand TEE_Time t2;
71b0104773SPascal Brand
72b0104773SPascal Brand res = tee_time_ta_get_offs(uuid, &offs, &positive);
73b0104773SPascal Brand if (res != TEE_SUCCESS)
74b0104773SPascal Brand return res;
75b0104773SPascal Brand
76b0104773SPascal Brand res = tee_time_get_sys_time(&t);
77b0104773SPascal Brand if (res != TEE_SUCCESS)
78b0104773SPascal Brand return res;
79b0104773SPascal Brand
80b0104773SPascal Brand if (positive) {
81b0104773SPascal Brand TEE_TIME_ADD(t, *offs, t2);
82b0104773SPascal Brand
83b0104773SPascal Brand /* Detect wrapping, the wrapped time should be returned. */
84b0104773SPascal Brand if (TEE_TIME_LT(t2, t))
85b0104773SPascal Brand res = TEE_ERROR_OVERFLOW;
86b0104773SPascal Brand } else {
87b0104773SPascal Brand TEE_TIME_SUB(t, *offs, t2);
88b0104773SPascal Brand
89b0104773SPascal Brand /* Detect wrapping, the wrapped time should be returned. */
90b0104773SPascal Brand if (TEE_TIME_LE(t, t2))
91b0104773SPascal Brand res = TEE_ERROR_OVERFLOW;
92b0104773SPascal Brand }
93b0104773SPascal Brand *time = t2;
94b0104773SPascal Brand
95b0104773SPascal Brand return res;
96b0104773SPascal Brand }
97b0104773SPascal Brand
tee_time_set_ta_time(const TEE_UUID * uuid,const TEE_Time * time)98b0104773SPascal Brand TEE_Result tee_time_set_ta_time(const TEE_UUID *uuid, const TEE_Time *time)
99b0104773SPascal Brand {
100b0104773SPascal Brand TEE_Result res;
101b0104773SPascal Brand TEE_Time offs;
102b0104773SPascal Brand TEE_Time t;
103b0104773SPascal Brand
104b0104773SPascal Brand /* Check that time is normalized. */
105b0104773SPascal Brand if (time->millis >= TEE_TIME_MILLIS_BASE)
106b0104773SPascal Brand return TEE_ERROR_BAD_PARAMETERS;
107b0104773SPascal Brand
108b0104773SPascal Brand res = tee_time_get_sys_time(&t);
109b0104773SPascal Brand if (res != TEE_SUCCESS)
110b0104773SPascal Brand return res;
111b0104773SPascal Brand
112b0104773SPascal Brand if (TEE_TIME_LT(t, *time)) {
113b0104773SPascal Brand TEE_TIME_SUB(*time, t, offs);
114b0104773SPascal Brand return tee_time_ta_set_offs(uuid, &offs, true);
115b0104773SPascal Brand } else {
116b0104773SPascal Brand TEE_TIME_SUB(t, *time, offs);
117b0104773SPascal Brand return tee_time_ta_set_offs(uuid, &offs, false);
118b0104773SPascal Brand }
119b0104773SPascal Brand }
120889dbbbfSVictor Chong
tee_time_busy_wait(uint32_t milliseconds_delay)121889dbbbfSVictor Chong void tee_time_busy_wait(uint32_t milliseconds_delay)
122889dbbbfSVictor Chong {
123889dbbbfSVictor Chong TEE_Time curr;
124889dbbbfSVictor Chong TEE_Time delta;
125889dbbbfSVictor Chong TEE_Time end;
126889dbbbfSVictor Chong
127889dbbbfSVictor Chong if (tee_time_get_sys_time(&curr) != TEE_SUCCESS)
128889dbbbfSVictor Chong panic();
129889dbbbfSVictor Chong delta.seconds = milliseconds_delay / 1000;
130889dbbbfSVictor Chong delta.millis = milliseconds_delay % 1000;
131889dbbbfSVictor Chong TEE_TIME_ADD(curr, delta, end);
132889dbbbfSVictor Chong
133889dbbbfSVictor Chong while (TEE_TIME_LT(curr, end))
134889dbbbfSVictor Chong if (tee_time_get_sys_time(&curr) != TEE_SUCCESS)
135889dbbbfSVictor Chong panic();
136889dbbbfSVictor Chong }
137