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