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