xref: /optee_os/core/arch/arm/kernel/secure_partition.c (revision c185655eafaab6b4b27759812cd6633e1da9db12)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2020-2021, Arm Limited.
4  */
5 #include <crypto/crypto.h>
6 #include <initcall.h>
7 #include <kernel/embedded_ts.h>
8 #include <kernel/ldelf_loader.h>
9 #include <kernel/secure_partition.h>
10 #include <kernel/thread_spmc.h>
11 #include <kernel/ts_store.h>
12 #include <ldelf.h>
13 #include <mm/core_mmu.h>
14 #include <mm/fobj.h>
15 #include <mm/mobj.h>
16 #include <mm/vm.h>
17 #include <optee_ffa.h>
18 #include <stdio.h>
19 #include <string.h>
20 #include <tee_api_types.h>
21 #include <trace.h>
22 #include <types_ext.h>
23 #include <utee_defines.h>
24 #include <util.h>
25 #include <zlib.h>
26 
27 static const struct ts_ops *_sp_ops;
28 
29 /* List that holds all of the loaded SP's */
30 static struct sp_sessions_head open_sp_sessions =
31 	TAILQ_HEAD_INITIALIZER(open_sp_sessions);
32 
33 static const struct ts_ops sp_ops __rodata_unpaged = {
34 };
35 
36 static const struct embedded_ts *find_secure_partition(const TEE_UUID *uuid)
37 {
38 	const struct embedded_ts *sp = NULL;
39 
40 	for_each_secure_partition(sp) {
41 		if (!memcmp(&sp->uuid, uuid, sizeof(*uuid)))
42 			return sp;
43 	}
44 	return NULL;
45 }
46 
47 bool is_sp_ctx(struct ts_ctx *ctx)
48 {
49 	return ctx && (ctx->ops == _sp_ops);
50 }
51 
52 static void set_sp_ctx_ops(struct ts_ctx *ctx)
53 {
54 	ctx->ops = _sp_ops;
55 }
56 
57 struct sp_session *sp_get_session(uint32_t session_id)
58 {
59 	struct sp_session *s = NULL;
60 
61 	TAILQ_FOREACH(s, &open_sp_sessions, link) {
62 		if (s->endpoint_id == session_id)
63 			return s;
64 	}
65 
66 	return NULL;
67 }
68 
69 static void sp_init_info(struct sp_ctx *ctx)
70 {
71 	struct sp_ffa_init_info *info = NULL;
72 
73 	ctx->uctx.stack_ptr -= ROUNDUP(sizeof(*info), STACK_ALIGNMENT);
74 
75 	ctx->sp_regs.x[0]  = (uintptr_t)ctx->uctx.stack_ptr;
76 	info = (struct sp_ffa_init_info *)ctx->uctx.stack_ptr;
77 
78 	info->magic = 0;
79 	info->count = 0;
80 }
81 
82 static uint16_t new_session_id(struct sp_sessions_head *open_sessions)
83 {
84 	struct sp_session *last = NULL;
85 	uint16_t id = SPMC_ENDPOINT_ID + 1;
86 
87 	last = TAILQ_LAST(open_sessions, sp_sessions_head);
88 	if (last)
89 		id = last->endpoint_id + 1;
90 
91 	assert(id > SPMC_ENDPOINT_ID);
92 	return id;
93 }
94 
95 static TEE_Result sp_create_ctx(const TEE_UUID *uuid, struct sp_session *s)
96 {
97 	TEE_Result res = TEE_SUCCESS;
98 	struct sp_ctx *spc = NULL;
99 
100 	/* Register context */
101 	spc = calloc(1, sizeof(struct sp_ctx));
102 	if (!spc)
103 		return TEE_ERROR_OUT_OF_MEMORY;
104 
105 	spc->uctx.ts_ctx = &spc->ts_ctx;
106 	spc->open_session = s;
107 	s->ts_sess.ctx = &spc->ts_ctx;
108 	spc->ts_ctx.uuid = *uuid;
109 
110 	res = vm_info_init(&spc->uctx);
111 	if (res)
112 		goto err;
113 
114 	set_sp_ctx_ops(&spc->ts_ctx);
115 
116 	return TEE_SUCCESS;
117 
118 err:
119 	free(spc);
120 	return res;
121 }
122 
123 static TEE_Result sp_create_session(struct sp_sessions_head *open_sessions,
124 				    const TEE_UUID *uuid,
125 				    struct sp_session **sess)
126 {
127 	TEE_Result res = TEE_SUCCESS;
128 	struct sp_session *s = calloc(1, sizeof(struct sp_session));
129 
130 	if (!s)
131 		return TEE_ERROR_OUT_OF_MEMORY;
132 
133 	s->endpoint_id = new_session_id(open_sessions);
134 	if (!s->endpoint_id) {
135 		res = TEE_ERROR_OVERFLOW;
136 		goto err;
137 	}
138 
139 	DMSG("Loading Secure Partition %pUl", (void *)uuid);
140 	res = sp_create_ctx(uuid, s);
141 	if (res)
142 		goto err;
143 
144 	TAILQ_INSERT_TAIL(open_sessions, s, link);
145 	*sess = s;
146 	return TEE_SUCCESS;
147 
148 err:
149 	free(s);
150 	return res;
151 }
152 
153 static TEE_Result sp_init_set_registers(struct sp_ctx *ctx)
154 {
155 	struct thread_ctx_regs *sp_regs = &ctx->sp_regs;
156 	uint64_t x0 = sp_regs->x[0];
157 
158 	/* Clear all addresses except x0, x0 contains the info address. */
159 	memset(sp_regs, 0, sizeof(*sp_regs));
160 	sp_regs->sp = ctx->uctx.stack_ptr;
161 	sp_regs->x[0] = x0;
162 	sp_regs->pc = ctx->uctx.entry_func;
163 
164 	return TEE_SUCCESS;
165 }
166 
167 static TEE_Result sp_open_session(struct sp_session **sess,
168 				  struct sp_sessions_head *open_sessions,
169 				  const TEE_UUID *uuid)
170 {
171 	TEE_Result res = TEE_SUCCESS;
172 	struct sp_session *s = NULL;
173 	struct sp_ctx *ctx = NULL;
174 
175 	if (!find_secure_partition(uuid))
176 		return TEE_ERROR_ITEM_NOT_FOUND;
177 
178 	res = sp_create_session(open_sessions, uuid, &s);
179 	if (res != TEE_SUCCESS) {
180 		DMSG("sp_create_session failed %#"PRIx32, res);
181 		return res;
182 	}
183 
184 	ctx = to_sp_ctx(s->ts_sess.ctx);
185 	assert(ctx);
186 	if (!ctx)
187 		return TEE_ERROR_TARGET_DEAD;
188 	*sess = s;
189 
190 	ts_push_current_session(&s->ts_sess);
191 	/* Load the SP using ldelf. */
192 	ldelf_load_ldelf(&ctx->uctx);
193 	res = ldelf_init_with_ldelf(&s->ts_sess, &ctx->uctx);
194 
195 	if (res != TEE_SUCCESS) {
196 		EMSG("Failed. loading SP using ldelf %#"PRIx32, res);
197 		ts_pop_current_session();
198 		return TEE_ERROR_TARGET_DEAD;
199 	}
200 
201 	/* Make the SP ready for its first run */
202 	s->state = sp_idle;
203 	s->caller_id = 0;
204 	sp_init_info(ctx);
205 	sp_init_set_registers(ctx);
206 	ts_pop_current_session();
207 
208 	return TEE_SUCCESS;
209 }
210 
211 static TEE_Result sp_init_uuid(const TEE_UUID *uuid)
212 {
213 	TEE_Result res = TEE_SUCCESS;
214 	struct sp_session *sess = NULL;
215 
216 	res = sp_open_session(&sess,
217 			      &open_sp_sessions,
218 			      uuid);
219 	if (res)
220 		return res;
221 
222 	return res;
223 }
224 
225 static TEE_Result sp_init_all(void)
226 {
227 	TEE_Result res = TEE_SUCCESS;
228 	const struct embedded_ts *sp = NULL;
229 	char __maybe_unused msg[60] = { '\0', };
230 
231 	_sp_ops = &sp_ops;
232 
233 	for_each_secure_partition(sp) {
234 		if (sp->uncompressed_size)
235 			snprintf(msg, sizeof(msg),
236 				 " (compressed, uncompressed %u)",
237 				 sp->uncompressed_size);
238 		else
239 			msg[0] = '\0';
240 		DMSG("SP %pUl size %u%s", (void *)&sp->uuid, sp->size, msg);
241 
242 		res = sp_init_uuid(&sp->uuid);
243 
244 		if (res != TEE_SUCCESS) {
245 			EMSG("Failed initializing SP(%pUl) err:%#"PRIx32,
246 			     &sp->uuid, res);
247 			if (!IS_ENABLED(CFG_SP_SKIP_FAILED))
248 				panic();
249 		}
250 	}
251 
252 	return TEE_SUCCESS;
253 }
254 
255 boot_final(sp_init_all);
256 
257 static TEE_Result secure_partition_open(const TEE_UUID *uuid,
258 					struct ts_store_handle **h)
259 {
260 	return emb_ts_open(uuid, h, find_secure_partition);
261 }
262 
263 REGISTER_SP_STORE(2) = {
264 	.description = "SP store",
265 	.open = secure_partition_open,
266 	.get_size = emb_ts_get_size,
267 	.get_tag = emb_ts_get_tag,
268 	.read = emb_ts_read,
269 	.close = emb_ts_close,
270 };
271