17509ff7cSJens Wiklander // SPDX-License-Identifier: BSD-2-Clause
27509ff7cSJens Wiklander /*
37509ff7cSJens Wiklander * Copyright (c) 2019, Linaro Limited
4af78e1b1SImre Kis * Copyright (c) 2022-2023, Arm Limited
57509ff7cSJens Wiklander */
67509ff7cSJens Wiklander
765137432SJens Wiklander #include <assert.h>
87509ff7cSJens Wiklander #include <ldelf.h>
97509ff7cSJens Wiklander #include <malloc.h>
10c86f218cSJens Wiklander #include <printk.h>
11c86f218cSJens Wiklander #include <string.h>
127509ff7cSJens Wiklander #include <sys/queue.h>
137509ff7cSJens Wiklander #include <tee_api_types.h>
147509ff7cSJens Wiklander #include <trace.h>
157509ff7cSJens Wiklander #include <types_ext.h>
16c86f218cSJens Wiklander #include <util.h>
177509ff7cSJens Wiklander
18ebef121cSJerome Forissier #include "dl.h"
19c86f218cSJens Wiklander #include "ftrace.h"
207509ff7cSJens Wiklander #include "sys.h"
21c86f218cSJens Wiklander #include "ta_elf.h"
227509ff7cSJens Wiklander
230e7c71e1SJerome Forissier static size_t mpool_size = 4 * SMALL_PAGE_SIZE;
247509ff7cSJens Wiklander static vaddr_t mpool_base;
257509ff7cSJens Wiklander
print_to_console(void * pctx __unused,const char * fmt,va_list ap)26c86f218cSJens Wiklander static void __printf(2, 0) print_to_console(void *pctx __unused,
27c86f218cSJens Wiklander const char *fmt, va_list ap)
28c86f218cSJens Wiklander {
29c86f218cSJens Wiklander trace_vprintf(NULL, 0, TRACE_ERROR, true, fmt, ap);
30c86f218cSJens Wiklander }
31c86f218cSJens Wiklander
dump_ta_state(struct dump_entry_arg * arg)3265137432SJens Wiklander static void __noreturn __maybe_unused dump_ta_state(struct dump_entry_arg *arg)
3365137432SJens Wiklander {
3465137432SJens Wiklander struct ta_elf *elf = TAILQ_FIRST(&main_elf_queue);
3565137432SJens Wiklander
3665137432SJens Wiklander assert(elf && elf->is_main);
3765137432SJens Wiklander EMSG_RAW("Status of TA %pUl", (void *)&elf->uuid);
38*ba2a6adbSAlvin Chang #if defined(ARM32) || defined(ARM64)
3965137432SJens Wiklander EMSG_RAW(" arch: %s", elf->is_32bit ? "arm" : "aarch64");
40*ba2a6adbSAlvin Chang #elif defined(RV32) || defined(RV64)
41*ba2a6adbSAlvin Chang EMSG_RAW(" arch: %s", elf->is_32bit ? "riscv32" : "riscv64");
42*ba2a6adbSAlvin Chang #endif
4365137432SJens Wiklander
44c86f218cSJens Wiklander ta_elf_print_mappings(NULL, print_to_console, &main_elf_queue,
45c86f218cSJens Wiklander arg->num_maps, arg->maps, mpool_base);
460242833aSJens Wiklander
47*ba2a6adbSAlvin Chang #if defined(ARM32) || defined(ARM64)
48cb5f271cSMarouene Boubakri if (arg->is_32bit)
490242833aSJens Wiklander ta_elf_stack_trace_a32(arg->arm32.regs);
500242833aSJens Wiklander else
510242833aSJens Wiklander ta_elf_stack_trace_a64(arg->arm64.fp, arg->arm64.sp,
520242833aSJens Wiklander arg->arm64.pc);
53*ba2a6adbSAlvin Chang #elif defined(RV32) || defined(RV64)
54*ba2a6adbSAlvin Chang ta_elf_stack_trace_riscv(arg->rv.fp, arg->rv.pc);
55*ba2a6adbSAlvin Chang #endif
560242833aSJens Wiklander
5765137432SJens Wiklander sys_return_cleanup();
5865137432SJens Wiklander }
5965137432SJens Wiklander
60099918f6SSumit Garg #ifdef CFG_FTRACE_SUPPORT
61c86f218cSJens Wiklander struct print_buf_ctx {
62c86f218cSJens Wiklander char *buf;
63c86f218cSJens Wiklander size_t blen;
64c86f218cSJens Wiklander size_t ret;
65c86f218cSJens Wiklander };
66c86f218cSJens Wiklander
print_to_pbuf(void * pctx,const char * fmt,va_list ap)67c86f218cSJens Wiklander static void __printf(2, 0) print_to_pbuf(void *pctx, const char *fmt,
68c86f218cSJens Wiklander va_list ap)
69c86f218cSJens Wiklander {
70c86f218cSJens Wiklander struct print_buf_ctx *pbuf = pctx;
71c86f218cSJens Wiklander char *buf = NULL;
72c86f218cSJens Wiklander size_t blen = 0;
73c86f218cSJens Wiklander int ret = 0;
74c86f218cSJens Wiklander
75c86f218cSJens Wiklander if (pbuf->buf && pbuf->blen > pbuf->ret) {
76c86f218cSJens Wiklander buf = pbuf->buf + pbuf->ret;
77c86f218cSJens Wiklander blen = pbuf->blen - pbuf->ret;
78c86f218cSJens Wiklander }
79c86f218cSJens Wiklander
80c86f218cSJens Wiklander ret = vsnprintk(buf, blen, fmt, ap);
81c86f218cSJens Wiklander assert(ret >= 0);
82c86f218cSJens Wiklander
83c86f218cSJens Wiklander pbuf->ret += ret;
84c86f218cSJens Wiklander }
85c86f218cSJens Wiklander
copy_to_pbuf(void * pctx,void * b,size_t bl)86c86f218cSJens Wiklander static void copy_to_pbuf(void *pctx, void *b, size_t bl)
87c86f218cSJens Wiklander {
88c86f218cSJens Wiklander struct print_buf_ctx *pbuf = pctx;
89c86f218cSJens Wiklander char *buf = NULL;
90c86f218cSJens Wiklander size_t blen = 0;
91c86f218cSJens Wiklander
92c86f218cSJens Wiklander if (pbuf->buf && pbuf->blen > pbuf->ret) {
93c86f218cSJens Wiklander buf = pbuf->buf + pbuf->ret;
94c86f218cSJens Wiklander blen = pbuf->blen - pbuf->ret;
95c86f218cSJens Wiklander memcpy(buf, b, MIN(blen, bl));
96c86f218cSJens Wiklander }
97c86f218cSJens Wiklander
98c86f218cSJens Wiklander pbuf->ret += bl;
99c86f218cSJens Wiklander
100c86f218cSJens Wiklander }
101c86f218cSJens Wiklander
ftrace_dump(void * buf,size_t * blen)102c86f218cSJens Wiklander static void __noreturn ftrace_dump(void *buf, size_t *blen)
103c86f218cSJens Wiklander {
104c86f218cSJens Wiklander struct print_buf_ctx pbuf = { .buf = buf, .blen = *blen };
105c86f218cSJens Wiklander
106c86f218cSJens Wiklander ta_elf_print_mappings(&pbuf, print_to_pbuf, &main_elf_queue,
107c86f218cSJens Wiklander 0, NULL, mpool_base);
108c86f218cSJens Wiklander ftrace_copy_buf(&pbuf, copy_to_pbuf);
109c86f218cSJens Wiklander *blen = pbuf.ret;
110c86f218cSJens Wiklander sys_return_cleanup();
111c86f218cSJens Wiklander }
112c86f218cSJens Wiklander #endif
113c86f218cSJens Wiklander
dl_entry(struct dl_entry_arg * arg)114ebef121cSJerome Forissier static void __noreturn dl_entry(struct dl_entry_arg *arg)
115ebef121cSJerome Forissier {
116ebef121cSJerome Forissier switch (arg->cmd) {
117ebef121cSJerome Forissier case LDELF_DL_ENTRY_DLOPEN:
118ebef121cSJerome Forissier arg->ret = dlopen_entry(arg);
119ebef121cSJerome Forissier break;
120ebef121cSJerome Forissier case LDELF_DL_ENTRY_DLSYM:
121ebef121cSJerome Forissier arg->ret = dlsym_entry(arg);
122ebef121cSJerome Forissier break;
123ebef121cSJerome Forissier default:
124ebef121cSJerome Forissier arg->ret = TEE_ERROR_NOT_SUPPORTED;
125ebef121cSJerome Forissier }
126ebef121cSJerome Forissier
127ebef121cSJerome Forissier sys_return_cleanup();
128ebef121cSJerome Forissier }
129ebef121cSJerome Forissier
1307509ff7cSJens Wiklander /*
1317509ff7cSJens Wiklander * ldelf()- Loads ELF into memory
1327509ff7cSJens Wiklander * @arg: Argument passing to/from TEE Core
1337509ff7cSJens Wiklander *
1347509ff7cSJens Wiklander * Only called from assembly
1357509ff7cSJens Wiklander */
1367509ff7cSJens Wiklander void __noreturn ldelf(struct ldelf_arg *arg);
ldelf(struct ldelf_arg * arg)1377509ff7cSJens Wiklander void ldelf(struct ldelf_arg *arg)
1387509ff7cSJens Wiklander {
1397509ff7cSJens Wiklander TEE_Result res = TEE_SUCCESS;
1407509ff7cSJens Wiklander struct ta_elf *elf = NULL;
1417509ff7cSJens Wiklander
1424e994fd8SJelle Sels DMSG("Loading TS %pUl", (void *)&arg->uuid);
1437509ff7cSJens Wiklander res = sys_map_zi(mpool_size, 0, &mpool_base, 0, 0);
1447509ff7cSJens Wiklander if (res) {
1457509ff7cSJens Wiklander EMSG("sys_map_zi(%zu): result %"PRIx32, mpool_size, res);
1467509ff7cSJens Wiklander panic();
1477509ff7cSJens Wiklander }
1487509ff7cSJens Wiklander malloc_add_pool((void *)mpool_base, mpool_size);
1497509ff7cSJens Wiklander
1507509ff7cSJens Wiklander /* Load the main binary and get a list of dependencies, if any. */
151c35dfd95SJens Wiklander ta_elf_load_main(&arg->uuid, &arg->is_32bit, &arg->stack_ptr,
152c35dfd95SJens Wiklander &arg->flags);
1537509ff7cSJens Wiklander
1547509ff7cSJens Wiklander /*
1557509ff7cSJens Wiklander * Load binaries, ta_elf_load() may add external libraries to the
1567509ff7cSJens Wiklander * list, so the loop will end when all the dependencies are
1577509ff7cSJens Wiklander * satisfied.
1587509ff7cSJens Wiklander */
1597509ff7cSJens Wiklander TAILQ_FOREACH(elf, &main_elf_queue, link)
1607509ff7cSJens Wiklander ta_elf_load_dependency(elf, arg->is_32bit);
1617509ff7cSJens Wiklander
1627509ff7cSJens Wiklander TAILQ_FOREACH(elf, &main_elf_queue, link) {
1637509ff7cSJens Wiklander ta_elf_relocate(elf);
1647509ff7cSJens Wiklander ta_elf_finalize_mappings(elf);
1657509ff7cSJens Wiklander }
1667509ff7cSJens Wiklander
167af78e1b1SImre Kis ta_elf_finalize_load_main(&arg->entry_func, &arg->load_addr);
168c35dfd95SJens Wiklander
169c86f218cSJens Wiklander arg->ftrace_entry = 0;
170099918f6SSumit Garg #ifdef CFG_FTRACE_SUPPORT
171f90488afSSumit Garg if (ftrace_init(&arg->fbuf))
172c86f218cSJens Wiklander arg->ftrace_entry = (vaddr_t)(void *)ftrace_dump;
173c86f218cSJens Wiklander #endif
174c86f218cSJens Wiklander
1757509ff7cSJens Wiklander TAILQ_FOREACH(elf, &main_elf_queue, link)
1767509ff7cSJens Wiklander DMSG("ELF (%pUl) at %#"PRIxVA,
1777509ff7cSJens Wiklander (void *)&elf->uuid, elf->load_addr);
1787509ff7cSJens Wiklander
17965137432SJens Wiklander #if TRACE_LEVEL >= TRACE_ERROR
18065137432SJens Wiklander arg->dump_entry = (vaddr_t)(void *)dump_ta_state;
18165137432SJens Wiklander #else
18265137432SJens Wiklander arg->dump_entry = 0;
18365137432SJens Wiklander #endif
184ebef121cSJerome Forissier arg->dl_entry = (vaddr_t)(void *)dl_entry;
18565137432SJens Wiklander
1867509ff7cSJens Wiklander sys_return_cleanup();
1877509ff7cSJens Wiklander }
188