1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2014-2020, Linaro Limited 4 */ 5 6 #include <stdlib.h> 7 #include <tee_internal_api.h> 8 #include <tee_internal_api_extensions.h> 9 10 #include "handle.h" 11 12 /* 13 * Define the initial capacity of the database. It should be a low number 14 * multiple of 2 since some databases a likely to only use a few handles. 15 * Since the algorithm is to doubles up when growing it shouldn't cause a 16 * noticeable overhead on large databases. 17 */ 18 #define HANDLE_DB_INITIAL_MAX_PTRS 4 19 20 void handle_db_init(struct handle_db *db) 21 { 22 TEE_MemFill(db, 0, sizeof(*db)); 23 } 24 25 void handle_db_destroy(struct handle_db *db) 26 { 27 if (db) { 28 TEE_Free(db->ptrs); 29 db->ptrs = NULL; 30 db->max_ptrs = 0; 31 } 32 } 33 34 uint32_t handle_get(struct handle_db *db, void *ptr) 35 { 36 uint32_t n = 0; 37 void *p = NULL; 38 uint32_t new_max_ptrs = 0; 39 40 if (!db || !ptr) 41 return 0; 42 43 /* Try to find an empty location (index 0 is reserved as invalid) */ 44 for (n = 1; n < db->max_ptrs; n++) { 45 if (!db->ptrs[n]) { 46 db->ptrs[n] = ptr; 47 return n; 48 } 49 } 50 51 /* No location available, grow the ptrs array */ 52 if (db->max_ptrs) 53 new_max_ptrs = db->max_ptrs * 2; 54 else 55 new_max_ptrs = HANDLE_DB_INITIAL_MAX_PTRS; 56 57 p = TEE_Realloc(db->ptrs, new_max_ptrs * sizeof(void *)); 58 if (!p) 59 return 0; 60 db->ptrs = p; 61 TEE_MemFill(db->ptrs + db->max_ptrs, 0, 62 (new_max_ptrs - db->max_ptrs) * sizeof(void *)); 63 db->max_ptrs = new_max_ptrs; 64 65 /* Since n stopped at db->max_ptrs there is an empty location there */ 66 db->ptrs[n] = ptr; 67 return n; 68 } 69 70 static bool handle_is_valid(struct handle_db *db, uint32_t handle) 71 { 72 return db && handle && handle < db->max_ptrs; 73 } 74 75 void *handle_put(struct handle_db *db, uint32_t handle) 76 { 77 void *p = NULL; 78 79 if (!handle_is_valid(db, handle)) 80 return NULL; 81 82 p = db->ptrs[handle]; 83 db->ptrs[handle] = NULL; 84 return p; 85 } 86 87 void *handle_lookup(struct handle_db *db, uint32_t handle) 88 { 89 if (!handle_is_valid(db, handle)) 90 return NULL; 91 92 return db->ptrs[handle]; 93 } 94 95 uint32_t handle_lookup_handle(struct handle_db *db, void *ptr) 96 { 97 uint32_t n = 0; 98 99 if (ptr) { 100 for (n = 1; n < db->max_ptrs; n++) 101 if (db->ptrs[n] == ptr) 102 return n; 103 } 104 105 return 0; 106 } 107