blob: 6ab56af75debc10dc0f83416b4bbd1c9a98ed431 [file] [log] [blame]
Edison Ai1e5822f2018-09-21 14:56:08 +08001/*
2 * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7#include <inttypes.h>
8#include <stdbool.h>
Edison Ai1e5822f2018-09-21 14:56:08 +08009#include <stdlib.h>
10#include "tfm_thread.h"
11#include "tfm_wait.h"
Jamie Foxcc31d402019-01-28 17:13:52 +000012#include "psa/client.h"
13#include "psa/service.h"
Edison Ai1e5822f2018-09-21 14:56:08 +080014#include "tfm_internal_defines.h"
15#include "cmsis_compiler.h"
16#include "tfm_utils.h"
17#include "tfm_list.h"
18#include "tfm_pools.h"
Edison Ai807fedb2019-03-07 11:22:03 +080019#include "tfm_memory_utils.h"
Mingyang Sun94b1b412019-09-20 15:11:14 +080020#include "tfm_core_utils.h"
Edison Ai1e5822f2018-09-21 14:56:08 +080021
22int32_t tfm_pool_init(struct tfm_pool_instance_t *pool, size_t poolsz,
23 size_t chunksz, size_t num)
24{
25 struct tfm_pool_chunk_t *pchunk;
26 size_t i;
27
28 if (!pool || num == 0) {
29 return IPC_ERROR_BAD_PARAMETERS;
30 }
31
32 /* Ensure buffer is large enough */
33 if (poolsz != ((chunksz + sizeof(struct tfm_pool_chunk_t)) * num +
34 sizeof(struct tfm_pool_instance_t))) {
35 return IPC_ERROR_BAD_PARAMETERS;
36 }
37
38 /* Buffer should be BSS cleared but clear it again */
Mingyang Sun94b1b412019-09-20 15:11:14 +080039 tfm_core_util_memset(pool, 0, poolsz);
Edison Ai1e5822f2018-09-21 14:56:08 +080040
41 /* Chain pool chunks */
42 tfm_list_init(&pool->chunks_list);
43
44 pchunk = (struct tfm_pool_chunk_t *)pool->chunks;
45 for (i = 0; i < num; i++) {
46 pchunk->pool = pool;
47 tfm_list_add_tail(&pool->chunks_list, &pchunk->list);
48 pchunk = (struct tfm_pool_chunk_t *)&pchunk->data[chunksz];
49 }
50
51 /* Prepare instance and insert to pool list */
52 pool->chunksz = chunksz;
Mate Toth-Pala4b5d242019-09-23 09:14:47 +020053 pool->chunk_count = num;
Edison Ai1e5822f2018-09-21 14:56:08 +080054
55 return IPC_SUCCESS;
56}
57
58void *tfm_pool_alloc(struct tfm_pool_instance_t *pool)
59{
60 struct tfm_list_node_t *node;
61 struct tfm_pool_chunk_t *pchunk;
62
63 if (!pool) {
64 return NULL;
65 }
66
67 if (tfm_list_is_empty(&pool->chunks_list)) {
68 return NULL;
69 }
70
71 node = tfm_list_first_node(&pool->chunks_list);
72 pchunk = TFM_GET_CONTAINER_PTR(node, struct tfm_pool_chunk_t, list);
73
74 /* Remove node from list node, it will be added when pool free */
75 tfm_list_del_node(node);
76
77 return &pchunk->data;
78}
79
80void tfm_pool_free(void *ptr)
81{
82 struct tfm_pool_chunk_t *pchunk;
83 struct tfm_pool_instance_t *pool;
84
85 pchunk = TFM_GET_CONTAINER_PTR(ptr, struct tfm_pool_chunk_t, data);
86 pool = (struct tfm_pool_instance_t *)pchunk->pool;
87 tfm_list_add_tail(&pool->chunks_list, &pchunk->list);
88}
Mate Toth-Pala4b5d242019-09-23 09:14:47 +020089
90bool is_valid_chunk_data_in_pool(struct tfm_pool_instance_t *pool,
91 uint8_t *data)
92{
93 const uintptr_t chunks_start = (uintptr_t)(pool->chunks);
94 const size_t chunks_size = pool->chunksz + sizeof(struct tfm_pool_chunk_t);
95 const size_t chunk_count = pool->chunk_count;
96 const uintptr_t chunks_end = chunks_start + chunks_size * chunk_count;
97 uintptr_t pool_chunk_address = 0;
98
99 /* Check that the message was allocated from the pool. */
100 if ((uintptr_t)data < chunks_start || (uintptr_t)data >= chunks_end) {
101 return false;
102 }
103
104 pool_chunk_address =
105 (uint32_t)TFM_GET_CONTAINER_PTR(data, struct tfm_pool_chunk_t, data);
106
107 /* Make sure that the chunk containing the message is aligned on */
108 /* chunk boundary in the pool. */
109 if ((pool_chunk_address - chunks_start) % chunks_size != 0) {
110 return false;
111 }
112 return true;
113}