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 /* Specific pointer ~0 denotes a still allocated but invalid handle */ 21 #define INVALID_HANDLE_PTR ((void *)~0) 22 23 void handle_db_init(struct handle_db *db) 24 { 25 TEE_MemFill(db, 0, sizeof(*db)); 26 } 27 28 void handle_db_destroy(struct handle_db *db) 29 { 30 if (db) { 31 TEE_Free(db->ptrs); 32 db->ptrs = NULL; 33 db->max_ptrs = 0; 34 } 35 } 36 37 uint32_t handle_get(struct handle_db *db, void *ptr) 38 { 39 uint32_t n = 0; 40 void *p = NULL; 41 uint32_t new_max_ptrs = 0; 42 43 if (!db || !ptr || ptr == INVALID_HANDLE_PTR) 44 return 0; 45 46 /* Try to find an empty location (index 0 is reserved as invalid) */ 47 for (n = 1; n < db->max_ptrs; n++) { 48 if (!db->ptrs[n]) { 49 db->ptrs[n] = ptr; 50 return n; 51 } 52 } 53 54 /* No location available, grow the ptrs array */ 55 if (db->max_ptrs) 56 new_max_ptrs = db->max_ptrs * 2; 57 else 58 new_max_ptrs = HANDLE_DB_INITIAL_MAX_PTRS; 59 60 p = TEE_Realloc(db->ptrs, new_max_ptrs * sizeof(void *)); 61 if (!p) 62 return 0; 63 db->ptrs = p; 64 TEE_MemFill(db->ptrs + db->max_ptrs, 0, 65 (new_max_ptrs - db->max_ptrs) * sizeof(void *)); 66 db->max_ptrs = new_max_ptrs; 67 68 /* Since n stopped at db->max_ptrs there is an empty location there */ 69 db->ptrs[n] = ptr; 70 return n; 71 } 72 73 static bool handle_is_valid(struct handle_db *db, uint32_t handle) 74 { 75 return db && handle && handle < db->max_ptrs; 76 } 77 78 void *handle_put(struct handle_db *db, uint32_t handle) 79 { 80 void *p = NULL; 81 82 if (!handle_is_valid(db, handle)) 83 return NULL; 84 85 p = db->ptrs[handle]; 86 db->ptrs[handle] = NULL; 87 return p; 88 } 89 90 void *handle_lookup(struct handle_db *db, uint32_t handle) 91 { 92 if (!handle_is_valid(db, handle) || 93 db->ptrs[handle] == INVALID_HANDLE_PTR) 94 return NULL; 95 96 return db->ptrs[handle]; 97 } 98 99 void handle_invalidate(struct handle_db *db, uint32_t handle) 100 { 101 if (handle_is_valid(db, handle)) { 102 if (!db->ptrs[handle]) 103 TEE_Panic(TEE_ERROR_GENERIC); 104 105 db->ptrs[handle] = INVALID_HANDLE_PTR; 106 } 107 } 108 109 uint32_t handle_lookup_handle(struct handle_db *db, void *ptr) 110 { 111 uint32_t n = 0; 112 113 if (ptr && ptr != INVALID_HANDLE_PTR) { 114 for (n = 1; n < db->max_ptrs; n++) 115 if (db->ptrs[n] == ptr) 116 return n; 117 } 118 119 return 0; 120 } 121