xref: /optee_os/core/tee/tee_time_generic.c (revision 5ca2c36555d169a2be60964e2cbe39340c5245a4)
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