blob: 1aa9d8ca976a8340c0e6c94f8fe27f8152830fb7 [file] [log] [blame]
Jens Wiklander7509ff72019-05-23 17:42:08 +02001// SPDX-License-Identifier: BSD-2-Clause
2/*
3 * Copyright (c) 2019, Linaro Limited
Imre Kisaf78e1b2022-10-24 12:50:07 +02004 * Copyright (c) 2022-2023, Arm Limited
Jens Wiklander7509ff72019-05-23 17:42:08 +02005 */
6
Jens Wiklander65137432019-05-23 17:42:14 +02007#include <assert.h>
Jens Wiklander7509ff72019-05-23 17:42:08 +02008#include <ldelf.h>
9#include <malloc.h>
Jens Wiklanderc86f2182019-06-18 16:45:19 +020010#include <printk.h>
11#include <string.h>
Jens Wiklander7509ff72019-05-23 17:42:08 +020012#include <sys/queue.h>
13#include <tee_api_types.h>
14#include <trace.h>
15#include <types_ext.h>
Jens Wiklanderc86f2182019-06-18 16:45:19 +020016#include <util.h>
Jens Wiklander7509ff72019-05-23 17:42:08 +020017
Jerome Forissierebef1212019-08-01 18:08:24 +020018#include "dl.h"
Jens Wiklanderc86f2182019-06-18 16:45:19 +020019#include "ftrace.h"
Jens Wiklander7509ff72019-05-23 17:42:08 +020020#include "sys.h"
Jens Wiklanderc86f2182019-06-18 16:45:19 +020021#include "ta_elf.h"
Jens Wiklander7509ff72019-05-23 17:42:08 +020022
Jerome Forissier0e7c71e2020-07-21 10:55:13 +020023static size_t mpool_size = 4 * SMALL_PAGE_SIZE;
Jens Wiklander7509ff72019-05-23 17:42:08 +020024static vaddr_t mpool_base;
25
Jens Wiklanderc86f2182019-06-18 16:45:19 +020026static 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
Jens Wiklander65137432019-05-23 17:42:14 +020032static 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
Jens Wiklanderc86f2182019-06-18 16:45:19 +020041 ta_elf_print_mappings(NULL, print_to_console, &main_elf_queue,
42 arg->num_maps, arg->maps, mpool_base);
Jens Wiklander02428332019-05-23 17:42:15 +020043
Marouene Boubakricb5f2712023-02-01 17:17:47 +010044 if (arg->is_32bit)
Jens Wiklander02428332019-05-23 17:42:15 +020045 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
Jens Wiklander65137432019-05-23 17:42:14 +020050 sys_return_cleanup();
51}
52
Sumit Garg099918f2019-09-05 13:23:01 +053053#ifdef CFG_FTRACE_SUPPORT
Jens Wiklanderc86f2182019-06-18 16:45:19 +020054struct print_buf_ctx {
55 char *buf;
56 size_t blen;
57 size_t ret;
58};
59
60static 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
79static 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
95static 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
Jerome Forissierebef1212019-08-01 18:08:24 +0200107static 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
Jens Wiklander7509ff72019-05-23 17:42:08 +0200123/*
124 * ldelf()- Loads ELF into memory
125 * @arg: Argument passing to/from TEE Core
126 *
127 * Only called from assembly
128 */
129void __noreturn ldelf(struct ldelf_arg *arg);
130void ldelf(struct ldelf_arg *arg)
131{
132 TEE_Result res = TEE_SUCCESS;
133 struct ta_elf *elf = NULL;
134
Jelle Sels4e994fd2021-01-19 11:41:58 +0100135 DMSG("Loading TS %pUl", (void *)&arg->uuid);
Jens Wiklander7509ff72019-05-23 17:42:08 +0200136 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. */
Jens Wiklanderc35dfd92019-07-30 08:39:27 +0200144 ta_elf_load_main(&arg->uuid, &arg->is_32bit, &arg->stack_ptr,
145 &arg->flags);
Jens Wiklander7509ff72019-05-23 17:42:08 +0200146
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
Imre Kisaf78e1b2022-10-24 12:50:07 +0200160 ta_elf_finalize_load_main(&arg->entry_func, &arg->load_addr);
Jens Wiklanderc35dfd92019-07-30 08:39:27 +0200161
Jens Wiklanderc86f2182019-06-18 16:45:19 +0200162 arg->ftrace_entry = 0;
Sumit Garg099918f2019-09-05 13:23:01 +0530163#ifdef CFG_FTRACE_SUPPORT
Sumit Gargf90488a2019-07-09 12:31:30 +0530164 if (ftrace_init(&arg->fbuf))
Jens Wiklanderc86f2182019-06-18 16:45:19 +0200165 arg->ftrace_entry = (vaddr_t)(void *)ftrace_dump;
166#endif
167
Jens Wiklander7509ff72019-05-23 17:42:08 +0200168 TAILQ_FOREACH(elf, &main_elf_queue, link)
169 DMSG("ELF (%pUl) at %#"PRIxVA,
170 (void *)&elf->uuid, elf->load_addr);
171
Jens Wiklander65137432019-05-23 17:42:14 +0200172#if TRACE_LEVEL >= TRACE_ERROR
173 arg->dump_entry = (vaddr_t)(void *)dump_ta_state;
174#else
175 arg->dump_entry = 0;
176#endif
Jerome Forissierebef1212019-08-01 18:08:24 +0200177 arg->dl_entry = (vaddr_t)(void *)dl_entry;
Jens Wiklander65137432019-05-23 17:42:14 +0200178
Jens Wiklander7509ff72019-05-23 17:42:08 +0200179 sys_return_cleanup();
180}