xref: /optee_os/ta/remoteproc/src/remoteproc_core.c (revision 14a1a72ba445a12c4680c14379d1602c1acbc954)
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 
remoteproc_header_dump(struct remoteproc_fw_hdr __maybe_unused * hdr)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 /*
227  * This function loads output data in @value and @length in 2 cases.
228  * Upon TEE_SUCCESS, output arguments provide the requested TLV information.
229  * Upon TEE_ERROR_NO_DATA, @value is set to NULL and @length to 0.
230  */
remoteproc_get_tlv(void * tlv_chunk,size_t tlv_size,uint16_t type,uint8_t ** value,size_t * length)231 static TEE_Result remoteproc_get_tlv(void *tlv_chunk, size_t tlv_size,
232 				     uint16_t type, uint8_t **value,
233 				     size_t *length)
234 {
235 	uint8_t *p_tlv = (uint8_t *)tlv_chunk;
236 	uint8_t *p_end_tlv = p_tlv + tlv_size;
237 	uint32_t tlv_type = 0;
238 	uint32_t tlv_length = 0;
239 	uint32_t tlv_v = 0;
240 	uintptr_t tmp_p_tlv = 0;
241 
242 	*value = NULL;
243 	*length = 0;
244 
245 	/* Parse the TLV area */
246 	while (p_tlv + RPROC_TLV_VALUE_OF <= p_end_tlv) {
247 		memcpy(&tlv_v, p_tlv, sizeof(tlv_v));
248 		tlv_type = TEE_U32_FROM_LITTLE_ENDIAN(tlv_v);
249 		memcpy(&tlv_v, p_tlv + RPROC_TLV_LENGTH_OF, sizeof(tlv_v));
250 		p_tlv += RPROC_TLV_VALUE_OF;
251 		tlv_length = TEE_U32_FROM_LITTLE_ENDIAN(tlv_v);
252 		if (ADD_OVERFLOW((uintptr_t)p_tlv, tlv_length, &tmp_p_tlv))
253 			break;
254 		if (tmp_p_tlv <= (uintptr_t)p_end_tlv && tlv_type == type) {
255 			/* The specified TLV has been found */
256 			DMSG("TLV type %#"PRIx32" found, size %#"PRIx32,
257 			     type, tlv_length);
258 			*value = p_tlv;
259 			*length = tlv_length;
260 			if (tlv_length)
261 				return TEE_SUCCESS;
262 			else
263 				return TEE_ERROR_NO_DATA;
264 		}
265 		p_tlv += ROUNDUP_64(tlv_length);
266 	}
267 
268 	return TEE_ERROR_NO_DATA;
269 }
270 
remoteproc_find_firmware(uint32_t rproc_id)271 static struct remoteproc_context *remoteproc_find_firmware(uint32_t rproc_id)
272 {
273 	struct remoteproc_context *ctx = NULL;
274 
275 	TAILQ_FOREACH(ctx, &firmware_head, link)
276 		if (ctx->rproc_id == rproc_id)
277 			return ctx;
278 
279 	return NULL;
280 }
281 
remoteproc_add_firmware(uint32_t rproc_id)282 static struct remoteproc_context *remoteproc_add_firmware(uint32_t rproc_id)
283 {
284 	struct remoteproc_context *ctx = NULL;
285 
286 	ctx = TEE_Malloc(sizeof(*ctx), TEE_MALLOC_FILL_ZERO);
287 	if (!ctx)
288 		return NULL;
289 
290 	ctx->rproc_id = rproc_id;
291 
292 	TAILQ_INSERT_TAIL(&firmware_head, ctx, link);
293 
294 	return ctx;
295 }
296 
remoteproc_get_algo(uint32_t sign_type)297 static const struct remoteproc_sig_algo *remoteproc_get_algo(uint32_t sign_type)
298 {
299 	unsigned int i = 0;
300 
301 	for (i = 0; i < ARRAY_SIZE(rproc_ta_sign_algo); i++)
302 		if (sign_type == rproc_ta_sign_algo[i].sign_type)
303 			return &rproc_ta_sign_algo[i];
304 
305 	return NULL;
306 }
307 
remoteproc_pta_verify(struct remoteproc_context * ctx,const struct remoteproc_sig_algo * algo,uint8_t * hash,uint32_t hash_len)308 static TEE_Result remoteproc_pta_verify(struct remoteproc_context *ctx,
309 					const struct remoteproc_sig_algo *algo,
310 					uint8_t *hash, uint32_t hash_len)
311 {
312 	TEE_Result res = TEE_ERROR_GENERIC;
313 	struct remoteproc_fw_hdr *hdr = (void *)ctx->sec_cpy;
314 	struct rproc_pta_key_info *keyinfo = NULL;
315 	uint32_t param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
316 					       TEE_PARAM_TYPE_MEMREF_INPUT,
317 					       TEE_PARAM_TYPE_MEMREF_INPUT,
318 					       TEE_PARAM_TYPE_MEMREF_INPUT);
319 	TEE_Param params[TEE_NUM_PARAMS] = { };
320 	size_t length = 0;
321 	uint8_t *tlv_keyinfo = NULL;
322 	uint8_t *sign = NULL;
323 
324 	res = remoteproc_get_tlv(ctx->tlvs, hdr->tlv_len,
325 				 RPROC_TLV_PKEYINFO, &tlv_keyinfo,
326 				 &length);
327 	if (res != TEE_SUCCESS && res != TEE_ERROR_NO_DATA)
328 		return res;
329 
330 	keyinfo = TEE_Malloc(sizeof(*keyinfo) + length, TEE_MALLOC_FILL_ZERO);
331 	if (!keyinfo)
332 		return TEE_ERROR_OUT_OF_MEMORY;
333 
334 	keyinfo->algo = algo->id;
335 	keyinfo->info_size = length;
336 	memcpy(keyinfo->info, tlv_keyinfo, length);
337 
338 	sign = FW_SIGN_PTR(ctx->sec_cpy, hdr);
339 
340 	params[0].value.a = ctx->rproc_id;
341 	params[1].memref.buffer = keyinfo;
342 	params[1].memref.size = rproc_pta_keyinfo_size(keyinfo);
343 	params[2].memref.buffer = hash;
344 	params[2].memref.size = hash_len;
345 	params[3].memref.buffer = sign;
346 	params[3].memref.size = hdr->sign_len;
347 
348 	res = TEE_InvokeTACommand(pta_session, TEE_TIMEOUT_INFINITE,
349 				  PTA_RPROC_VERIFY_DIGEST,
350 				  param_types, params, NULL);
351 	if (res != TEE_SUCCESS)
352 		EMSG("Failed to verify signature, res = %#"PRIx32, res);
353 
354 	TEE_Free(keyinfo);
355 
356 	return res;
357 }
358 
359 static TEE_Result
remoteproc_save_fw_header_and_tlvs(struct remoteproc_context * ctx,void * fw_orig,uint32_t fw_orig_size)360 remoteproc_save_fw_header_and_tlvs(struct remoteproc_context *ctx,
361 				   void *fw_orig, uint32_t fw_orig_size)
362 {
363 	struct remoteproc_fw_hdr *hdr = fw_orig;
364 	uint32_t length = 0;
365 
366 	if (!IS_ALIGNED_WITH_TYPE(fw_orig, struct remoteproc_fw_hdr))
367 		return TEE_ERROR_BAD_PARAMETERS;
368 
369 	if (ADD_OVERFLOW(sizeof(*hdr), ROUNDUP_64(hdr->tlv_len), &length) ||
370 	    ADD_OVERFLOW(length, ROUNDUP_64(hdr->sign_len), &length))
371 		return TEE_ERROR_BAD_PARAMETERS;
372 
373 	if (fw_orig_size <= length || !hdr->sign_len || !hdr->tlv_len)
374 		return TEE_ERROR_BAD_PARAMETERS;
375 
376 	remoteproc_header_dump(hdr);
377 
378 	/* Copy the header, the TLVs and the signature in secure memory */
379 	ctx->sec_cpy = TEE_Malloc(length, TEE_MALLOC_FILL_ZERO);
380 	if (!ctx->sec_cpy)
381 		return TEE_ERROR_OUT_OF_MEMORY;
382 
383 	memcpy(ctx->sec_cpy, fw_orig, length);
384 
385 	return TEE_SUCCESS;
386 }
387 
remoteproc_verify_signature(struct remoteproc_context * ctx)388 static TEE_Result remoteproc_verify_signature(struct remoteproc_context *ctx)
389 {
390 	TEE_OperationHandle op = TEE_HANDLE_NULL;
391 	struct remoteproc_fw_hdr *hdr = (void *)ctx->sec_cpy;
392 	const struct remoteproc_sig_algo *algo = NULL;
393 	TEE_Result res = TEE_ERROR_GENERIC;
394 	uint8_t *tlv_sign_algo = NULL;
395 	size_t length = 0;
396 	uint8_t *hash = NULL;
397 	size_t hash_len = 0;
398 
399 	/* Get the algo type from TLV data */
400 	res = remoteproc_get_tlv(ctx->tlvs, hdr->tlv_len, RPROC_TLV_SIGNTYPE,
401 				 &tlv_sign_algo, &length);
402 
403 	if (res != TEE_SUCCESS || length != RPROC_TLV_SIGNTYPE_LGTH)
404 		return TEE_ERROR_BAD_PARAMETERS;
405 
406 	algo = remoteproc_get_algo(*tlv_sign_algo);
407 	if (!algo) {
408 		EMSG("Unsupported signature type %"PRId8, *tlv_sign_algo);
409 		return TEE_ERROR_NOT_SUPPORTED;
410 	}
411 
412 	/* Compute the header and TLVs hashes */
413 	hash_len = algo->hash_len;
414 	hash = TEE_Malloc(hash_len, TEE_MALLOC_FILL_ZERO);
415 	if (!hash)
416 		return TEE_ERROR_OUT_OF_MEMORY;
417 
418 	res = TEE_AllocateOperation(&op, TEE_ALG_SHA256, TEE_MODE_DIGEST, 0);
419 	if (res != TEE_SUCCESS)
420 		goto free_hash;
421 
422 	TEE_DigestUpdate(op, hdr, sizeof(*hdr));
423 	res = TEE_DigestDoFinal(op, ctx->tlvs, ROUNDUP_64(hdr->tlv_len),
424 				hash, &hash_len);
425 
426 	if (res != TEE_SUCCESS)
427 		goto out;
428 
429 	/*
430 	 * This implementation could be enhanced by providing alternative to
431 	 * verify the signature in the TA. This could be done for instance by
432 	 * getting the key object from secure storage.
433 	 */
434 
435 	/* By default ask the remoteproc PTA to verify the signature. */
436 	res = remoteproc_pta_verify(ctx, algo, hash, hash_len);
437 
438 out:
439 	TEE_FreeOperation(op);
440 free_hash:
441 	TEE_Free(hash);
442 
443 	return res;
444 }
445 
remoteproc_verify_header(struct remoteproc_context * ctx,uint32_t fw_orig_size)446 static TEE_Result remoteproc_verify_header(struct remoteproc_context *ctx,
447 					   uint32_t fw_orig_size)
448 {
449 	struct remoteproc_fw_hdr *hdr = (void *)ctx->sec_cpy;
450 	uint32_t size = 0;
451 
452 	if (hdr->magic != RPROC_HDR_MAGIC)
453 		return TEE_ERROR_BAD_PARAMETERS;
454 
455 	if (hdr->version != HEADER_VERSION)
456 		return TEE_ERROR_BAD_PARAMETERS;
457 
458 	/*
459 	 * The offsets are aligned to 64 bits format. While the length of each
460 	 * chunks are the effective length, excluding the alignment padding
461 	 * bytes.
462 	 */
463 	if (ADD_OVERFLOW(sizeof(*hdr), ROUNDUP_64(hdr->sign_len), &size) ||
464 	    ADD_OVERFLOW(size, ROUNDUP_64(hdr->img_len), &size) ||
465 	    ADD_OVERFLOW(size, ROUNDUP_64(hdr->tlv_len), &size) ||
466 	    fw_orig_size != size)
467 		return TEE_ERROR_BAD_PARAMETERS;
468 
469 	return TEE_SUCCESS;
470 }
471 
get_rproc_pta_capabilities(struct remoteproc_context * ctx)472 static TEE_Result get_rproc_pta_capabilities(struct remoteproc_context *ctx)
473 {
474 	uint32_t param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
475 					       TEE_PARAM_TYPE_VALUE_OUTPUT,
476 					       TEE_PARAM_TYPE_VALUE_OUTPUT,
477 					       TEE_PARAM_TYPE_NONE);
478 	TEE_Param params[TEE_NUM_PARAMS] = { };
479 	TEE_Result res = TEE_ERROR_GENERIC;
480 
481 	params[0].value.a = ctx->rproc_id;
482 
483 	res = TEE_InvokeTACommand(pta_session, TEE_TIMEOUT_INFINITE,
484 				  PTA_RPROC_HW_CAPABILITIES,
485 				  param_types, params, NULL);
486 	if (res)
487 		return res;
488 
489 	ctx->hw_fmt = params[1].value.a;
490 	ctx->hw_img_prot = params[2].value.a;
491 
492 	return TEE_SUCCESS;
493 }
494 
remoteproc_verify_firmware(struct remoteproc_context * ctx,uint8_t * fw_orig,uint32_t fw_orig_size)495 static TEE_Result remoteproc_verify_firmware(struct remoteproc_context *ctx,
496 					     uint8_t *fw_orig,
497 					     uint32_t fw_orig_size)
498 {
499 	struct remoteproc_fw_hdr *hdr = NULL;
500 	TEE_Result res = TEE_ERROR_GENERIC;
501 
502 	res = get_rproc_pta_capabilities(ctx);
503 	if (res)
504 		return res;
505 
506 	/* Secure the firmware image depending on strategy */
507 	if (!(ctx->hw_img_prot & PTA_RPROC_HWCAP_PROT_HASH_TABLE) ||
508 	    ctx->hw_fmt != PTA_RPROC_HWCAP_FMT_ELF) {
509 		/*
510 		 * Only hash table for ELF format support implemented
511 		 * in a first step.
512 		 */
513 		return TEE_ERROR_NOT_IMPLEMENTED;
514 	}
515 
516 	res = remoteproc_save_fw_header_and_tlvs(ctx, fw_orig, fw_orig_size);
517 	if (res)
518 		return res;
519 
520 	res = remoteproc_verify_header(ctx, fw_orig_size);
521 	if (res)
522 		goto free_sec_cpy;
523 
524 	hdr = (void *)ctx->sec_cpy;
525 	ctx->tlvs_sz = hdr->tlv_len;
526 	ctx->tlvs = FW_TLV_PTR(ctx->sec_cpy, hdr);
527 
528 	res = remoteproc_verify_signature(ctx);
529 	if (res)
530 		goto free_sec_cpy;
531 
532 	/* Store location of the loadable binary in non-secure memory */
533 	ctx->fw_img_sz = hdr->img_len;
534 	ctx->fw_img = FW_IMG_PTR(fw_orig, hdr);
535 
536 	DMSG("Firmware images addr: %p size: %zu", ctx->fw_img,
537 	     ctx->fw_img_sz);
538 
539 	return TEE_SUCCESS;
540 
541 free_sec_cpy:
542 	TEE_Free(ctx->sec_cpy);
543 	ctx->sec_cpy = NULL;
544 
545 	return res;
546 }
547 
remoteproc_da_to_pa(uint32_t da,size_t size,struct remoteproc_context * ctx)548 static paddr_t remoteproc_da_to_pa(uint32_t da, size_t size,
549 				   struct remoteproc_context *ctx)
550 {
551 	uint32_t param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
552 					       TEE_PARAM_TYPE_VALUE_INPUT,
553 					       TEE_PARAM_TYPE_VALUE_INPUT,
554 					       TEE_PARAM_TYPE_VALUE_OUTPUT);
555 	TEE_Param params[TEE_NUM_PARAMS] = { };
556 	TEE_Result res = TEE_ERROR_GENERIC;
557 	paddr_t pa = 0;
558 
559 	/*
560 	 * The ELF file contains remote processor device addresses, that refer
561 	 * to the remote processor memory space.
562 	 * A translation is needed to get the corresponding physical address.
563 	 */
564 
565 	params[0].value.a = ctx->rproc_id;
566 	params[1].value.a = da;
567 	params[2].value.a = size;
568 
569 	res = TEE_InvokeTACommand(pta_session, TEE_TIMEOUT_INFINITE,
570 				  PTA_RPROC_FIRMWARE_DA_TO_PA,
571 				  param_types, params, NULL);
572 	if (res != TEE_SUCCESS) {
573 		EMSG("Failed to translate device address %#"PRIx32, da);
574 		return 0;
575 	}
576 
577 	pa = (paddr_t)reg_pair_to_64(params[3].value.b, params[3].value.a);
578 
579 	/* Assert that the pa address is not 0 */
580 	assert(pa);
581 
582 	return pa;
583 }
584 
remoteproc_parse_rsc_table(struct remoteproc_context * ctx,uint8_t * fw_img,size_t fw_img_sz,paddr_t * rsc_pa,size_t * rsc_size)585 static TEE_Result remoteproc_parse_rsc_table(struct remoteproc_context *ctx,
586 					     uint8_t *fw_img, size_t fw_img_sz,
587 					     paddr_t *rsc_pa,
588 					     size_t *rsc_size)
589 {
590 	uint32_t da = 0;
591 	TEE_Result res = TEE_ERROR_GENERIC;
592 	Elf32_Word size = 0;
593 
594 	res = e32_parser_find_rsc_table(fw_img, fw_img_sz, &da, &size);
595 	if (res)
596 		return res;
597 
598 	DMSG("Resource table device address %#"PRIx32" size %#"PRIx32,
599 	     da, size);
600 
601 	*rsc_pa = remoteproc_da_to_pa(da, size, ctx);
602 	if (!*rsc_pa)
603 		return TEE_ERROR_ACCESS_DENIED;
604 
605 	*rsc_size = size;
606 
607 	return TEE_SUCCESS;
608 }
609 
get_hash_table(struct remoteproc_context * ctx)610 static TEE_Result get_hash_table(struct remoteproc_context *ctx)
611 {
612 	TEE_Result res = TEE_ERROR_GENERIC;
613 	uint8_t *tlv_hash = NULL;
614 	struct remoteproc_segment *hash_table = NULL;
615 	size_t length = 0;
616 
617 	/* Get the segment's hash table from TLV data */
618 	res = remoteproc_get_tlv(ctx->tlvs, ctx->tlvs_sz, RPROC_TLV_HASHTABLE,
619 				 &tlv_hash, &length);
620 	if (res)
621 		return res;
622 
623 	if (length % sizeof(struct remoteproc_segment))
624 		return TEE_ERROR_BAD_PARAMETERS;
625 
626 	/* We can not ensure that tlv_hash is memory aligned so make a copy */
627 	hash_table = TEE_Malloc(length, TEE_MALLOC_FILL_ZERO);
628 	if (!hash_table)
629 		return TEE_ERROR_OUT_OF_MEMORY;
630 
631 	memcpy(hash_table, tlv_hash, length);
632 
633 	ctx->hash_table = hash_table;
634 	ctx->nb_segment = length / sizeof(struct remoteproc_segment);
635 
636 	return TEE_SUCCESS;
637 }
638 
get_tlv_images_type(struct remoteproc_context * ctx,uint8_t num_img,uint8_t idx,uint8_t * img_type)639 static TEE_Result get_tlv_images_type(struct remoteproc_context *ctx,
640 				      uint8_t num_img, uint8_t idx,
641 				      uint8_t *img_type)
642 {
643 	TEE_Result res = TEE_ERROR_GENERIC;
644 	uint8_t *tlv_value = NULL;
645 	size_t length = 0;
646 
647 	/* Get the type of the image to load, from TLV data */
648 	res = remoteproc_get_tlv(ctx->tlvs, ctx->tlvs_sz, RPROC_TLV_IMGTYPE,
649 				 &tlv_value, &length);
650 	if (res)
651 		return res;
652 
653 	if (length != (sizeof(*img_type) * num_img))
654 		return TEE_ERROR_BAD_PARAMETERS;
655 
656 	*img_type = tlv_value[idx];
657 
658 	return TEE_SUCCESS;
659 }
660 
get_tlv_images_size(struct remoteproc_context * ctx,uint8_t num_img,uint8_t idx,uint32_t * img_size)661 static TEE_Result get_tlv_images_size(struct remoteproc_context *ctx,
662 				      uint8_t num_img, uint8_t idx,
663 				      uint32_t *img_size)
664 {
665 	TEE_Result res = TEE_ERROR_GENERIC;
666 	uint8_t *tlv_value = NULL;
667 	uint32_t tlv_v = 0;
668 	size_t length = 0;
669 
670 	/* Get the size of the image to load, from TLV data */
671 	res = remoteproc_get_tlv(ctx->tlvs, ctx->tlvs_sz, RPROC_TLV_IMGSIZE,
672 				 &tlv_value, &length);
673 	if (res)
674 		return res;
675 
676 	if (length != (sizeof(*img_size) * num_img))
677 		return TEE_ERROR_BAD_PARAMETERS;
678 
679 	memcpy(&tlv_v, &tlv_value[sizeof(*img_size) * idx], sizeof(tlv_v));
680 	*img_size = TEE_U32_FROM_LITTLE_ENDIAN(tlv_v);
681 
682 	return TEE_SUCCESS;
683 }
684 
get_segment_hash(struct remoteproc_context * ctx,uint8_t * src,uint32_t size,uint32_t da,uint32_t mem_size,uint8_t ** hash)685 static TEE_Result get_segment_hash(struct remoteproc_context *ctx, uint8_t *src,
686 				   uint32_t size, uint32_t da,
687 				   uint32_t mem_size, uint8_t **hash)
688 {
689 	struct remoteproc_segment *peh = NULL;
690 	unsigned int i = 0;
691 	unsigned int nb_entry = ctx->nb_segment;
692 
693 	peh = (void *)(ctx->hash_table);
694 
695 	for (i = 0; i < nb_entry; peh++, i++) {
696 		if (peh->phdr.p_paddr != da)
697 			continue;
698 
699 		/*
700 		 * Segment metadata are read from a non-secure memory.
701 		 * Validate them using hash table data stored in secure memory.
702 		 */
703 		if (peh->phdr.p_type != PT_LOAD)
704 			return TEE_ERROR_BAD_PARAMETERS;
705 
706 		if (peh->phdr.p_filesz != size || peh->phdr.p_memsz != mem_size)
707 			return TEE_ERROR_BAD_PARAMETERS;
708 
709 		if (src < ctx->fw_img ||
710 		    src >  (ctx->fw_img + ctx->fw_img_sz) ||
711 		    (src + peh->phdr.p_filesz) > (ctx->fw_img + ctx->fw_img_sz))
712 			return TEE_ERROR_BAD_PARAMETERS;
713 
714 		*hash = peh->hash;
715 
716 		return TEE_SUCCESS;
717 	}
718 
719 	return TEE_ERROR_NO_DATA;
720 }
721 
remoteproc_load_segment(uint8_t * src,uint32_t size,uint32_t da,uint32_t mem_size,void * priv)722 static TEE_Result remoteproc_load_segment(uint8_t *src, uint32_t size,
723 					  uint32_t da, uint32_t mem_size,
724 					  void *priv)
725 {
726 	struct remoteproc_context *ctx = priv;
727 	uint32_t param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
728 					       TEE_PARAM_TYPE_MEMREF_INPUT,
729 					       TEE_PARAM_TYPE_VALUE_INPUT,
730 					       TEE_PARAM_TYPE_MEMREF_INPUT);
731 	TEE_Param params[TEE_NUM_PARAMS] = { };
732 	TEE_Result res = TEE_ERROR_GENERIC;
733 	uint8_t *hash = NULL;
734 
735 	/*
736 	 * Invoke platform remoteproc PTA to load the segment in remote
737 	 * processor memory which is not mapped in the TA space.
738 	 */
739 
740 	DMSG("Load segment %#"PRIx32" size %"PRIu32" (%"PRIu32")", da, size,
741 	     mem_size);
742 
743 	res = get_segment_hash(ctx, src, size, da, mem_size, &hash);
744 	if (res)
745 		return res;
746 
747 	params[0].value.a = ctx->rproc_id;
748 	params[1].memref.buffer = src;
749 	params[1].memref.size = size;
750 	params[2].value.a = da;
751 	params[3].memref.buffer = hash;
752 	params[3].memref.size = TEE_SHA256_HASH_SIZE;
753 
754 	if (size) {
755 		res = TEE_InvokeTACommand(pta_session, TEE_TIMEOUT_INFINITE,
756 					  PTA_RPROC_LOAD_SEGMENT_SHA256,
757 					  param_types, params, NULL);
758 		if (res != TEE_SUCCESS) {
759 			EMSG("Fails to load segment, res = 0x%#"PRIx32, res);
760 			return res;
761 		}
762 	}
763 
764 	/* Fill the rest of the memory with 0 */
765 	if (size < mem_size) {
766 		param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
767 					      TEE_PARAM_TYPE_VALUE_INPUT,
768 					      TEE_PARAM_TYPE_VALUE_INPUT,
769 					      TEE_PARAM_TYPE_VALUE_INPUT);
770 		params[1].value.a = da + size;
771 		params[2].value.a = mem_size - size;
772 		params[3].value.a = 0;
773 
774 		res = TEE_InvokeTACommand(pta_session, TEE_TIMEOUT_INFINITE,
775 					  PTA_RPROC_SET_MEMORY,
776 					  param_types, params, NULL);
777 		if (res != TEE_SUCCESS)
778 			EMSG("Fails to clear segment, res = %#"PRIx32, res);
779 	}
780 
781 	return res;
782 }
783 
remoteproc_load_elf(struct remoteproc_context * ctx)784 static TEE_Result remoteproc_load_elf(struct remoteproc_context *ctx)
785 {
786 	TEE_Result res = TEE_ERROR_GENERIC;
787 	unsigned int num_img = 0;
788 	unsigned int i = 0;
789 	uint8_t img_type = REMOTEPROC_INVALID_TYPE;
790 	uint32_t img_size = 0;
791 	uint8_t *tlv = NULL;
792 	int32_t offset = 0;
793 	size_t length = 0;
794 	paddr_t rsc_pa = 0;
795 	size_t rsc_size = 0;
796 
797 	res = e32_parse_ehdr(ctx->fw_img, ctx->fw_img_sz);
798 	if (res) {
799 		EMSG("Failed to parse firmware, res = %#"PRIx32, res);
800 		return res;
801 	}
802 
803 	res = get_hash_table(ctx);
804 	if (res)
805 		return res;
806 
807 	/* Get the number of firmware images to load */
808 	res = remoteproc_get_tlv(ctx->tlvs, ctx->tlvs_sz, RPROC_TLV_NUM_IMG,
809 				 &tlv, &length);
810 	if (res)
811 		goto out;
812 	if (length != sizeof(uint8_t)) {
813 		res = TEE_ERROR_BAD_FORMAT;
814 		goto out;
815 	}
816 
817 	num_img = *tlv;
818 	if (!num_img) {
819 		res = TEE_ERROR_NO_DATA;
820 		goto out;
821 	}
822 
823 	/*
824 	 * Initialize resource table with zero. These values will be returned if
825 	 * no optional resource table is found in images.
826 	 */
827 	ctx->rsc_pa = 0;
828 	ctx->rsc_size = 0;
829 
830 	for (i = 0; i < num_img; i++) {
831 		res = get_tlv_images_type(ctx, num_img, i, &img_type);
832 		if (res)
833 			goto out;
834 		if (img_type != REMOTEPROC_ELF_TYPE) {
835 			res = TEE_ERROR_BAD_FORMAT;
836 			goto out;
837 		}
838 
839 		res = get_tlv_images_size(ctx, num_img, i, &img_size);
840 		if (res)
841 			goto out;
842 
843 		res = e32_parser_load_elf_image(ctx->fw_img + offset, img_size,
844 						remoteproc_load_segment, ctx);
845 		if (res)
846 			goto out;
847 
848 		/* Take opportunity to get the resource table address */
849 		res = remoteproc_parse_rsc_table(ctx, ctx->fw_img + offset,
850 						 img_size, &rsc_pa, &rsc_size);
851 		if (res != TEE_SUCCESS && res != TEE_ERROR_NO_DATA)
852 			goto out;
853 
854 		if (res == TEE_SUCCESS) {
855 			/*
856 			 * Only one resource table is supported, check that no
857 			 * other one has been declared in a previously loaded
858 			 * firmware.
859 			 */
860 			if (ctx->rsc_pa || ctx->rsc_size) {
861 				EMSG("More than one resource table found");
862 				res = TEE_ERROR_BAD_FORMAT;
863 				goto out;
864 			}
865 			ctx->rsc_pa = rsc_pa;
866 			ctx->rsc_size = rsc_size;
867 		} else {
868 			/*
869 			 * No resource table found. Force to TEE_SUCCESS as the
870 			 * resource table is optional.
871 			 */
872 			res = TEE_SUCCESS;
873 		}
874 		offset += img_size;
875 	}
876 
877 out:
878 	/* Should we clean-up the memories in case of fail ? */
879 	TEE_Free(ctx->hash_table);
880 	ctx->hash_table = NULL;
881 
882 	return res;
883 }
884 
remoteproc_load_fw(uint32_t pt,TEE_Param params[TEE_NUM_PARAMS])885 static TEE_Result remoteproc_load_fw(uint32_t pt,
886 				     TEE_Param params[TEE_NUM_PARAMS])
887 {
888 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
889 						TEE_PARAM_TYPE_MEMREF_INPUT,
890 						TEE_PARAM_TYPE_NONE,
891 						TEE_PARAM_TYPE_NONE);
892 	struct remoteproc_context *ctx = NULL;
893 	uint32_t rproc_id = params[0].value.a;
894 	TEE_Result res = TEE_ERROR_GENERIC;
895 
896 	if (pt != exp_pt)
897 		return TEE_ERROR_BAD_PARAMETERS;
898 
899 	ctx = remoteproc_find_firmware(rproc_id);
900 	if (!ctx)
901 		ctx = remoteproc_add_firmware(rproc_id);
902 	if (!ctx)
903 		return TEE_ERROR_OUT_OF_MEMORY;
904 
905 	/* The firmware is already loaded, do nothing */
906 	if (ctx->state == REMOTEPROC_LOADED)
907 		return TEE_SUCCESS;
908 
909 	if (ctx->state != REMOTEPROC_OFF)
910 		return TEE_ERROR_BAD_STATE;
911 
912 	if (!params[1].memref.buffer || !params[1].memref.size)
913 		return TEE_ERROR_BAD_PARAMETERS;
914 
915 	DMSG("Got base addr: %p size %#zx", params[1].memref.buffer,
916 	     params[1].memref.size);
917 
918 	res = remoteproc_verify_firmware(ctx, params[1].memref.buffer,
919 					 params[1].memref.size);
920 	if (res) {
921 		EMSG("Can't Authenticate the firmware (res = %#"PRIx32")", res);
922 		goto out;
923 	}
924 
925 	res = remoteproc_load_elf(ctx);
926 	if (res)
927 		goto out;
928 
929 	ctx->state = REMOTEPROC_LOADED;
930 
931 out:
932 	/* Clear reference to firmware image from shared memory */
933 	ctx->fw_img = NULL;
934 	ctx->fw_img_sz = 0;
935 	ctx->nb_segment = 0;
936 
937 	/* Free allocated memories */
938 	TEE_Free(ctx->sec_cpy);
939 	ctx->sec_cpy = NULL;
940 
941 	return res;
942 }
943 
remoteproc_start_fw(uint32_t pt,TEE_Param params[TEE_NUM_PARAMS])944 static TEE_Result remoteproc_start_fw(uint32_t pt,
945 				      TEE_Param params[TEE_NUM_PARAMS])
946 {
947 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
948 						TEE_PARAM_TYPE_NONE,
949 						TEE_PARAM_TYPE_NONE,
950 						TEE_PARAM_TYPE_NONE);
951 	struct remoteproc_context *ctx = NULL;
952 	uint32_t rproc_id = params[0].value.a;
953 	TEE_Result res = TEE_ERROR_GENERIC;
954 
955 	if (pt != exp_pt)
956 		return TEE_ERROR_BAD_PARAMETERS;
957 
958 	ctx = remoteproc_find_firmware(rproc_id);
959 	if (!ctx)
960 		return TEE_ERROR_BAD_PARAMETERS;
961 
962 	switch (ctx->state) {
963 	case REMOTEPROC_OFF:
964 		res = TEE_ERROR_BAD_STATE;
965 		break;
966 	case REMOTEPROC_STARTED:
967 		res = TEE_SUCCESS;
968 		break;
969 	case REMOTEPROC_LOADED:
970 		res = TEE_InvokeTACommand(pta_session, TEE_TIMEOUT_INFINITE,
971 					  PTA_RPROC_FIRMWARE_START,
972 					  pt, params, NULL);
973 		if (res == TEE_SUCCESS)
974 			ctx->state = REMOTEPROC_STARTED;
975 		break;
976 	default:
977 		res = TEE_ERROR_BAD_STATE;
978 	}
979 
980 	return res;
981 }
982 
remoteproc_stop_fw(uint32_t pt,TEE_Param params[TEE_NUM_PARAMS])983 static TEE_Result remoteproc_stop_fw(uint32_t pt,
984 				     TEE_Param params[TEE_NUM_PARAMS])
985 {
986 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
987 						TEE_PARAM_TYPE_NONE,
988 						TEE_PARAM_TYPE_NONE,
989 						TEE_PARAM_TYPE_NONE);
990 	struct remoteproc_context *ctx = NULL;
991 	uint32_t rproc_id = params[0].value.a;
992 	TEE_Result res = TEE_ERROR_GENERIC;
993 
994 	if (pt != exp_pt)
995 		return TEE_ERROR_BAD_PARAMETERS;
996 
997 	ctx = remoteproc_find_firmware(rproc_id);
998 	if (!ctx)
999 		return TEE_ERROR_BAD_PARAMETERS;
1000 
1001 	switch (ctx->state) {
1002 	case REMOTEPROC_LOADED:
1003 		res = TEE_ERROR_BAD_STATE;
1004 		break;
1005 	case REMOTEPROC_OFF:
1006 		res = TEE_SUCCESS;
1007 		break;
1008 	case REMOTEPROC_STARTED:
1009 		res = TEE_InvokeTACommand(pta_session, TEE_TIMEOUT_INFINITE,
1010 					  PTA_RPROC_FIRMWARE_STOP,
1011 					  pt, params, NULL);
1012 		if (res == TEE_SUCCESS)
1013 			ctx->state = REMOTEPROC_OFF;
1014 		break;
1015 	default:
1016 		res = TEE_ERROR_BAD_STATE;
1017 	}
1018 
1019 	return res;
1020 }
1021 
remoteproc_get_rsc_table(uint32_t pt,TEE_Param params[TEE_NUM_PARAMS])1022 static TEE_Result remoteproc_get_rsc_table(uint32_t pt,
1023 					   TEE_Param params[TEE_NUM_PARAMS])
1024 {
1025 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
1026 						TEE_PARAM_TYPE_VALUE_OUTPUT,
1027 						TEE_PARAM_TYPE_VALUE_OUTPUT,
1028 						TEE_PARAM_TYPE_NONE);
1029 	struct remoteproc_context *ctx = NULL;
1030 
1031 	if (pt != exp_pt)
1032 		return TEE_ERROR_BAD_PARAMETERS;
1033 
1034 	ctx = remoteproc_find_firmware(params[0].value.a);
1035 	if (!ctx)
1036 		return TEE_ERROR_BAD_PARAMETERS;
1037 
1038 	if (ctx->state == REMOTEPROC_OFF)
1039 		return TEE_ERROR_BAD_STATE;
1040 
1041 	reg_pair_from_64((uint64_t)ctx->rsc_pa,
1042 			 &params[1].value.b, &params[1].value.a);
1043 	reg_pair_from_64((uint64_t)ctx->rsc_size,
1044 			 &params[2].value.b, &params[2].value.a);
1045 
1046 	return TEE_SUCCESS;
1047 }
1048 
remoteproc_release_fw(uint32_t pt,TEE_Param params[TEE_NUM_PARAMS])1049 static TEE_Result remoteproc_release_fw(uint32_t pt,
1050 					TEE_Param params[TEE_NUM_PARAMS])
1051 {
1052 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
1053 						TEE_PARAM_TYPE_NONE,
1054 						TEE_PARAM_TYPE_NONE,
1055 						TEE_PARAM_TYPE_NONE);
1056 	struct remoteproc_context *ctx = NULL;
1057 	uint32_t rproc_id = params[0].value.a;
1058 	TEE_Result res = TEE_ERROR_GENERIC;
1059 
1060 	if (pt != exp_pt)
1061 		return TEE_ERROR_BAD_PARAMETERS;
1062 
1063 	ctx = remoteproc_find_firmware(rproc_id);
1064 	if (!ctx)
1065 		return TEE_ERROR_BAD_PARAMETERS;
1066 
1067 	if (ctx->state == REMOTEPROC_STARTED)
1068 		return TEE_ERROR_BAD_STATE;
1069 
1070 	res = TEE_InvokeTACommand(pta_session, TEE_TIMEOUT_INFINITE,
1071 				  PTA_REMOTEPROC_RELEASE, pt, params, NULL);
1072 	if (res == TEE_SUCCESS)
1073 		ctx->state = REMOTEPROC_OFF;
1074 
1075 	return res;
1076 }
1077 
TA_CreateEntryPoint(void)1078 TEE_Result TA_CreateEntryPoint(void)
1079 {
1080 	return TEE_SUCCESS;
1081 }
1082 
TA_DestroyEntryPoint(void)1083 void TA_DestroyEntryPoint(void)
1084 {
1085 }
1086 
1087 /*
1088  * TA_OpenSessionEntryPoint: open a TA session associated to a remote processor
1089  * to manage.
1090  *
1091  * [in] params[0].value.a:	Unique 32bit remote processor identifier
1092  */
TA_OpenSessionEntryPoint(uint32_t pt,TEE_Param params[TEE_NUM_PARAMS],void ** sess __unused)1093 TEE_Result TA_OpenSessionEntryPoint(uint32_t pt,
1094 				    TEE_Param params[TEE_NUM_PARAMS],
1095 				    void **sess __unused)
1096 {
1097 	static const TEE_UUID uuid = PTA_RPROC_UUID;
1098 	TEE_Result res = TEE_ERROR_GENERIC;
1099 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
1100 						TEE_PARAM_TYPE_NONE,
1101 						TEE_PARAM_TYPE_NONE,
1102 						TEE_PARAM_TYPE_NONE);
1103 
1104 	if (pt != exp_pt)
1105 		return TEE_ERROR_BAD_PARAMETERS;
1106 
1107 	if (!session_refcount) {
1108 		res = TEE_OpenTASession(&uuid, TEE_TIMEOUT_INFINITE, pt, params,
1109 					&pta_session, NULL);
1110 		if (res)
1111 			return res;
1112 	}
1113 
1114 	session_refcount++;
1115 
1116 	return TEE_SUCCESS;
1117 }
1118 
TA_CloseSessionEntryPoint(void * sess __unused)1119 void TA_CloseSessionEntryPoint(void *sess __unused)
1120 {
1121 	session_refcount--;
1122 
1123 	if (!session_refcount)
1124 		TEE_CloseTASession(pta_session);
1125 }
1126 
TA_InvokeCommandEntryPoint(void * sess __unused,uint32_t cmd_id,uint32_t pt,TEE_Param params[TEE_NUM_PARAMS])1127 TEE_Result TA_InvokeCommandEntryPoint(void *sess __unused, uint32_t cmd_id,
1128 				      uint32_t pt,
1129 				      TEE_Param params[TEE_NUM_PARAMS])
1130 {
1131 	switch (cmd_id) {
1132 	case TA_RPROC_CMD_LOAD_FW:
1133 		return remoteproc_load_fw(pt, params);
1134 	case TA_RPROC_CMD_START_FW:
1135 		return remoteproc_start_fw(pt, params);
1136 	case TA_RPROC_CMD_STOP_FW:
1137 		return remoteproc_stop_fw(pt, params);
1138 	case TA_RPROC_CMD_GET_RSC_TABLE:
1139 		return remoteproc_get_rsc_table(pt, params);
1140 	case TA_RPROC_CMD_GET_COREDUMP:
1141 		return TEE_ERROR_NOT_IMPLEMENTED;
1142 	case TA_RPROC_CMD_RELEASE_FW:
1143 		return remoteproc_release_fw(pt, params);
1144 	default:
1145 		return TEE_ERROR_BAD_PARAMETERS;
1146 	}
1147 }
1148