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