xref: /optee_os/ldelf/main.c (revision c86f218c5bc8ba0deb6e7c6ff58f8db93c01e32f)
17509ff7cSJens Wiklander // SPDX-License-Identifier: BSD-2-Clause
27509ff7cSJens Wiklander /*
37509ff7cSJens Wiklander  * Copyright (c) 2019, Linaro Limited
47509ff7cSJens Wiklander  */
57509ff7cSJens Wiklander 
665137432SJens Wiklander #include <assert.h>
77509ff7cSJens Wiklander #include <ldelf.h>
87509ff7cSJens Wiklander #include <malloc.h>
9*c86f218cSJens Wiklander #include <printk.h>
10*c86f218cSJens Wiklander #include <string.h>
117509ff7cSJens Wiklander #include <sys/queue.h>
127509ff7cSJens Wiklander #include <tee_api_types.h>
137509ff7cSJens Wiklander #include <trace.h>
147509ff7cSJens Wiklander #include <types_ext.h>
15*c86f218cSJens Wiklander #include <util.h>
167509ff7cSJens Wiklander 
17*c86f218cSJens Wiklander #include "ftrace.h"
187509ff7cSJens Wiklander #include "sys.h"
19*c86f218cSJens Wiklander #include "ta_elf.h"
207509ff7cSJens Wiklander 
217509ff7cSJens Wiklander static size_t mpool_size = 2 * SMALL_PAGE_SIZE;
227509ff7cSJens Wiklander static vaddr_t mpool_base;
237509ff7cSJens Wiklander 
24*c86f218cSJens Wiklander static void __printf(2, 0) print_to_console(void *pctx __unused,
25*c86f218cSJens Wiklander 					    const char *fmt, va_list ap)
26*c86f218cSJens Wiklander {
27*c86f218cSJens Wiklander 	trace_vprintf(NULL, 0, TRACE_ERROR, true, fmt, ap);
28*c86f218cSJens Wiklander }
29*c86f218cSJens Wiklander 
3065137432SJens Wiklander static void __noreturn __maybe_unused dump_ta_state(struct dump_entry_arg *arg)
3165137432SJens Wiklander {
3265137432SJens Wiklander 	struct ta_elf *elf = TAILQ_FIRST(&main_elf_queue);
3365137432SJens Wiklander 
3465137432SJens Wiklander 	assert(elf && elf->is_main);
3565137432SJens Wiklander 	EMSG_RAW("Status of TA %pUl", (void *)&elf->uuid);
3665137432SJens Wiklander 	EMSG_RAW(" arch: %s", elf->is_32bit ? "arm" : "aarch64");
3765137432SJens Wiklander 
3865137432SJens Wiklander 
39*c86f218cSJens Wiklander 	ta_elf_print_mappings(NULL, print_to_console, &main_elf_queue,
40*c86f218cSJens Wiklander 			      arg->num_maps, arg->maps, mpool_base);
410242833aSJens Wiklander 
420242833aSJens Wiklander 	if (arg->is_arm32)
430242833aSJens Wiklander 		ta_elf_stack_trace_a32(arg->arm32.regs);
440242833aSJens Wiklander 	else
450242833aSJens Wiklander 		ta_elf_stack_trace_a64(arg->arm64.fp, arg->arm64.sp,
460242833aSJens Wiklander 				       arg->arm64.pc);
470242833aSJens Wiklander 
4865137432SJens Wiklander 	sys_return_cleanup();
4965137432SJens Wiklander }
5065137432SJens Wiklander 
51*c86f218cSJens Wiklander #ifdef CFG_TA_FTRACE_SUPPORT
52*c86f218cSJens Wiklander struct print_buf_ctx {
53*c86f218cSJens Wiklander 	char *buf;
54*c86f218cSJens Wiklander 	size_t blen;
55*c86f218cSJens Wiklander 	size_t ret;
56*c86f218cSJens Wiklander };
57*c86f218cSJens Wiklander 
58*c86f218cSJens Wiklander static void __printf(2, 0) print_to_pbuf(void *pctx, const char *fmt,
59*c86f218cSJens Wiklander 					 va_list ap)
60*c86f218cSJens Wiklander {
61*c86f218cSJens Wiklander 	struct print_buf_ctx *pbuf = pctx;
62*c86f218cSJens Wiklander 	char *buf = NULL;
63*c86f218cSJens Wiklander 	size_t blen = 0;
64*c86f218cSJens Wiklander 	int ret = 0;
65*c86f218cSJens Wiklander 
66*c86f218cSJens Wiklander 	if (pbuf->buf && pbuf->blen > pbuf->ret) {
67*c86f218cSJens Wiklander 		buf = pbuf->buf + pbuf->ret;
68*c86f218cSJens Wiklander 		blen = pbuf->blen - pbuf->ret;
69*c86f218cSJens Wiklander 	}
70*c86f218cSJens Wiklander 
71*c86f218cSJens Wiklander 	ret = vsnprintk(buf, blen, fmt, ap);
72*c86f218cSJens Wiklander 	assert(ret >= 0);
73*c86f218cSJens Wiklander 
74*c86f218cSJens Wiklander 	pbuf->ret += ret;
75*c86f218cSJens Wiklander }
76*c86f218cSJens Wiklander 
77*c86f218cSJens Wiklander static void copy_to_pbuf(void *pctx, void *b, size_t bl)
78*c86f218cSJens Wiklander {
79*c86f218cSJens Wiklander 	struct print_buf_ctx *pbuf = pctx;
80*c86f218cSJens Wiklander 	char *buf = NULL;
81*c86f218cSJens Wiklander 	size_t blen = 0;
82*c86f218cSJens Wiklander 
83*c86f218cSJens Wiklander 	if (pbuf->buf && pbuf->blen > pbuf->ret) {
84*c86f218cSJens Wiklander 		buf = pbuf->buf + pbuf->ret;
85*c86f218cSJens Wiklander 		blen = pbuf->blen - pbuf->ret;
86*c86f218cSJens Wiklander 		memcpy(buf, b, MIN(blen, bl));
87*c86f218cSJens Wiklander 	}
88*c86f218cSJens Wiklander 
89*c86f218cSJens Wiklander 	pbuf->ret += bl;
90*c86f218cSJens Wiklander 
91*c86f218cSJens Wiklander }
92*c86f218cSJens Wiklander 
93*c86f218cSJens Wiklander static void __noreturn ftrace_dump(void *buf, size_t *blen)
94*c86f218cSJens Wiklander {
95*c86f218cSJens Wiklander 	struct print_buf_ctx pbuf = { .buf = buf, .blen = *blen };
96*c86f218cSJens Wiklander 
97*c86f218cSJens Wiklander 	ta_elf_print_mappings(&pbuf, print_to_pbuf, &main_elf_queue,
98*c86f218cSJens Wiklander 			      0, NULL, mpool_base);
99*c86f218cSJens Wiklander 	ftrace_copy_buf(&pbuf, copy_to_pbuf);
100*c86f218cSJens Wiklander 	*blen = pbuf.ret;
101*c86f218cSJens Wiklander 	sys_return_cleanup();
102*c86f218cSJens Wiklander }
103*c86f218cSJens Wiklander #endif
104*c86f218cSJens Wiklander 
1057509ff7cSJens Wiklander /*
1067509ff7cSJens Wiklander  * ldelf()- Loads ELF into memory
1077509ff7cSJens Wiklander  * @arg:	Argument passing to/from TEE Core
1087509ff7cSJens Wiklander  *
1097509ff7cSJens Wiklander  * Only called from assembly
1107509ff7cSJens Wiklander  */
1117509ff7cSJens Wiklander void __noreturn ldelf(struct ldelf_arg *arg);
1127509ff7cSJens Wiklander void ldelf(struct ldelf_arg *arg)
1137509ff7cSJens Wiklander {
1147509ff7cSJens Wiklander 	TEE_Result res = TEE_SUCCESS;
1157509ff7cSJens Wiklander 	struct ta_elf *elf = NULL;
1167509ff7cSJens Wiklander 
1177509ff7cSJens Wiklander 	DMSG("Loading TA %pUl", (void *)&arg->uuid);
1187509ff7cSJens Wiklander 	res = sys_map_zi(mpool_size, 0, &mpool_base, 0, 0);
1197509ff7cSJens Wiklander 	if (res) {
1207509ff7cSJens Wiklander 		EMSG("sys_map_zi(%zu): result %"PRIx32, mpool_size, res);
1217509ff7cSJens Wiklander 		panic();
1227509ff7cSJens Wiklander 	}
1237509ff7cSJens Wiklander 	malloc_add_pool((void *)mpool_base, mpool_size);
1247509ff7cSJens Wiklander 
1257509ff7cSJens Wiklander 	/* Load the main binary and get a list of dependencies, if any. */
1267509ff7cSJens Wiklander 	ta_elf_load_main(&arg->uuid, &arg->is_32bit, &arg->entry_func,
1277509ff7cSJens Wiklander 			 &arg->stack_ptr, &arg->flags);
1287509ff7cSJens Wiklander 
1297509ff7cSJens Wiklander 	/*
1307509ff7cSJens Wiklander 	 * Load binaries, ta_elf_load() may add external libraries to the
1317509ff7cSJens Wiklander 	 * list, so the loop will end when all the dependencies are
1327509ff7cSJens Wiklander 	 * satisfied.
1337509ff7cSJens Wiklander 	 */
1347509ff7cSJens Wiklander 	TAILQ_FOREACH(elf, &main_elf_queue, link)
1357509ff7cSJens Wiklander 		ta_elf_load_dependency(elf, arg->is_32bit);
1367509ff7cSJens Wiklander 
1377509ff7cSJens Wiklander 	TAILQ_FOREACH(elf, &main_elf_queue, link) {
1387509ff7cSJens Wiklander 		ta_elf_relocate(elf);
1397509ff7cSJens Wiklander 		ta_elf_finalize_mappings(elf);
1407509ff7cSJens Wiklander 	}
1417509ff7cSJens Wiklander 
142*c86f218cSJens Wiklander 	arg->ftrace_entry = 0;
143*c86f218cSJens Wiklander #ifdef CFG_TA_FTRACE_SUPPORT
144*c86f218cSJens Wiklander 	if (ftrace_init())
145*c86f218cSJens Wiklander 		arg->ftrace_entry = (vaddr_t)(void *)ftrace_dump;
146*c86f218cSJens Wiklander #endif
147*c86f218cSJens Wiklander 
1487509ff7cSJens Wiklander 	TAILQ_FOREACH(elf, &main_elf_queue, link)
1497509ff7cSJens Wiklander 		DMSG("ELF (%pUl) at %#"PRIxVA,
1507509ff7cSJens Wiklander 		     (void *)&elf->uuid, elf->load_addr);
1517509ff7cSJens Wiklander 
15265137432SJens Wiklander #if TRACE_LEVEL >= TRACE_ERROR
15365137432SJens Wiklander 	arg->dump_entry = (vaddr_t)(void *)dump_ta_state;
15465137432SJens Wiklander #else
15565137432SJens Wiklander 	arg->dump_entry = 0;
15665137432SJens Wiklander #endif
15765137432SJens Wiklander 
1587509ff7cSJens Wiklander 	sys_return_cleanup();
1597509ff7cSJens Wiklander }
160