122ada947SEtienne Carriere // SPDX-License-Identifier: BSD-2-Clause 222ada947SEtienne Carriere /* 322ada947SEtienne Carriere * Copyright (c) 2014-2020, Linaro Limited 422ada947SEtienne Carriere */ 522ada947SEtienne Carriere 622ada947SEtienne Carriere #include <stdlib.h> 722ada947SEtienne Carriere #include <tee_internal_api.h> 822ada947SEtienne Carriere #include <tee_internal_api_extensions.h> 922ada947SEtienne Carriere 1022ada947SEtienne Carriere #include "handle.h" 1122ada947SEtienne Carriere 1222ada947SEtienne Carriere /* 1322ada947SEtienne Carriere * Define the initial capacity of the database. It should be a low number 1422ada947SEtienne Carriere * multiple of 2 since some databases a likely to only use a few handles. 1522ada947SEtienne Carriere * Since the algorithm is to doubles up when growing it shouldn't cause a 1622ada947SEtienne Carriere * noticeable overhead on large databases. 1722ada947SEtienne Carriere */ 1822ada947SEtienne Carriere #define HANDLE_DB_INITIAL_MAX_PTRS 4 1922ada947SEtienne Carriere 20*2bc50ed5SEtienne Carriere /* Specific pointer ~0 denotes a still allocated but invalid handle */ 21*2bc50ed5SEtienne Carriere #define INVALID_HANDLE_PTR ((void *)~0) 22*2bc50ed5SEtienne Carriere 2322ada947SEtienne Carriere void handle_db_init(struct handle_db *db) 2422ada947SEtienne Carriere { 2522ada947SEtienne Carriere TEE_MemFill(db, 0, sizeof(*db)); 2622ada947SEtienne Carriere } 2722ada947SEtienne Carriere 2822ada947SEtienne Carriere void handle_db_destroy(struct handle_db *db) 2922ada947SEtienne Carriere { 3022ada947SEtienne Carriere if (db) { 3122ada947SEtienne Carriere TEE_Free(db->ptrs); 3222ada947SEtienne Carriere db->ptrs = NULL; 3322ada947SEtienne Carriere db->max_ptrs = 0; 3422ada947SEtienne Carriere } 3522ada947SEtienne Carriere } 3622ada947SEtienne Carriere 3722ada947SEtienne Carriere uint32_t handle_get(struct handle_db *db, void *ptr) 3822ada947SEtienne Carriere { 3922ada947SEtienne Carriere uint32_t n = 0; 4022ada947SEtienne Carriere void *p = NULL; 4122ada947SEtienne Carriere uint32_t new_max_ptrs = 0; 4222ada947SEtienne Carriere 43*2bc50ed5SEtienne Carriere if (!db || !ptr || ptr == INVALID_HANDLE_PTR) 4422ada947SEtienne Carriere return 0; 4522ada947SEtienne Carriere 4622ada947SEtienne Carriere /* Try to find an empty location (index 0 is reserved as invalid) */ 4722ada947SEtienne Carriere for (n = 1; n < db->max_ptrs; n++) { 4822ada947SEtienne Carriere if (!db->ptrs[n]) { 4922ada947SEtienne Carriere db->ptrs[n] = ptr; 5022ada947SEtienne Carriere return n; 5122ada947SEtienne Carriere } 5222ada947SEtienne Carriere } 5322ada947SEtienne Carriere 5422ada947SEtienne Carriere /* No location available, grow the ptrs array */ 5522ada947SEtienne Carriere if (db->max_ptrs) 5622ada947SEtienne Carriere new_max_ptrs = db->max_ptrs * 2; 5722ada947SEtienne Carriere else 5822ada947SEtienne Carriere new_max_ptrs = HANDLE_DB_INITIAL_MAX_PTRS; 5922ada947SEtienne Carriere 6022ada947SEtienne Carriere p = TEE_Realloc(db->ptrs, new_max_ptrs * sizeof(void *)); 6122ada947SEtienne Carriere if (!p) 6222ada947SEtienne Carriere return 0; 6322ada947SEtienne Carriere db->ptrs = p; 6422ada947SEtienne Carriere TEE_MemFill(db->ptrs + db->max_ptrs, 0, 6522ada947SEtienne Carriere (new_max_ptrs - db->max_ptrs) * sizeof(void *)); 6622ada947SEtienne Carriere db->max_ptrs = new_max_ptrs; 6722ada947SEtienne Carriere 6822ada947SEtienne Carriere /* Since n stopped at db->max_ptrs there is an empty location there */ 6922ada947SEtienne Carriere db->ptrs[n] = ptr; 7022ada947SEtienne Carriere return n; 7122ada947SEtienne Carriere } 7222ada947SEtienne Carriere 73b8fa5170SEtienne Carriere static bool handle_is_valid(struct handle_db *db, uint32_t handle) 74b8fa5170SEtienne Carriere { 75b8fa5170SEtienne Carriere return db && handle && handle < db->max_ptrs; 76b8fa5170SEtienne Carriere } 77b8fa5170SEtienne Carriere 7822ada947SEtienne Carriere void *handle_put(struct handle_db *db, uint32_t handle) 7922ada947SEtienne Carriere { 8022ada947SEtienne Carriere void *p = NULL; 8122ada947SEtienne Carriere 82b8fa5170SEtienne Carriere if (!handle_is_valid(db, handle)) 8322ada947SEtienne Carriere return NULL; 8422ada947SEtienne Carriere 8522ada947SEtienne Carriere p = db->ptrs[handle]; 8622ada947SEtienne Carriere db->ptrs[handle] = NULL; 8722ada947SEtienne Carriere return p; 8822ada947SEtienne Carriere } 8922ada947SEtienne Carriere 9022ada947SEtienne Carriere void *handle_lookup(struct handle_db *db, uint32_t handle) 9122ada947SEtienne Carriere { 92*2bc50ed5SEtienne Carriere if (!handle_is_valid(db, handle) || 93*2bc50ed5SEtienne Carriere db->ptrs[handle] == INVALID_HANDLE_PTR) 9422ada947SEtienne Carriere return NULL; 9522ada947SEtienne Carriere 9622ada947SEtienne Carriere return db->ptrs[handle]; 9722ada947SEtienne Carriere } 9822ada947SEtienne Carriere 99*2bc50ed5SEtienne Carriere void handle_invalidate(struct handle_db *db, uint32_t handle) 100*2bc50ed5SEtienne Carriere { 101*2bc50ed5SEtienne Carriere if (handle_is_valid(db, handle)) { 102*2bc50ed5SEtienne Carriere if (!db->ptrs[handle]) 103*2bc50ed5SEtienne Carriere TEE_Panic(TEE_ERROR_GENERIC); 104*2bc50ed5SEtienne Carriere 105*2bc50ed5SEtienne Carriere db->ptrs[handle] = INVALID_HANDLE_PTR; 106*2bc50ed5SEtienne Carriere } 107*2bc50ed5SEtienne Carriere } 108*2bc50ed5SEtienne Carriere 10922ada947SEtienne Carriere uint32_t handle_lookup_handle(struct handle_db *db, void *ptr) 11022ada947SEtienne Carriere { 11122ada947SEtienne Carriere uint32_t n = 0; 11222ada947SEtienne Carriere 113*2bc50ed5SEtienne Carriere if (ptr && ptr != INVALID_HANDLE_PTR) { 11422ada947SEtienne Carriere for (n = 1; n < db->max_ptrs; n++) 11522ada947SEtienne Carriere if (db->ptrs[n] == ptr) 11622ada947SEtienne Carriere return n; 11722ada947SEtienne Carriere } 11822ada947SEtienne Carriere 11922ada947SEtienne Carriere return 0; 12022ada947SEtienne Carriere } 121