blob: f298340054f6236b92883ac53ceecf95b141ac17 [file] [log] [blame]
/*
* Copyright (c) 2018-2021, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h>
#include "tfm_thread.h"
#include "tfm_wait.h"
#include "psa/client.h"
#include "psa/service.h"
#include "internal_errors.h"
#include "cmsis_compiler.h"
#include "utilities.h"
#include "lists.h"
#include "tfm_pools.h"
#include "tfm_memory_utils.h"
#include "tfm_core_utils.h"
int32_t tfm_pool_init(struct tfm_pool_instance_t *pool, size_t poolsz,
size_t chunksz, size_t num)
{
struct tfm_pool_chunk_t *pchunk;
size_t i;
if (!pool || num == 0) {
return SPM_ERROR_BAD_PARAMETERS;
}
/* Ensure buffer is large enough */
if (poolsz != ((chunksz + sizeof(struct tfm_pool_chunk_t)) * num +
sizeof(struct tfm_pool_instance_t))) {
return SPM_ERROR_BAD_PARAMETERS;
}
/* Buffer should be BSS cleared but clear it again */
spm_memset(pool, 0, poolsz);
/* Chain pool chunks */
BI_LIST_INIT_NODE(&pool->chunks_list);
pchunk = (struct tfm_pool_chunk_t *)pool->chunks;
for (i = 0; i < num; i++) {
BI_LIST_INSERT_BEFORE(&pool->chunks_list, &pchunk->list);
pchunk = (struct tfm_pool_chunk_t *)&pchunk->data[chunksz];
}
/* Prepare instance and insert to pool list */
pool->chunksz = chunksz;
pool->chunk_count = num;
return SPM_SUCCESS;
}
void *tfm_pool_alloc(struct tfm_pool_instance_t *pool)
{
struct bi_list_node_t *node;
struct tfm_pool_chunk_t *pchunk;
if (!pool) {
return NULL;
}
if (BI_LIST_IS_EMPTY(&pool->chunks_list)) {
return NULL;
}
node = BI_LIST_NEXT_NODE(&pool->chunks_list);
pchunk = TFM_GET_CONTAINER_PTR(node, struct tfm_pool_chunk_t, list);
/* Remove node from list node, it will be added when pool free */
BI_LIST_REMOVE_NODE(node);
return &pchunk->data;
}
void tfm_pool_free(struct tfm_pool_instance_t *pool, void *ptr)
{
struct tfm_pool_chunk_t *pchunk;
pchunk = TFM_GET_CONTAINER_PTR(ptr, struct tfm_pool_chunk_t, data);
BI_LIST_INSERT_BEFORE(&pool->chunks_list, &pchunk->list);
}
bool is_valid_chunk_data_in_pool(struct tfm_pool_instance_t *pool,
uint8_t *data)
{
const uintptr_t chunks_start = (uintptr_t)(pool->chunks);
const size_t chunks_size = pool->chunksz + sizeof(struct tfm_pool_chunk_t);
const size_t chunk_count = pool->chunk_count;
const uintptr_t chunks_end = chunks_start + chunks_size * chunk_count;
uintptr_t pool_chunk_address = 0;
/* Check that the message was allocated from the pool. */
if ((uintptr_t)data < chunks_start || (uintptr_t)data >= chunks_end) {
return false;
}
pool_chunk_address =
(uint32_t)TFM_GET_CONTAINER_PTR(data, struct tfm_pool_chunk_t, data);
/* Make sure that the chunk containing the message is aligned on */
/* chunk boundary in the pool. */
if ((pool_chunk_address - chunks_start) % chunks_size != 0) {
return false;
}
return true;
}