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
handle_db_init(struct handle_db * db)20 void handle_db_init(struct handle_db *db)
21 {
22 TEE_MemFill(db, 0, sizeof(*db));
23 }
24
handle_db_destroy(struct handle_db * db)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
handle_get(struct handle_db * db,void * ptr)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
handle_put(struct handle_db * db,uint32_t handle)70 void *handle_put(struct handle_db *db, uint32_t handle)
71 {
72 void *p = NULL;
73
74 if (!db || !handle || handle >= db->max_ptrs)
75 return NULL;
76
77 p = db->ptrs[handle];
78 db->ptrs[handle] = NULL;
79 return p;
80 }
81
handle_lookup(struct handle_db * db,uint32_t handle)82 void *handle_lookup(struct handle_db *db, uint32_t handle)
83 {
84 if (!db || !handle || handle >= db->max_ptrs)
85 return NULL;
86
87 return db->ptrs[handle];
88 }
89
handle_lookup_handle(struct handle_db * db,void * ptr)90 uint32_t handle_lookup_handle(struct handle_db *db, void *ptr)
91 {
92 uint32_t n = 0;
93
94 if (ptr) {
95 for (n = 1; n < db->max_ptrs; n++)
96 if (db->ptrs[n] == ptr)
97 return n;
98 }
99
100 return 0;
101 }
102