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