1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2014, STMicroelectronics International N.V. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright notice, 10 * this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright notice, 13 * this list of conditions and the following disclaimer in the documentation 14 * and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <kernel/panic.h> 30 #include <kernel/tee_time.h> 31 #include <string.h> 32 #include <stdlib.h> 33 #include <trace.h> 34 #include <utee_defines.h> 35 36 struct tee_ta_time_offs { 37 TEE_UUID uuid; 38 TEE_Time offs; 39 bool positive; 40 }; 41 42 static struct tee_ta_time_offs *tee_time_offs; 43 static size_t tee_time_num_offs; 44 45 static TEE_Result tee_time_ta_get_offs(const TEE_UUID *uuid, 46 const TEE_Time **offs, bool *positive) 47 { 48 size_t n; 49 50 for (n = 0; n < tee_time_num_offs; n++) { 51 if (memcmp(uuid, &tee_time_offs[n].uuid, sizeof(TEE_UUID)) 52 == 0) { 53 *offs = &tee_time_offs[n].offs; 54 *positive = tee_time_offs[n].positive; 55 return TEE_SUCCESS; 56 } 57 } 58 return TEE_ERROR_TIME_NOT_SET; 59 } 60 61 static TEE_Result tee_time_ta_set_offs(const TEE_UUID *uuid, 62 const TEE_Time *offs, bool positive) 63 { 64 size_t n; 65 struct tee_ta_time_offs *o; 66 67 for (n = 0; n < tee_time_num_offs; n++) { 68 if (memcmp(uuid, &tee_time_offs[n].uuid, sizeof(TEE_UUID)) 69 == 0) { 70 tee_time_offs[n].offs = *offs; 71 tee_time_offs[n].positive = positive; 72 return TEE_SUCCESS; 73 } 74 } 75 76 n = tee_time_num_offs + 1; 77 o = realloc(tee_time_offs, n * sizeof(struct tee_ta_time_offs)); 78 if (!o) 79 return TEE_ERROR_OUT_OF_MEMORY; 80 tee_time_offs = o; 81 tee_time_offs[tee_time_num_offs].uuid = *uuid; 82 tee_time_offs[tee_time_num_offs].offs = *offs; 83 tee_time_offs[tee_time_num_offs].positive = positive; 84 tee_time_num_offs = n; 85 return TEE_SUCCESS; 86 } 87 88 TEE_Result tee_time_get_ta_time(const TEE_UUID *uuid, TEE_Time *time) 89 { 90 TEE_Result res; 91 const TEE_Time *offs; 92 bool positive; 93 TEE_Time t; 94 TEE_Time t2; 95 96 res = tee_time_ta_get_offs(uuid, &offs, &positive); 97 if (res != TEE_SUCCESS) 98 return res; 99 100 res = tee_time_get_sys_time(&t); 101 if (res != TEE_SUCCESS) 102 return res; 103 104 if (positive) { 105 TEE_TIME_ADD(t, *offs, t2); 106 107 /* Detect wrapping, the wrapped time should be returned. */ 108 if (TEE_TIME_LT(t2, t)) 109 res = TEE_ERROR_OVERFLOW; 110 } else { 111 TEE_TIME_SUB(t, *offs, t2); 112 113 /* Detect wrapping, the wrapped time should be returned. */ 114 if (TEE_TIME_LE(t, t2)) 115 res = TEE_ERROR_OVERFLOW; 116 } 117 *time = t2; 118 119 return res; 120 } 121 122 TEE_Result tee_time_set_ta_time(const TEE_UUID *uuid, const TEE_Time *time) 123 { 124 TEE_Result res; 125 TEE_Time offs; 126 TEE_Time t; 127 128 /* Check that time is normalized. */ 129 if (time->millis >= TEE_TIME_MILLIS_BASE) 130 return TEE_ERROR_BAD_PARAMETERS; 131 132 res = tee_time_get_sys_time(&t); 133 if (res != TEE_SUCCESS) 134 return res; 135 136 if (TEE_TIME_LT(t, *time)) { 137 TEE_TIME_SUB(*time, t, offs); 138 return tee_time_ta_set_offs(uuid, &offs, true); 139 } else { 140 TEE_TIME_SUB(t, *time, offs); 141 return tee_time_ta_set_offs(uuid, &offs, false); 142 } 143 } 144 145 void tee_time_busy_wait(uint32_t milliseconds_delay) 146 { 147 TEE_Time curr; 148 TEE_Time delta; 149 TEE_Time end; 150 151 if (tee_time_get_sys_time(&curr) != TEE_SUCCESS) 152 panic(); 153 delta.seconds = milliseconds_delay / 1000; 154 delta.millis = milliseconds_delay % 1000; 155 TEE_TIME_ADD(curr, delta, end); 156 157 while (TEE_TIME_LT(curr, end)) 158 if (tee_time_get_sys_time(&curr) != TEE_SUCCESS) 159 panic(); 160 } 161