1 /*
2  * Copyright (c) 2018-2023, Arm Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 #include <inttypes.h>
8 #include <stdbool.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include "thread.h"
12 #include "psa/client.h"
13 #include "psa/service.h"
14 #include "internal_status_code.h"
15 #include "cmsis_compiler.h"
16 #include "utilities.h"
17 #include "lists.h"
18 #include "tfm_pools.h"
19 
tfm_pool_init(struct tfm_pool_instance_t * pool,size_t poolsz,size_t chunksz,size_t num)20 psa_status_t tfm_pool_init(struct tfm_pool_instance_t *pool, size_t poolsz,
21                            size_t chunksz, size_t num)
22 {
23     struct tfm_pool_chunk_t *pchunk;
24     size_t i;
25 
26     if (!pool || num == 0) {
27         return SPM_ERROR_BAD_PARAMETERS;
28     }
29 
30     /* Ensure buffer is large enough */
31     if (poolsz != ((chunksz + sizeof(struct tfm_pool_chunk_t)) * num +
32         sizeof(struct tfm_pool_instance_t))) {
33         return SPM_ERROR_BAD_PARAMETERS;
34     }
35 
36     /* Buffer should be BSS cleared but clear it again */
37     spm_memset(pool, 0, poolsz);
38 
39     /* Chain pool chunks */
40     UNI_LISI_INIT_NODE(pool, next);
41 
42     pchunk = (struct tfm_pool_chunk_t *)pool->chunks;
43     for (i = 0; i < num; i++) {
44         UNI_LIST_INSERT_AFTER(pool, pchunk, next);
45         pchunk = (struct tfm_pool_chunk_t *)&pchunk->data[chunksz];
46     }
47 
48     /* Prepare instance and insert to pool list */
49     pool->chunksz = chunksz;
50     pool->pool_sz = poolsz;
51 
52     return PSA_SUCCESS;
53 }
54 
tfm_pool_alloc(struct tfm_pool_instance_t * pool)55 void *tfm_pool_alloc(struct tfm_pool_instance_t *pool)
56 {
57     struct tfm_pool_chunk_t *node;
58 
59     if (!pool) {
60         return NULL;
61     }
62 
63     if (UNI_LIST_IS_EMPTY(pool, next)) {
64         return NULL;
65     }
66 
67     node = UNI_LIST_NEXT_NODE(pool, next);
68     UNI_LIST_REMOVE_NODE(pool, node, next);
69 
70     return &(((struct tfm_pool_chunk_t *)node)->data);
71 }
72 
tfm_pool_free(struct tfm_pool_instance_t * pool,void * ptr)73 void tfm_pool_free(struct tfm_pool_instance_t *pool, void *ptr)
74 {
75     struct tfm_pool_chunk_t *pchunk;
76 
77     pchunk = TO_CONTAINER(ptr, struct tfm_pool_chunk_t, data);
78 
79     UNI_LIST_INSERT_AFTER(pool, pchunk, next);
80 }
81 
is_valid_chunk_data_in_pool(struct tfm_pool_instance_t * pool,uint8_t * data)82 bool is_valid_chunk_data_in_pool(struct tfm_pool_instance_t *pool,
83                                  uint8_t *data)
84 {
85     const uintptr_t chunks_start = (uintptr_t)(pool->chunks);
86     const size_t chunks_offset = (uintptr_t)data - chunks_start;
87 
88     /* Check that the message was allocated from the pool. */
89     if ((uintptr_t)data < chunks_start || chunks_offset >= pool->pool_sz) {
90         return false;
91     }
92 
93     if ((chunks_offset % (pool->chunksz + sizeof(struct tfm_pool_chunk_t)))
94         != offsetof(struct tfm_pool_chunk_t, data)) {
95         return false;
96     }
97 
98     return true;
99 }
100