122ada947SEtienne Carriere // SPDX-License-Identifier: BSD-2-Clause
222ada947SEtienne Carriere /*
322ada947SEtienne Carriere * Copyright (c) 2014-2020, Linaro Limited
422ada947SEtienne Carriere */
522ada947SEtienne Carriere
622ada947SEtienne Carriere #include <stdlib.h>
722ada947SEtienne Carriere #include <tee_internal_api.h>
822ada947SEtienne Carriere
922ada947SEtienne Carriere #include "handle.h"
1022ada947SEtienne Carriere
1122ada947SEtienne Carriere /*
1222ada947SEtienne Carriere * Define the initial capacity of the database. It should be a low number
1322ada947SEtienne Carriere * multiple of 2 since some databases a likely to only use a few handles.
1422ada947SEtienne Carriere * Since the algorithm is to doubles up when growing it shouldn't cause a
1522ada947SEtienne Carriere * noticeable overhead on large databases.
1622ada947SEtienne Carriere */
1722ada947SEtienne Carriere #define HANDLE_DB_INITIAL_MAX_PTRS 4
1822ada947SEtienne Carriere
19*2bc50ed5SEtienne Carriere /* Specific pointer ~0 denotes a still allocated but invalid handle */
20*2bc50ed5SEtienne Carriere #define INVALID_HANDLE_PTR ((void *)~0)
21*2bc50ed5SEtienne Carriere
handle_db_init(struct handle_db * db)2222ada947SEtienne Carriere void handle_db_init(struct handle_db *db)
2322ada947SEtienne Carriere {
2422ada947SEtienne Carriere TEE_MemFill(db, 0, sizeof(*db));
2522ada947SEtienne Carriere }
2622ada947SEtienne Carriere
handle_db_destroy(struct handle_db * db)2722ada947SEtienne Carriere void handle_db_destroy(struct handle_db *db)
2822ada947SEtienne Carriere {
2922ada947SEtienne Carriere if (db) {
3022ada947SEtienne Carriere TEE_Free(db->ptrs);
3122ada947SEtienne Carriere db->ptrs = NULL;
3222ada947SEtienne Carriere db->max_ptrs = 0;
3322ada947SEtienne Carriere }
3422ada947SEtienne Carriere }
3522ada947SEtienne Carriere
handle_get(struct handle_db * db,void * ptr)3622ada947SEtienne Carriere uint32_t handle_get(struct handle_db *db, void *ptr)
3722ada947SEtienne Carriere {
3822ada947SEtienne Carriere uint32_t n = 0;
3922ada947SEtienne Carriere void *p = NULL;
4022ada947SEtienne Carriere uint32_t new_max_ptrs = 0;
4122ada947SEtienne Carriere
42*2bc50ed5SEtienne Carriere if (!db || !ptr || ptr == INVALID_HANDLE_PTR)
4322ada947SEtienne Carriere return 0;
4422ada947SEtienne Carriere
4522ada947SEtienne Carriere /* Try to find an empty location (index 0 is reserved as invalid) */
4622ada947SEtienne Carriere for (n = 1; n < db->max_ptrs; n++) {
4722ada947SEtienne Carriere if (!db->ptrs[n]) {
4822ada947SEtienne Carriere db->ptrs[n] = ptr;
4922ada947SEtienne Carriere return n;
5022ada947SEtienne Carriere }
5122ada947SEtienne Carriere }
5222ada947SEtienne Carriere
5322ada947SEtienne Carriere /* No location available, grow the ptrs array */
5422ada947SEtienne Carriere if (db->max_ptrs)
5522ada947SEtienne Carriere new_max_ptrs = db->max_ptrs * 2;
5622ada947SEtienne Carriere else
5722ada947SEtienne Carriere new_max_ptrs = HANDLE_DB_INITIAL_MAX_PTRS;
5822ada947SEtienne Carriere
5922ada947SEtienne Carriere p = TEE_Realloc(db->ptrs, new_max_ptrs * sizeof(void *));
6022ada947SEtienne Carriere if (!p)
6122ada947SEtienne Carriere return 0;
6222ada947SEtienne Carriere db->ptrs = p;
6322ada947SEtienne Carriere TEE_MemFill(db->ptrs + db->max_ptrs, 0,
6422ada947SEtienne Carriere (new_max_ptrs - db->max_ptrs) * sizeof(void *));
6522ada947SEtienne Carriere db->max_ptrs = new_max_ptrs;
6622ada947SEtienne Carriere
6722ada947SEtienne Carriere /* Since n stopped at db->max_ptrs there is an empty location there */
6822ada947SEtienne Carriere db->ptrs[n] = ptr;
6922ada947SEtienne Carriere return n;
7022ada947SEtienne Carriere }
7122ada947SEtienne Carriere
handle_is_valid(struct handle_db * db,uint32_t handle)72b8fa5170SEtienne Carriere static bool handle_is_valid(struct handle_db *db, uint32_t handle)
73b8fa5170SEtienne Carriere {
74b8fa5170SEtienne Carriere return db && handle && handle < db->max_ptrs;
75b8fa5170SEtienne Carriere }
76b8fa5170SEtienne Carriere
handle_put(struct handle_db * db,uint32_t handle)7722ada947SEtienne Carriere void *handle_put(struct handle_db *db, uint32_t handle)
7822ada947SEtienne Carriere {
7922ada947SEtienne Carriere void *p = NULL;
8022ada947SEtienne Carriere
81b8fa5170SEtienne Carriere if (!handle_is_valid(db, handle))
8222ada947SEtienne Carriere return NULL;
8322ada947SEtienne Carriere
8422ada947SEtienne Carriere p = db->ptrs[handle];
8522ada947SEtienne Carriere db->ptrs[handle] = NULL;
8622ada947SEtienne Carriere return p;
8722ada947SEtienne Carriere }
8822ada947SEtienne Carriere
handle_lookup(struct handle_db * db,uint32_t handle)8922ada947SEtienne Carriere void *handle_lookup(struct handle_db *db, uint32_t handle)
9022ada947SEtienne Carriere {
91*2bc50ed5SEtienne Carriere if (!handle_is_valid(db, handle) ||
92*2bc50ed5SEtienne Carriere db->ptrs[handle] == INVALID_HANDLE_PTR)
9322ada947SEtienne Carriere return NULL;
9422ada947SEtienne Carriere
9522ada947SEtienne Carriere return db->ptrs[handle];
9622ada947SEtienne Carriere }
9722ada947SEtienne Carriere
handle_invalidate(struct handle_db * db,uint32_t handle)98*2bc50ed5SEtienne Carriere void handle_invalidate(struct handle_db *db, uint32_t handle)
99*2bc50ed5SEtienne Carriere {
100*2bc50ed5SEtienne Carriere if (handle_is_valid(db, handle)) {
101*2bc50ed5SEtienne Carriere if (!db->ptrs[handle])
102*2bc50ed5SEtienne Carriere TEE_Panic(TEE_ERROR_GENERIC);
103*2bc50ed5SEtienne Carriere
104*2bc50ed5SEtienne Carriere db->ptrs[handle] = INVALID_HANDLE_PTR;
105*2bc50ed5SEtienne Carriere }
106*2bc50ed5SEtienne Carriere }
107*2bc50ed5SEtienne Carriere
handle_lookup_handle(struct handle_db * db,void * ptr)10822ada947SEtienne Carriere uint32_t handle_lookup_handle(struct handle_db *db, void *ptr)
10922ada947SEtienne Carriere {
11022ada947SEtienne Carriere uint32_t n = 0;
11122ada947SEtienne Carriere
112*2bc50ed5SEtienne Carriere if (ptr && ptr != INVALID_HANDLE_PTR) {
11322ada947SEtienne Carriere for (n = 1; n < db->max_ptrs; n++)
11422ada947SEtienne Carriere if (db->ptrs[n] == ptr)
11522ada947SEtienne Carriere return n;
11622ada947SEtienne Carriere }
11722ada947SEtienne Carriere
11822ada947SEtienne Carriere return 0;
11922ada947SEtienne Carriere }
120