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