// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #include #include #include #include #include #include struct tee_ta_time_offs { TEE_UUID uuid; TEE_Time offs; bool positive; }; static struct tee_ta_time_offs *tee_time_offs; static size_t tee_time_num_offs; static TEE_Result tee_time_ta_get_offs(const TEE_UUID *uuid, const TEE_Time **offs, bool *positive) { size_t n; for (n = 0; n < tee_time_num_offs; n++) { if (memcmp(uuid, &tee_time_offs[n].uuid, sizeof(TEE_UUID)) == 0) { *offs = &tee_time_offs[n].offs; *positive = tee_time_offs[n].positive; return TEE_SUCCESS; } } return TEE_ERROR_TIME_NOT_SET; } static TEE_Result tee_time_ta_set_offs(const TEE_UUID *uuid, const TEE_Time *offs, bool positive) { size_t n; struct tee_ta_time_offs *o; for (n = 0; n < tee_time_num_offs; n++) { if (memcmp(uuid, &tee_time_offs[n].uuid, sizeof(TEE_UUID)) == 0) { tee_time_offs[n].offs = *offs; tee_time_offs[n].positive = positive; return TEE_SUCCESS; } } n = tee_time_num_offs + 1; o = realloc(tee_time_offs, n * sizeof(struct tee_ta_time_offs)); if (!o) return TEE_ERROR_OUT_OF_MEMORY; tee_time_offs = o; tee_time_offs[tee_time_num_offs].uuid = *uuid; tee_time_offs[tee_time_num_offs].offs = *offs; tee_time_offs[tee_time_num_offs].positive = positive; tee_time_num_offs = n; return TEE_SUCCESS; } TEE_Result tee_time_get_ta_time(const TEE_UUID *uuid, TEE_Time *time) { TEE_Result res; const TEE_Time *offs; bool positive; TEE_Time t; TEE_Time t2; res = tee_time_ta_get_offs(uuid, &offs, &positive); if (res != TEE_SUCCESS) return res; res = tee_time_get_sys_time(&t); if (res != TEE_SUCCESS) return res; if (positive) { TEE_TIME_ADD(t, *offs, t2); /* Detect wrapping, the wrapped time should be returned. */ if (TEE_TIME_LT(t2, t)) res = TEE_ERROR_OVERFLOW; } else { TEE_TIME_SUB(t, *offs, t2); /* Detect wrapping, the wrapped time should be returned. */ if (TEE_TIME_LE(t, t2)) res = TEE_ERROR_OVERFLOW; } *time = t2; return res; } TEE_Result tee_time_set_ta_time(const TEE_UUID *uuid, const TEE_Time *time) { TEE_Result res; TEE_Time offs; TEE_Time t; /* Check that time is normalized. */ if (time->millis >= TEE_TIME_MILLIS_BASE) return TEE_ERROR_BAD_PARAMETERS; res = tee_time_get_sys_time(&t); if (res != TEE_SUCCESS) return res; if (TEE_TIME_LT(t, *time)) { TEE_TIME_SUB(*time, t, offs); return tee_time_ta_set_offs(uuid, &offs, true); } else { TEE_TIME_SUB(t, *time, offs); return tee_time_ta_set_offs(uuid, &offs, false); } } void tee_time_busy_wait(uint32_t milliseconds_delay) { TEE_Time curr; TEE_Time delta; TEE_Time end; if (tee_time_get_sys_time(&curr) != TEE_SUCCESS) panic(); delta.seconds = milliseconds_delay / 1000; delta.millis = milliseconds_delay % 1000; TEE_TIME_ADD(curr, delta, end); while (TEE_TIME_LT(curr, end)) if (tee_time_get_sys_time(&curr) != TEE_SUCCESS) panic(); }