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