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 ¶ms[1].value.b, ¶ms[1].value.a);
1043 reg_pair_from_64((uint64_t)ctx->rsc_size,
1044 ¶ms[2].value.b, ¶ms[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