xref: /optee_os/ta/remoteproc/src/remoteproc_core.c (revision 56a69fb46115a1cd3bc41b0d47fe273513356cdc)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (C) 2023, STMicroelectronics
4  */
5 
6 #include <elf_parser.h>
7 #include <remoteproc_pta.h>
8 #include <string.h>
9 #include <sys/queue.h>
10 #include <ta_remoteproc.h>
11 #include <tee_internal_api.h>
12 #include <tee_internal_api_extensions.h>
13 #include <types_ext.h>
14 #include <utee_defines.h>
15 
16 /*
17  * The remoteproc Trusted Application is in charge of authenticating and loading
18  * images signed by the scripts/sign_rproc_fw.py. The TA is also in charge of
19  * starting and stopping the remote processor.
20  * The structure of the signed image is:
21  *
22  *                   -----+-------------+
23  *                  /     |    Magic    |  32-bit word, magic value equal to
24  *                 /      +-------------+  0x3543A468
25  *                /       +-------------+
26  *               /        |   version   |  32-bit word, version of the format
27  *              /         +-------------+
28  * +-----------+          +-------------+
29  * |   Header  |          |  TLV size   |  32-bit word, size of the TLV
30  * +-----------+          +-------------+  (aligned on 64-bit), in bytes.
31  *              \         +-------------+
32  *               \        |  sign size  |  32-bit word, size of the signature
33  *                \       +-------------+  (aligned on 64-bit), in bytes.
34  *                 \      +-------------+
35  *                  \     | images size |  32-bit word, size of the images to
36  *                   -----+-------------+  load (aligned on 64-bit), in bytes.
37  *
38  *                        +-------------+  Information used to authenticate the
39  *                        |     TLV     |  images and boot the remote processor,
40  *                        |             |  stored in Type-Length-Value format.
41  *                        +-------------+  'Type' and 'Length' are 32-bit words.
42  *
43  *                        +-------------+
44  *                        | Signature   |   Signature of the header and the TLV.
45  *                        +-------------+
46  *
47  *                        +-------------+
48  *                        |   Firmware  |
49  *                        |    image 1  |
50  *                        +-------------+
51  *                               ...
52  *                        +-------------+
53  *                        |   Firmware  |
54  *                        |    image n  |
55  *                        +-------------+
56  */
57 
58 /* Firmware state */
59 enum remoteproc_state {
60 	REMOTEPROC_OFF = 0,
61 	REMOTEPROC_LOADED,
62 	REMOTEPROC_STARTED,
63 };
64 
65 #define RPROC_HDR_MAGIC		0x3543A468
66 #define HEADER_VERSION		1
67 
68 /* Supported signature algorithm */
69 enum remoteproc_sign_type {
70 	RPROC_RSASSA_PKCS1_v1_5_SHA256 = 1,
71 	RPROC_ECDSA_SHA256 = 2,
72 };
73 
74 enum remoteproc_img_type {
75 	REMOTEPROC_ELF_TYPE = 1,
76 	REMOTEPROC_INVALID_TYPE = 0xFF
77 };
78 
79 /* remoteproc_tlv structure offsets */
80 #define RPROC_TLV_LENGTH_OF	U(0x04)
81 #define RPROC_TLV_VALUE_OF	U(0x08)
82 
83 /* TLV types */
84 #define RPROC_TLV_SIGNTYPE	U(0x00000001)
85 #define RPROC_TLV_HASHTYPE	U(0x00000002)
86 #define RPROC_TLV_NUM_IMG	U(0x00000003)
87 #define RPROC_TLV_IMGTYPE	U(0x00000004)
88 #define RPROC_TLV_IMGSIZE	U(0x00000005)
89 #define RPROC_TLV_HASHTABLE	U(0x00000010)
90 #define RPROC_TLV_PKEYINFO	U(0x00000011)
91 
92 #define RPROC_PLAT_TLV_TYPE_MIN	U(0x00010000)
93 #define RPROC_PLAT_TLV_TYPE_MAX	U(0x00020000)
94 
95 #define RPROC_TLV_SIGNTYPE_LGTH U(1)
96 
97 #define ROUNDUP_64(x) ROUNDUP((x), sizeof(uint64_t))
98 
99 /*
100  * struct remoteproc_tlv - Type-Length-Value structure
101  * @type: type of data
102  * @length: size of the data.
103  * @value: pointer to the data.
104  */
105 struct remoteproc_tlv {
106 	uint32_t type;
107 	uint32_t length;
108 	uint8_t value[];
109 };
110 
111 /*
112  * struct remoteproc_segment - program header with hash structure
113  * @phdr: program header
114  * @hash: hash associated to the program segment.
115  */
116 struct remoteproc_segment {
117 	Elf32_Phdr phdr;
118 	uint8_t hash[TEE_SHA256_HASH_SIZE];
119 };
120 
121 /*
122  * struct remoteproc_fw_hdr - firmware header
123  * @magic:        Magic number, must be equal to RPROC_HDR_MAGIC
124  * @version:      Version of the header (must be 1)
125  * @tlv_len:      Generic meta data chunk (TLV format)
126  * @sign_len:     Signature chunk byte length
127  * @img_len:      Firmware image chunk byte length
128  */
129 struct remoteproc_fw_hdr {
130 	uint32_t magic;
131 	uint32_t version;
132 	uint32_t tlv_len;
133 	uint32_t sign_len;
134 	uint32_t img_len;
135 };
136 
137 #define FW_TLV_PTR(img, hdr)  ((img) + sizeof(*(hdr)))
138 #define FW_SIGN_PTR(img, hdr) ({					\
139 		struct remoteproc_fw_hdr *__hdr = (hdr);		\
140 									\
141 		FW_TLV_PTR((img), __hdr) + ROUNDUP_64(__hdr->tlv_len);	\
142 	})
143 #define FW_IMG_PTR(img, hdr) ({						   \
144 		struct remoteproc_fw_hdr *___hdr = (hdr);		   \
145 									   \
146 		FW_SIGN_PTR((img), ___hdr) + ROUNDUP_64(___hdr->sign_len); \
147 	})
148 
149 /*
150  * struct remoteproc_sig_algo - signature algorithm information
151  * @sign_type: Header signature type
152  * @id:        Signature algorithm identifier TEE_ALG_*
153  * @hash_len:  Signature hash length
154  */
155 struct remoteproc_sig_algo {
156 	enum remoteproc_sign_type sign_type;
157 	uint32_t id;
158 	size_t hash_len;
159 };
160 
161 /*
162  * struct remoteproc_context - firmware context
163  * @rproc_id:    Unique Id of the processor
164  * @sec_cpy:     Location of a secure copy of the header, TLVs and signature
165  * @tlvs:        Location of a secure copy of the firmware TLVs
166  * @tlvs_sz:     Byte size of the firmware TLVs blob.
167  * @fw_img:      Firmware image
168  * @fw_img_sz:   Byte size of the firmware image
169  * @hash_table:  Location of a copy of the segment's hash table
170  * @nb_segment:  number of segment to load
171  * @state:       Remote-processor state
172  * @hw_fmt:      Image format capabilities of the remoteproc PTA
173  * @hw_img_prot: Image protection capabilities of the remoteproc PTA
174  * @link:        Linked list element
175  */
176 struct remoteproc_context {
177 	uint32_t rproc_id;
178 	uint8_t *sec_cpy;
179 	uint8_t *tlvs;
180 	size_t tlvs_sz;
181 	uint8_t *fw_img;
182 	size_t fw_img_sz;
183 	struct remoteproc_segment *hash_table;
184 	uint32_t nb_segment;
185 	enum remoteproc_state state;
186 	uint32_t hw_fmt;
187 	uint32_t hw_img_prot;
188 	TAILQ_ENTRY(remoteproc_context) link;
189 };
190 
191 TAILQ_HEAD(remoteproc_firmware_head, remoteproc_context);
192 
193 static struct remoteproc_firmware_head firmware_head =
194 	TAILQ_HEAD_INITIALIZER(firmware_head);
195 
196 static const struct remoteproc_sig_algo rproc_ta_sign_algo[] = {
197 	{
198 		.sign_type = RPROC_RSASSA_PKCS1_v1_5_SHA256,
199 		.id = TEE_ALG_RSASSA_PKCS1_V1_5_SHA256,
200 		.hash_len = TEE_SHA256_HASH_SIZE,
201 	},
202 	{
203 		.sign_type = RPROC_ECDSA_SHA256,
204 		.id = TEE_ALG_ECDSA_P256,
205 		.hash_len = TEE_SHA256_HASH_SIZE,
206 	},
207 };
208 
209 static size_t session_refcount;
210 static TEE_TASessionHandle pta_session;
211 
212 static void remoteproc_header_dump(struct remoteproc_fw_hdr __maybe_unused *hdr)
213 {
214 	DMSG("magic :\t%#"PRIx32, hdr->magic);
215 	DMSG("version :\t%#"PRIx32, hdr->version);
216 	DMSG("tlv_len :\t%#"PRIx32, hdr->tlv_len);
217 	DMSG("sign_len :\t%#"PRIx32, hdr->sign_len);
218 	DMSG("img_len :\t%#"PRIx32, hdr->img_len);
219 }
220 
221 static TEE_Result remoteproc_get_tlv(void *tlv_chunk, size_t tlv_size,
222 				     uint16_t type, uint8_t **value,
223 				     size_t *length)
224 {
225 	uint8_t *p_tlv = (uint8_t *)tlv_chunk;
226 	uint8_t *p_end_tlv = p_tlv + tlv_size;
227 	uint32_t tlv_type = 0;
228 	uint32_t tlv_length = 0;
229 	uint32_t tlv_v = 0;
230 
231 	*value = NULL;
232 	*length = 0;
233 
234 	/* Parse the TLV area */
235 	while (p_tlv < p_end_tlv) {
236 		memcpy(&tlv_v, p_tlv, sizeof(tlv_v));
237 		tlv_type = TEE_U32_FROM_LITTLE_ENDIAN(tlv_v);
238 		memcpy(&tlv_v, p_tlv + RPROC_TLV_LENGTH_OF, sizeof(tlv_v));
239 		tlv_length = TEE_U32_FROM_LITTLE_ENDIAN(tlv_v);
240 		if (tlv_type == type) {
241 			/* The specified TLV has been found */
242 			DMSG("TLV type %#"PRIx32" found, size %#"PRIx32,
243 			     type, tlv_length);
244 			*value = &p_tlv[RPROC_TLV_VALUE_OF];
245 			*length = tlv_length;
246 			if (tlv_length)
247 				return TEE_SUCCESS;
248 			else
249 				return TEE_ERROR_NO_DATA;
250 		}
251 		p_tlv += ROUNDUP_64(sizeof(struct remoteproc_tlv) + tlv_length);
252 	}
253 
254 	return TEE_ERROR_NO_DATA;
255 }
256 
257 static struct remoteproc_context *remoteproc_find_firmware(uint32_t rproc_id)
258 {
259 	struct remoteproc_context *ctx = NULL;
260 
261 	TAILQ_FOREACH(ctx, &firmware_head, link)
262 		if (ctx->rproc_id == rproc_id)
263 			return ctx;
264 
265 	return NULL;
266 }
267 
268 static struct remoteproc_context *remoteproc_add_firmware(uint32_t rproc_id)
269 {
270 	struct remoteproc_context *ctx = NULL;
271 
272 	ctx = TEE_Malloc(sizeof(*ctx), TEE_MALLOC_FILL_ZERO);
273 	if (!ctx)
274 		return NULL;
275 
276 	ctx->rproc_id = rproc_id;
277 
278 	TAILQ_INSERT_TAIL(&firmware_head, ctx, link);
279 
280 	return ctx;
281 }
282 
283 static const struct remoteproc_sig_algo *remoteproc_get_algo(uint32_t sign_type)
284 {
285 	unsigned int i = 0;
286 
287 	for (i = 0; i < ARRAY_SIZE(rproc_ta_sign_algo); i++)
288 		if (sign_type == rproc_ta_sign_algo[i].sign_type)
289 			return &rproc_ta_sign_algo[i];
290 
291 	return NULL;
292 }
293 
294 static TEE_Result remoteproc_pta_verify(struct remoteproc_context *ctx,
295 					const struct remoteproc_sig_algo *algo,
296 					uint8_t *hash, uint32_t hash_len)
297 {
298 	TEE_Result res = TEE_ERROR_GENERIC;
299 	struct remoteproc_fw_hdr *hdr = (void *)ctx->sec_cpy;
300 	struct rproc_pta_key_info *keyinfo = NULL;
301 	uint32_t param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
302 					       TEE_PARAM_TYPE_MEMREF_INPUT,
303 					       TEE_PARAM_TYPE_MEMREF_INPUT,
304 					       TEE_PARAM_TYPE_MEMREF_INPUT);
305 	TEE_Param params[TEE_NUM_PARAMS] = { };
306 	size_t length = 0;
307 	uint8_t *tlv_keyinfo = NULL;
308 	uint8_t *sign = NULL;
309 
310 	res = remoteproc_get_tlv(ctx->tlvs, hdr->tlv_len,
311 				 RPROC_TLV_PKEYINFO, &tlv_keyinfo,
312 				 &length);
313 	if (res != TEE_SUCCESS && res != TEE_ERROR_NO_DATA)
314 		return res;
315 
316 	keyinfo = TEE_Malloc(sizeof(*keyinfo) + length, TEE_MALLOC_FILL_ZERO);
317 	if (!keyinfo)
318 		return TEE_ERROR_OUT_OF_MEMORY;
319 
320 	keyinfo->algo = algo->id;
321 	keyinfo->info_size = length;
322 	memcpy(keyinfo->info, tlv_keyinfo, length);
323 
324 	sign = FW_SIGN_PTR(ctx->sec_cpy, hdr);
325 
326 	params[0].value.a = ctx->rproc_id;
327 	params[1].memref.buffer = keyinfo;
328 	params[1].memref.size = rproc_pta_keyinfo_size(keyinfo);
329 	params[2].memref.buffer = hash;
330 	params[2].memref.size = hash_len;
331 	params[3].memref.buffer = sign;
332 	params[3].memref.size = hdr->sign_len;
333 
334 	res = TEE_InvokeTACommand(pta_session, TEE_TIMEOUT_INFINITE,
335 				  PTA_RPROC_VERIFY_DIGEST,
336 				  param_types, params, NULL);
337 	if (res != TEE_SUCCESS)
338 		EMSG("Failed to verify signature, res = %#"PRIx32, res);
339 
340 	TEE_Free(keyinfo);
341 
342 	return res;
343 }
344 
345 static TEE_Result
346 remoteproc_save_fw_header_and_tlvs(struct remoteproc_context *ctx,
347 				   void *fw_orig, uint32_t fw_orig_size)
348 {
349 	struct remoteproc_fw_hdr *hdr = fw_orig;
350 	uint32_t length = 0;
351 
352 	if (!IS_ALIGNED_WITH_TYPE(fw_orig, struct remoteproc_fw_hdr))
353 		return TEE_ERROR_BAD_PARAMETERS;
354 
355 	if (ADD_OVERFLOW(sizeof(*hdr), ROUNDUP_64(hdr->tlv_len), &length) ||
356 	    ADD_OVERFLOW(length, ROUNDUP_64(hdr->sign_len), &length))
357 		return TEE_ERROR_BAD_PARAMETERS;
358 
359 	if (fw_orig_size <= length || !hdr->sign_len || !hdr->tlv_len)
360 		return TEE_ERROR_BAD_PARAMETERS;
361 
362 	remoteproc_header_dump(hdr);
363 
364 	/* Copy the header, the TLVs and the signature in secure memory */
365 	ctx->sec_cpy = TEE_Malloc(length, TEE_MALLOC_FILL_ZERO);
366 	if (!ctx->sec_cpy)
367 		return TEE_ERROR_OUT_OF_MEMORY;
368 
369 	memcpy(ctx->sec_cpy, fw_orig, length);
370 
371 	return TEE_SUCCESS;
372 }
373 
374 static TEE_Result remoteproc_verify_signature(struct remoteproc_context *ctx)
375 {
376 	TEE_OperationHandle op = TEE_HANDLE_NULL;
377 	struct remoteproc_fw_hdr *hdr = (void *)ctx->sec_cpy;
378 	const struct remoteproc_sig_algo *algo = NULL;
379 	TEE_Result res = TEE_ERROR_GENERIC;
380 	uint8_t *tlv_sign_algo = NULL;
381 	size_t length = 0;
382 	uint8_t *hash = NULL;
383 	size_t hash_len = 0;
384 
385 	/* Get the algo type from TLV data */
386 	res = remoteproc_get_tlv(ctx->tlvs, hdr->tlv_len, RPROC_TLV_SIGNTYPE,
387 				 &tlv_sign_algo, &length);
388 
389 	if (res != TEE_SUCCESS || length != RPROC_TLV_SIGNTYPE_LGTH)
390 		return TEE_ERROR_BAD_PARAMETERS;
391 
392 	algo = remoteproc_get_algo(*tlv_sign_algo);
393 	if (!algo) {
394 		EMSG("Unsupported signature type %"PRId8, *tlv_sign_algo);
395 		return TEE_ERROR_NOT_SUPPORTED;
396 	}
397 
398 	/* Compute the header and TLVs hashes */
399 	hash_len = algo->hash_len;
400 	hash = TEE_Malloc(hash_len, TEE_MALLOC_FILL_ZERO);
401 	if (!hash)
402 		return TEE_ERROR_OUT_OF_MEMORY;
403 
404 	res = TEE_AllocateOperation(&op, TEE_ALG_SHA256, TEE_MODE_DIGEST, 0);
405 	if (res != TEE_SUCCESS)
406 		goto free_hash;
407 
408 	TEE_DigestUpdate(op, hdr, sizeof(*hdr));
409 	res = TEE_DigestDoFinal(op, ctx->tlvs, ROUNDUP_64(hdr->tlv_len),
410 				hash, &hash_len);
411 
412 	if (res != TEE_SUCCESS)
413 		goto out;
414 
415 	/*
416 	 * This implementation could be enhanced by providing alternative to
417 	 * verify the signature in the TA. This could be done for instance by
418 	 * getting the key object from secure storage.
419 	 */
420 
421 	/* By default ask the remoteproc PTA to verify the signature. */
422 	res = remoteproc_pta_verify(ctx, algo, hash, hash_len);
423 
424 out:
425 	TEE_FreeOperation(op);
426 free_hash:
427 	TEE_Free(hash);
428 
429 	return res;
430 }
431 
432 static TEE_Result remoteproc_verify_header(struct remoteproc_context *ctx,
433 					   uint32_t fw_orig_size)
434 {
435 	struct remoteproc_fw_hdr *hdr = (void *)ctx->sec_cpy;
436 	uint32_t size = 0;
437 
438 	if (hdr->magic != RPROC_HDR_MAGIC)
439 		return TEE_ERROR_BAD_PARAMETERS;
440 
441 	if (hdr->version != HEADER_VERSION)
442 		return TEE_ERROR_BAD_PARAMETERS;
443 
444 	/*
445 	 * The offsets are aligned to 64 bits format. While the length of each
446 	 * chunks are the effective length, excluding the alignment padding
447 	 * bytes.
448 	 */
449 	if (ADD_OVERFLOW(sizeof(*hdr), ROUNDUP_64(hdr->sign_len), &size) ||
450 	    ADD_OVERFLOW(size, ROUNDUP_64(hdr->img_len), &size) ||
451 	    ADD_OVERFLOW(size, ROUNDUP_64(hdr->tlv_len), &size) ||
452 	    fw_orig_size != size)
453 		return TEE_ERROR_BAD_PARAMETERS;
454 
455 	return TEE_SUCCESS;
456 }
457 
458 static TEE_Result get_rproc_pta_capabilities(struct remoteproc_context *ctx)
459 {
460 	uint32_t param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
461 					       TEE_PARAM_TYPE_VALUE_OUTPUT,
462 					       TEE_PARAM_TYPE_VALUE_OUTPUT,
463 					       TEE_PARAM_TYPE_NONE);
464 	TEE_Param params[TEE_NUM_PARAMS] = { };
465 	TEE_Result res = TEE_ERROR_GENERIC;
466 
467 	params[0].value.a = ctx->rproc_id;
468 
469 	res = TEE_InvokeTACommand(pta_session, TEE_TIMEOUT_INFINITE,
470 				  PTA_RPROC_HW_CAPABILITIES,
471 				  param_types, params, NULL);
472 	if (res)
473 		return res;
474 
475 	ctx->hw_fmt = params[1].value.a;
476 	ctx->hw_img_prot = params[2].value.a;
477 
478 	return TEE_SUCCESS;
479 }
480 
481 static TEE_Result remoteproc_verify_firmware(struct remoteproc_context *ctx,
482 					     uint8_t *fw_orig,
483 					     uint32_t fw_orig_size)
484 {
485 	struct remoteproc_fw_hdr *hdr = NULL;
486 	TEE_Result res = TEE_ERROR_GENERIC;
487 
488 	res = get_rproc_pta_capabilities(ctx);
489 	if (res)
490 		return res;
491 
492 	/* Secure the firmware image depending on strategy */
493 	if (!(ctx->hw_img_prot & PTA_RPROC_HWCAP_PROT_HASH_TABLE) ||
494 	    ctx->hw_fmt != PTA_RPROC_HWCAP_FMT_ELF) {
495 		/*
496 		 * Only hash table for ELF format support implemented
497 		 * in a first step.
498 		 */
499 		return TEE_ERROR_NOT_IMPLEMENTED;
500 	}
501 
502 	res = remoteproc_save_fw_header_and_tlvs(ctx, fw_orig, fw_orig_size);
503 	if (res)
504 		return res;
505 
506 	res = remoteproc_verify_header(ctx, fw_orig_size);
507 	if (res)
508 		goto free_sec_cpy;
509 
510 	hdr = (void *)ctx->sec_cpy;
511 	ctx->tlvs_sz = hdr->tlv_len;
512 	ctx->tlvs = FW_TLV_PTR(ctx->sec_cpy, hdr);
513 
514 	res = remoteproc_verify_signature(ctx);
515 	if (res)
516 		goto free_sec_cpy;
517 
518 	/* Store location of the loadable binary in non-secure memory */
519 	ctx->fw_img_sz = hdr->img_len;
520 	ctx->fw_img = FW_IMG_PTR(fw_orig, hdr);
521 
522 	DMSG("Firmware images addr: %p size: %zu", ctx->fw_img,
523 	     ctx->fw_img_sz);
524 
525 	return TEE_SUCCESS;
526 
527 free_sec_cpy:
528 	TEE_Free(ctx->sec_cpy);
529 	ctx->sec_cpy = NULL;
530 
531 	return res;
532 }
533 
534 static TEE_Result get_hash_table(struct remoteproc_context *ctx)
535 {
536 	TEE_Result res = TEE_ERROR_GENERIC;
537 	uint8_t *tlv_hash = NULL;
538 	struct remoteproc_segment *hash_table = NULL;
539 	size_t length = 0;
540 
541 	/* Get the segment's hash table from TLV data */
542 	res = remoteproc_get_tlv(ctx->tlvs, ctx->tlvs_sz, RPROC_TLV_HASHTABLE,
543 				 &tlv_hash, &length);
544 	if (res)
545 		return res;
546 
547 	if (length % sizeof(struct remoteproc_segment))
548 		return TEE_ERROR_BAD_PARAMETERS;
549 
550 	/* We can not ensure that tlv_hash is memory aligned so make a copy */
551 	hash_table = TEE_Malloc(length, TEE_MALLOC_FILL_ZERO);
552 	if (!hash_table)
553 		return TEE_ERROR_OUT_OF_MEMORY;
554 
555 	memcpy(hash_table, tlv_hash, length);
556 
557 	ctx->hash_table = hash_table;
558 	ctx->nb_segment = length / sizeof(struct remoteproc_segment);
559 
560 	return TEE_SUCCESS;
561 }
562 
563 static TEE_Result get_tlv_images_type(struct remoteproc_context *ctx,
564 				      uint8_t num_img, uint8_t idx,
565 				      uint8_t *img_type)
566 {
567 	TEE_Result res = TEE_ERROR_GENERIC;
568 	uint8_t *tlv_value = NULL;
569 	size_t length = 0;
570 
571 	/* Get the type of the image to load, from TLV data */
572 	res = remoteproc_get_tlv(ctx->tlvs, ctx->tlvs_sz, RPROC_TLV_IMGTYPE,
573 				 &tlv_value, &length);
574 	if (res)
575 		return res;
576 
577 	if (length != (sizeof(*img_type) * num_img))
578 		return TEE_ERROR_BAD_PARAMETERS;
579 
580 	*img_type = tlv_value[idx];
581 
582 	return TEE_SUCCESS;
583 }
584 
585 static TEE_Result get_tlv_images_size(struct remoteproc_context *ctx,
586 				      uint8_t num_img, uint8_t idx,
587 				      uint32_t *img_size)
588 {
589 	TEE_Result res = TEE_ERROR_GENERIC;
590 	uint8_t *tlv_value = NULL;
591 	uint32_t tlv_v = 0;
592 	size_t length = 0;
593 
594 	/* Get the size of the image to load, from TLV data */
595 	res = remoteproc_get_tlv(ctx->tlvs, ctx->tlvs_sz, RPROC_TLV_IMGSIZE,
596 				 &tlv_value, &length);
597 	if (res)
598 		return res;
599 
600 	if (length != (sizeof(*img_size) * num_img))
601 		return TEE_ERROR_BAD_PARAMETERS;
602 
603 	memcpy(&tlv_v, &tlv_value[sizeof(*img_size) * idx], sizeof(tlv_v));
604 	*img_size = TEE_U32_FROM_LITTLE_ENDIAN(tlv_v);
605 
606 	return TEE_SUCCESS;
607 }
608 
609 static TEE_Result get_segment_hash(struct remoteproc_context *ctx, uint8_t *src,
610 				   uint32_t size, uint32_t da,
611 				   uint32_t mem_size, uint8_t **hash)
612 {
613 	struct remoteproc_segment *peh = NULL;
614 	unsigned int i = 0;
615 	unsigned int nb_entry = ctx->nb_segment;
616 
617 	peh = (void *)(ctx->hash_table);
618 
619 	for (i = 0; i < nb_entry; peh++, i++) {
620 		if (peh->phdr.p_paddr != da)
621 			continue;
622 
623 		/*
624 		 * Segment metadata are read from a non-secure memory.
625 		 * Validate them using hash table data stored in secure memory.
626 		 */
627 		if (peh->phdr.p_type != PT_LOAD)
628 			return TEE_ERROR_BAD_PARAMETERS;
629 
630 		if (peh->phdr.p_filesz != size || peh->phdr.p_memsz != mem_size)
631 			return TEE_ERROR_BAD_PARAMETERS;
632 
633 		if (src < ctx->fw_img ||
634 		    src >  (ctx->fw_img + ctx->fw_img_sz) ||
635 		    (src + peh->phdr.p_filesz) > (ctx->fw_img + ctx->fw_img_sz))
636 			return TEE_ERROR_BAD_PARAMETERS;
637 
638 		*hash = peh->hash;
639 
640 		return TEE_SUCCESS;
641 	}
642 
643 	return TEE_ERROR_NO_DATA;
644 }
645 
646 static TEE_Result remoteproc_load_segment(uint8_t *src, uint32_t size,
647 					  uint32_t da, uint32_t mem_size,
648 					  void *priv)
649 {
650 	struct remoteproc_context *ctx = priv;
651 	uint32_t param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
652 					       TEE_PARAM_TYPE_MEMREF_INPUT,
653 					       TEE_PARAM_TYPE_VALUE_INPUT,
654 					       TEE_PARAM_TYPE_MEMREF_INPUT);
655 	TEE_Param params[TEE_NUM_PARAMS] = { };
656 	TEE_Result res = TEE_ERROR_GENERIC;
657 	uint8_t *hash = NULL;
658 
659 	/*
660 	 * Invoke platform remoteproc PTA to load the segment in remote
661 	 * processor memory which is not mapped in the TA space.
662 	 */
663 
664 	DMSG("Load segment %#"PRIx32" size %"PRIu32" (%"PRIu32")", da, size,
665 	     mem_size);
666 
667 	res = get_segment_hash(ctx, src, size, da, mem_size, &hash);
668 	if (res)
669 		return res;
670 
671 	params[0].value.a = ctx->rproc_id;
672 	params[1].memref.buffer = src;
673 	params[1].memref.size = size;
674 	params[2].value.a = da;
675 	params[3].memref.buffer = hash;
676 	params[3].memref.size = TEE_SHA256_HASH_SIZE;
677 
678 	if (size) {
679 		res = TEE_InvokeTACommand(pta_session, TEE_TIMEOUT_INFINITE,
680 					  PTA_RPROC_LOAD_SEGMENT_SHA256,
681 					  param_types, params, NULL);
682 		if (res != TEE_SUCCESS) {
683 			EMSG("Fails to load segment, res = 0x%#"PRIx32, res);
684 			return res;
685 		}
686 	}
687 
688 	/* Fill the rest of the memory with 0 */
689 	if (size < mem_size) {
690 		param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
691 					      TEE_PARAM_TYPE_VALUE_INPUT,
692 					      TEE_PARAM_TYPE_VALUE_INPUT,
693 					      TEE_PARAM_TYPE_VALUE_INPUT);
694 		params[1].value.a = da + size;
695 		params[2].value.a = mem_size - size;
696 		params[3].value.a = 0;
697 
698 		res = TEE_InvokeTACommand(pta_session, TEE_TIMEOUT_INFINITE,
699 					  PTA_RPROC_SET_MEMORY,
700 					  param_types, params, NULL);
701 		if (res != TEE_SUCCESS)
702 			EMSG("Fails to clear segment, res = %#"PRIx32, res);
703 	}
704 
705 	return res;
706 }
707 
708 static TEE_Result remoteproc_load_elf(struct remoteproc_context *ctx)
709 {
710 	TEE_Result res = TEE_ERROR_GENERIC;
711 	unsigned int num_img = 0;
712 	unsigned int i = 0;
713 	uint8_t img_type = REMOTEPROC_INVALID_TYPE;
714 	uint32_t img_size = 0;
715 	uint8_t *tlv = NULL;
716 	int32_t offset = 0;
717 	size_t length = 0;
718 
719 	res = e32_parse_ehdr(ctx->fw_img, ctx->fw_img_sz);
720 	if (res) {
721 		EMSG("Failed to parse firmware, res = %#"PRIx32, res);
722 		return res;
723 	}
724 
725 	res = get_hash_table(ctx);
726 	if (res)
727 		return res;
728 
729 	/* Get the number of firmware images to load */
730 	res = remoteproc_get_tlv(ctx->tlvs, ctx->tlvs_sz, RPROC_TLV_NUM_IMG,
731 				 &tlv, &length);
732 	if (res)
733 		goto out;
734 	if (length != sizeof(uint8_t)) {
735 		res = TEE_ERROR_BAD_FORMAT;
736 		goto out;
737 	}
738 
739 	num_img = *tlv;
740 	if (!num_img) {
741 		res = TEE_ERROR_NO_DATA;
742 		goto out;
743 	}
744 
745 	for (i = 0; i < num_img; i++) {
746 		res = get_tlv_images_type(ctx, num_img, i, &img_type);
747 		if (res)
748 			goto out;
749 		if (img_type != REMOTEPROC_ELF_TYPE) {
750 			res = TEE_ERROR_BAD_FORMAT;
751 			goto out;
752 		}
753 
754 		res = get_tlv_images_size(ctx, num_img, i, &img_size);
755 		if (res)
756 			goto out;
757 
758 		res = e32_parser_load_elf_image(ctx->fw_img + offset, img_size,
759 						remoteproc_load_segment, ctx);
760 		if (res)
761 			goto out;
762 
763 		offset += img_size;
764 	}
765 
766 out:
767 	/* Should we clean-up the memories in case of fail ? */
768 	TEE_Free(ctx->hash_table);
769 	ctx->hash_table = NULL;
770 
771 	return res;
772 }
773 
774 static TEE_Result remoteproc_load_fw(uint32_t pt,
775 				     TEE_Param params[TEE_NUM_PARAMS])
776 {
777 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
778 						TEE_PARAM_TYPE_MEMREF_INPUT,
779 						TEE_PARAM_TYPE_NONE,
780 						TEE_PARAM_TYPE_NONE);
781 	struct remoteproc_context *ctx = NULL;
782 	uint32_t rproc_id = params[0].value.a;
783 	TEE_Result res = TEE_ERROR_GENERIC;
784 
785 	if (pt != exp_pt)
786 		return TEE_ERROR_BAD_PARAMETERS;
787 
788 	ctx = remoteproc_find_firmware(rproc_id);
789 	if (!ctx)
790 		ctx = remoteproc_add_firmware(rproc_id);
791 	if (!ctx)
792 		return TEE_ERROR_OUT_OF_MEMORY;
793 
794 	if (ctx->state != REMOTEPROC_OFF)
795 		return TEE_ERROR_BAD_STATE;
796 
797 	if (!params[1].memref.buffer || !params[1].memref.size)
798 		return TEE_ERROR_BAD_PARAMETERS;
799 
800 	DMSG("Got base addr: %p size %#zx", params[1].memref.buffer,
801 	     params[1].memref.size);
802 
803 	res = remoteproc_verify_firmware(ctx, params[1].memref.buffer,
804 					 params[1].memref.size);
805 	if (res) {
806 		EMSG("Can't Authenticate the firmware (res = %#"PRIx32")", res);
807 		goto out;
808 	}
809 
810 	res = remoteproc_load_elf(ctx);
811 	if (res)
812 		goto out;
813 
814 	ctx->state = REMOTEPROC_LOADED;
815 
816 out:
817 	/* Clear reference to firmware image from shared memory */
818 	ctx->fw_img = NULL;
819 	ctx->fw_img_sz = 0;
820 	ctx->nb_segment = 0;
821 
822 	/* Free allocated memories */
823 	TEE_Free(ctx->sec_cpy);
824 	ctx->sec_cpy = NULL;
825 
826 	return res;
827 }
828 
829 static TEE_Result remoteproc_start_fw(uint32_t pt,
830 				      TEE_Param params[TEE_NUM_PARAMS])
831 {
832 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
833 						TEE_PARAM_TYPE_NONE,
834 						TEE_PARAM_TYPE_NONE,
835 						TEE_PARAM_TYPE_NONE);
836 	struct remoteproc_context *ctx = NULL;
837 	uint32_t rproc_id = params[0].value.a;
838 	TEE_Result res = TEE_ERROR_GENERIC;
839 
840 	if (pt != exp_pt)
841 		return TEE_ERROR_BAD_PARAMETERS;
842 
843 	ctx = remoteproc_find_firmware(rproc_id);
844 	if (!ctx)
845 		return TEE_ERROR_BAD_PARAMETERS;
846 
847 	switch (ctx->state) {
848 	case REMOTEPROC_OFF:
849 		res = TEE_ERROR_BAD_STATE;
850 		break;
851 	case REMOTEPROC_STARTED:
852 		res = TEE_SUCCESS;
853 		break;
854 	case REMOTEPROC_LOADED:
855 		res = TEE_InvokeTACommand(pta_session, TEE_TIMEOUT_INFINITE,
856 					  PTA_RPROC_FIRMWARE_START,
857 					  pt, params, NULL);
858 		if (res == TEE_SUCCESS)
859 			ctx->state = REMOTEPROC_STARTED;
860 		break;
861 	default:
862 		res = TEE_ERROR_BAD_STATE;
863 	}
864 
865 	return res;
866 }
867 
868 static TEE_Result remoteproc_stop_fw(uint32_t pt,
869 				     TEE_Param params[TEE_NUM_PARAMS])
870 {
871 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
872 						TEE_PARAM_TYPE_NONE,
873 						TEE_PARAM_TYPE_NONE,
874 						TEE_PARAM_TYPE_NONE);
875 	struct remoteproc_context *ctx = NULL;
876 	uint32_t rproc_id = params[0].value.a;
877 	TEE_Result res = TEE_ERROR_GENERIC;
878 
879 	if (pt != exp_pt)
880 		return TEE_ERROR_BAD_PARAMETERS;
881 
882 	ctx = remoteproc_find_firmware(rproc_id);
883 	if (!ctx)
884 		return TEE_ERROR_BAD_PARAMETERS;
885 
886 	switch (ctx->state) {
887 	case REMOTEPROC_LOADED:
888 		res = TEE_ERROR_BAD_STATE;
889 		break;
890 	case REMOTEPROC_OFF:
891 		res = TEE_SUCCESS;
892 		break;
893 	case REMOTEPROC_STARTED:
894 		res = TEE_InvokeTACommand(pta_session, TEE_TIMEOUT_INFINITE,
895 					  PTA_RPROC_FIRMWARE_STOP,
896 					  pt, params, NULL);
897 		if (res == TEE_SUCCESS)
898 			ctx->state = REMOTEPROC_OFF;
899 		break;
900 	default:
901 		res = TEE_ERROR_BAD_STATE;
902 	}
903 
904 	return res;
905 }
906 
907 TEE_Result TA_CreateEntryPoint(void)
908 {
909 	return TEE_SUCCESS;
910 }
911 
912 void TA_DestroyEntryPoint(void)
913 {
914 }
915 
916 /*
917  * TA_OpenSessionEntryPoint: open a TA session associated to a remote processor
918  * to manage.
919  *
920  * [in] params[0].value.a:	Unique 32bit remote processor identifier
921  */
922 TEE_Result TA_OpenSessionEntryPoint(uint32_t pt,
923 				    TEE_Param params[TEE_NUM_PARAMS],
924 				    void **sess __unused)
925 {
926 	static const TEE_UUID uuid = PTA_RPROC_UUID;
927 	TEE_Result res = TEE_ERROR_GENERIC;
928 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
929 						TEE_PARAM_TYPE_NONE,
930 						TEE_PARAM_TYPE_NONE,
931 						TEE_PARAM_TYPE_NONE);
932 
933 	if (pt != exp_pt)
934 		return TEE_ERROR_BAD_PARAMETERS;
935 
936 	if (!session_refcount) {
937 		res = TEE_OpenTASession(&uuid, TEE_TIMEOUT_INFINITE, pt, params,
938 					&pta_session, NULL);
939 		if (res)
940 			return res;
941 	}
942 
943 	session_refcount++;
944 
945 	return TEE_SUCCESS;
946 }
947 
948 void TA_CloseSessionEntryPoint(void *sess __unused)
949 {
950 	session_refcount--;
951 
952 	if (!session_refcount)
953 		TEE_CloseTASession(pta_session);
954 }
955 
956 TEE_Result TA_InvokeCommandEntryPoint(void *sess __unused, uint32_t cmd_id,
957 				      uint32_t pt,
958 				      TEE_Param params[TEE_NUM_PARAMS])
959 {
960 	switch (cmd_id) {
961 	case TA_RPROC_CMD_LOAD_FW:
962 		return remoteproc_load_fw(pt, params);
963 	case TA_RPROC_CMD_START_FW:
964 		return remoteproc_start_fw(pt, params);
965 	case TA_RPROC_CMD_STOP_FW:
966 		return remoteproc_stop_fw(pt, params);
967 	case TA_RPROC_CMD_GET_RSC_TABLE:
968 		return TEE_ERROR_NOT_IMPLEMENTED;
969 	case TA_RPROC_CMD_GET_COREDUMP:
970 		return TEE_ERROR_NOT_IMPLEMENTED;
971 	default:
972 		return TEE_ERROR_BAD_PARAMETERS;
973 	}
974 }
975