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