summaryrefslogtreecommitdiff
path: root/core/tee/se/manager.c
blob: 325fa13a351e12f57919d682a4d38283bad88dc6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// SPDX-License-Identifier: BSD-2-Clause
/*
 * Copyright (c) 2014, Linaro Limited
 */

#include <initcall.h>
#include <trace.h>
#include <kernel/mutex.h>
#include <tee/se/manager.h>
#include <tee/se/session.h>
#include <tee/se/reader.h>
#include <tee/se/reader/interface.h>

#include <stdlib.h>
#include <sys/queue.h>

#include "reader_priv.h"
#include "session_priv.h"

TAILQ_HEAD(reader_proxy_head, tee_se_reader_proxy);

struct tee_se_manager_ctx {
	/* number of readers registered */
	size_t reader_count;
	/* mutex to pretect the reader proxy list */
	struct mutex mutex;
	/* list of registered readers */
	struct reader_proxy_head reader_proxies;
};
static struct tee_se_manager_ctx se_manager_ctx;

TEE_Result tee_se_manager_register_reader(struct tee_se_reader *r)
{
	struct tee_se_manager_ctx *ctx = &se_manager_ctx;
	struct tee_se_reader_proxy *proxy =
		malloc(sizeof(struct tee_se_reader_proxy));
	if (!proxy)
		return TEE_ERROR_OUT_OF_MEMORY;

	proxy->reader = r;
	proxy->refcnt = 0;
	proxy->basic_channel_locked = false;
	mutex_init(&proxy->mutex);

	mutex_lock(&ctx->mutex);
	TAILQ_INSERT_TAIL(&ctx->reader_proxies, proxy, link);
	ctx->reader_count++;
	mutex_unlock(&ctx->mutex);

	return TEE_SUCCESS;
}

TEE_Result tee_se_manager_unregister_reader(struct tee_se_reader *r)
{
	struct tee_se_manager_ctx *ctx = &se_manager_ctx;
	struct tee_se_reader_proxy *proxy, *next_proxy;

	mutex_lock(&ctx->mutex);
	TAILQ_FOREACH_SAFE(proxy, &ctx->reader_proxies, link, next_proxy)
	{
		if (proxy->reader == r)
			TAILQ_REMOVE(&ctx->reader_proxies, proxy, link);
		free(proxy);
	}
	ctx->reader_count--;
	mutex_unlock(&ctx->mutex);

	return TEE_SUCCESS;
}

size_t tee_se_manager_get_reader_count(void)
{
	struct tee_se_manager_ctx *ctx = &se_manager_ctx;

	return ctx->reader_count;
}

TEE_Result tee_se_manager_get_readers(
		struct tee_se_reader_proxy **proxy_list,
		size_t *proxy_list_size)
{
	struct tee_se_manager_ctx *ctx = &se_manager_ctx;
	struct tee_se_reader_proxy *proxy;
	size_t i = 0;

	if (TAILQ_EMPTY(&ctx->reader_proxies))
		return TEE_ERROR_ITEM_NOT_FOUND;

	TAILQ_FOREACH(proxy, &ctx->reader_proxies, link) {
		if (i >= *proxy_list_size)
			return TEE_ERROR_SHORT_BUFFER;

		proxy_list[i] = proxy;
		i++;
	}
	*proxy_list_size = i;

	return TEE_SUCCESS;
}

bool tee_se_manager_is_reader_proxy_valid(
		struct tee_se_reader_proxy *proxy)
{
	struct tee_se_manager_ctx *ctx = &se_manager_ctx;
	struct tee_se_reader_proxy *h;

	TAILQ_FOREACH(h, &ctx->reader_proxies, link) {
		if (h == proxy)
			return true;
	}

	return false;
}

static void context_init(struct tee_se_manager_ctx *ctx)
{
	TAILQ_INIT(&ctx->reader_proxies);
	mutex_init(&ctx->mutex);
	ctx->reader_count = 0;
}

static TEE_Result tee_se_manager_init(void)
{
	struct tee_se_manager_ctx *ctx = &se_manager_ctx;

	context_init(ctx);

	return TEE_SUCCESS;
}

service_init(tee_se_manager_init);