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