xref: /optee_os/ldelf/main.c (revision 1478437e65c44163f7c96f8a4c5d1532a9312bc3)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2019, Linaro Limited
4  * Copyright (c) 2022-2023, Arm Limited
5  */
6 
7 #include <assert.h>
8 #include <ldelf.h>
9 #include <malloc.h>
10 #include <printk.h>
11 #include <string.h>
12 #include <sys/queue.h>
13 #include <tee_api_types.h>
14 #include <trace.h>
15 #include <types_ext.h>
16 #include <util.h>
17 
18 #include "dl.h"
19 #include "ftrace.h"
20 #include "sys.h"
21 #include "ta_elf.h"
22 
23 static size_t mpool_size = 4 * SMALL_PAGE_SIZE;
24 static vaddr_t mpool_base;
25 
26 static void __printf(2, 0) print_to_console(void *pctx __unused,
27 					    const char *fmt, va_list ap)
28 {
29 	trace_vprintf(NULL, 0, TRACE_ERROR, true, fmt, ap);
30 }
31 
32 static void __noreturn __maybe_unused dump_ta_state(struct dump_entry_arg *arg)
33 {
34 	struct ta_elf *elf = TAILQ_FIRST(&main_elf_queue);
35 
36 	assert(elf && elf->is_main);
37 	EMSG_RAW("Status of TA %pUl", (void *)&elf->uuid);
38 	EMSG_RAW(" arch: %s", elf->is_32bit ? "arm" : "aarch64");
39 
40 
41 	ta_elf_print_mappings(NULL, print_to_console, &main_elf_queue,
42 			      arg->num_maps, arg->maps, mpool_base);
43 
44 	if (arg->is_32bit)
45 		ta_elf_stack_trace_a32(arg->arm32.regs);
46 	else
47 		ta_elf_stack_trace_a64(arg->arm64.fp, arg->arm64.sp,
48 				       arg->arm64.pc);
49 
50 	sys_return_cleanup();
51 }
52 
53 #ifdef CFG_FTRACE_SUPPORT
54 struct print_buf_ctx {
55 	char *buf;
56 	size_t blen;
57 	size_t ret;
58 };
59 
60 static void __printf(2, 0) print_to_pbuf(void *pctx, const char *fmt,
61 					 va_list ap)
62 {
63 	struct print_buf_ctx *pbuf = pctx;
64 	char *buf = NULL;
65 	size_t blen = 0;
66 	int ret = 0;
67 
68 	if (pbuf->buf && pbuf->blen > pbuf->ret) {
69 		buf = pbuf->buf + pbuf->ret;
70 		blen = pbuf->blen - pbuf->ret;
71 	}
72 
73 	ret = vsnprintk(buf, blen, fmt, ap);
74 	assert(ret >= 0);
75 
76 	pbuf->ret += ret;
77 }
78 
79 static void copy_to_pbuf(void *pctx, void *b, size_t bl)
80 {
81 	struct print_buf_ctx *pbuf = pctx;
82 	char *buf = NULL;
83 	size_t blen = 0;
84 
85 	if (pbuf->buf && pbuf->blen > pbuf->ret) {
86 		buf = pbuf->buf + pbuf->ret;
87 		blen = pbuf->blen - pbuf->ret;
88 		memcpy(buf, b, MIN(blen, bl));
89 	}
90 
91 	pbuf->ret += bl;
92 
93 }
94 
95 static void __noreturn ftrace_dump(void *buf, size_t *blen)
96 {
97 	struct print_buf_ctx pbuf = { .buf = buf, .blen = *blen };
98 
99 	ta_elf_print_mappings(&pbuf, print_to_pbuf, &main_elf_queue,
100 			      0, NULL, mpool_base);
101 	ftrace_copy_buf(&pbuf, copy_to_pbuf);
102 	*blen = pbuf.ret;
103 	sys_return_cleanup();
104 }
105 #endif
106 
107 static void __noreturn dl_entry(struct dl_entry_arg *arg)
108 {
109 	switch (arg->cmd) {
110 	case LDELF_DL_ENTRY_DLOPEN:
111 		arg->ret = dlopen_entry(arg);
112 		break;
113 	case LDELF_DL_ENTRY_DLSYM:
114 		arg->ret = dlsym_entry(arg);
115 		break;
116 	default:
117 		arg->ret = TEE_ERROR_NOT_SUPPORTED;
118 	}
119 
120 	sys_return_cleanup();
121 }
122 
123 /*
124  * ldelf()- Loads ELF into memory
125  * @arg:	Argument passing to/from TEE Core
126  *
127  * Only called from assembly
128  */
129 void __noreturn ldelf(struct ldelf_arg *arg);
130 void ldelf(struct ldelf_arg *arg)
131 {
132 	TEE_Result res = TEE_SUCCESS;
133 	struct ta_elf *elf = NULL;
134 
135 	DMSG("Loading TS %pUl", (void *)&arg->uuid);
136 	res = sys_map_zi(mpool_size, 0, &mpool_base, 0, 0);
137 	if (res) {
138 		EMSG("sys_map_zi(%zu): result %"PRIx32, mpool_size, res);
139 		panic();
140 	}
141 	malloc_add_pool((void *)mpool_base, mpool_size);
142 
143 	/* Load the main binary and get a list of dependencies, if any. */
144 	ta_elf_load_main(&arg->uuid, &arg->is_32bit, &arg->stack_ptr,
145 			 &arg->flags);
146 
147 	/*
148 	 * Load binaries, ta_elf_load() may add external libraries to the
149 	 * list, so the loop will end when all the dependencies are
150 	 * satisfied.
151 	 */
152 	TAILQ_FOREACH(elf, &main_elf_queue, link)
153 		ta_elf_load_dependency(elf, arg->is_32bit);
154 
155 	TAILQ_FOREACH(elf, &main_elf_queue, link) {
156 		ta_elf_relocate(elf);
157 		ta_elf_finalize_mappings(elf);
158 	}
159 
160 	ta_elf_finalize_load_main(&arg->entry_func, &arg->load_addr);
161 
162 	arg->ftrace_entry = 0;
163 #ifdef CFG_FTRACE_SUPPORT
164 	if (ftrace_init(&arg->fbuf))
165 		arg->ftrace_entry = (vaddr_t)(void *)ftrace_dump;
166 #endif
167 
168 	TAILQ_FOREACH(elf, &main_elf_queue, link)
169 		DMSG("ELF (%pUl) at %#"PRIxVA,
170 		     (void *)&elf->uuid, elf->load_addr);
171 
172 #if TRACE_LEVEL >= TRACE_ERROR
173 	arg->dump_entry = (vaddr_t)(void *)dump_ta_state;
174 #else
175 	arg->dump_entry = 0;
176 #endif
177 	arg->dl_entry = (vaddr_t)(void *)dl_entry;
178 
179 	sys_return_cleanup();
180 }
181