17509ff7cSJens Wiklander // SPDX-License-Identifier: BSD-2-Clause 27509ff7cSJens Wiklander /* 37509ff7cSJens Wiklander * Copyright (c) 2019, Linaro Limited 4*af78e1b1SImre 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 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 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); 3865137432SJens Wiklander EMSG_RAW(" arch: %s", elf->is_32bit ? "arm" : "aarch64"); 3965137432SJens Wiklander 4065137432SJens Wiklander 41c86f218cSJens Wiklander ta_elf_print_mappings(NULL, print_to_console, &main_elf_queue, 42c86f218cSJens Wiklander arg->num_maps, arg->maps, mpool_base); 430242833aSJens Wiklander 44cb5f271cSMarouene Boubakri if (arg->is_32bit) 450242833aSJens Wiklander ta_elf_stack_trace_a32(arg->arm32.regs); 460242833aSJens Wiklander else 470242833aSJens Wiklander ta_elf_stack_trace_a64(arg->arm64.fp, arg->arm64.sp, 480242833aSJens Wiklander arg->arm64.pc); 490242833aSJens Wiklander 5065137432SJens Wiklander sys_return_cleanup(); 5165137432SJens Wiklander } 5265137432SJens Wiklander 53099918f6SSumit Garg #ifdef CFG_FTRACE_SUPPORT 54c86f218cSJens Wiklander struct print_buf_ctx { 55c86f218cSJens Wiklander char *buf; 56c86f218cSJens Wiklander size_t blen; 57c86f218cSJens Wiklander size_t ret; 58c86f218cSJens Wiklander }; 59c86f218cSJens Wiklander 60c86f218cSJens Wiklander static void __printf(2, 0) print_to_pbuf(void *pctx, const char *fmt, 61c86f218cSJens Wiklander va_list ap) 62c86f218cSJens Wiklander { 63c86f218cSJens Wiklander struct print_buf_ctx *pbuf = pctx; 64c86f218cSJens Wiklander char *buf = NULL; 65c86f218cSJens Wiklander size_t blen = 0; 66c86f218cSJens Wiklander int ret = 0; 67c86f218cSJens Wiklander 68c86f218cSJens Wiklander if (pbuf->buf && pbuf->blen > pbuf->ret) { 69c86f218cSJens Wiklander buf = pbuf->buf + pbuf->ret; 70c86f218cSJens Wiklander blen = pbuf->blen - pbuf->ret; 71c86f218cSJens Wiklander } 72c86f218cSJens Wiklander 73c86f218cSJens Wiklander ret = vsnprintk(buf, blen, fmt, ap); 74c86f218cSJens Wiklander assert(ret >= 0); 75c86f218cSJens Wiklander 76c86f218cSJens Wiklander pbuf->ret += ret; 77c86f218cSJens Wiklander } 78c86f218cSJens Wiklander 79c86f218cSJens Wiklander static void copy_to_pbuf(void *pctx, void *b, size_t bl) 80c86f218cSJens Wiklander { 81c86f218cSJens Wiklander struct print_buf_ctx *pbuf = pctx; 82c86f218cSJens Wiklander char *buf = NULL; 83c86f218cSJens Wiklander size_t blen = 0; 84c86f218cSJens Wiklander 85c86f218cSJens Wiklander if (pbuf->buf && pbuf->blen > pbuf->ret) { 86c86f218cSJens Wiklander buf = pbuf->buf + pbuf->ret; 87c86f218cSJens Wiklander blen = pbuf->blen - pbuf->ret; 88c86f218cSJens Wiklander memcpy(buf, b, MIN(blen, bl)); 89c86f218cSJens Wiklander } 90c86f218cSJens Wiklander 91c86f218cSJens Wiklander pbuf->ret += bl; 92c86f218cSJens Wiklander 93c86f218cSJens Wiklander } 94c86f218cSJens Wiklander 95c86f218cSJens Wiklander static void __noreturn ftrace_dump(void *buf, size_t *blen) 96c86f218cSJens Wiklander { 97c86f218cSJens Wiklander struct print_buf_ctx pbuf = { .buf = buf, .blen = *blen }; 98c86f218cSJens Wiklander 99c86f218cSJens Wiklander ta_elf_print_mappings(&pbuf, print_to_pbuf, &main_elf_queue, 100c86f218cSJens Wiklander 0, NULL, mpool_base); 101c86f218cSJens Wiklander ftrace_copy_buf(&pbuf, copy_to_pbuf); 102c86f218cSJens Wiklander *blen = pbuf.ret; 103c86f218cSJens Wiklander sys_return_cleanup(); 104c86f218cSJens Wiklander } 105c86f218cSJens Wiklander #endif 106c86f218cSJens Wiklander 107ebef121cSJerome Forissier static void __noreturn dl_entry(struct dl_entry_arg *arg) 108ebef121cSJerome Forissier { 109ebef121cSJerome Forissier switch (arg->cmd) { 110ebef121cSJerome Forissier case LDELF_DL_ENTRY_DLOPEN: 111ebef121cSJerome Forissier arg->ret = dlopen_entry(arg); 112ebef121cSJerome Forissier break; 113ebef121cSJerome Forissier case LDELF_DL_ENTRY_DLSYM: 114ebef121cSJerome Forissier arg->ret = dlsym_entry(arg); 115ebef121cSJerome Forissier break; 116ebef121cSJerome Forissier default: 117ebef121cSJerome Forissier arg->ret = TEE_ERROR_NOT_SUPPORTED; 118ebef121cSJerome Forissier } 119ebef121cSJerome Forissier 120ebef121cSJerome Forissier sys_return_cleanup(); 121ebef121cSJerome Forissier } 122ebef121cSJerome Forissier 1237509ff7cSJens Wiklander /* 1247509ff7cSJens Wiklander * ldelf()- Loads ELF into memory 1257509ff7cSJens Wiklander * @arg: Argument passing to/from TEE Core 1267509ff7cSJens Wiklander * 1277509ff7cSJens Wiklander * Only called from assembly 1287509ff7cSJens Wiklander */ 1297509ff7cSJens Wiklander void __noreturn ldelf(struct ldelf_arg *arg); 1307509ff7cSJens Wiklander void ldelf(struct ldelf_arg *arg) 1317509ff7cSJens Wiklander { 1327509ff7cSJens Wiklander TEE_Result res = TEE_SUCCESS; 1337509ff7cSJens Wiklander struct ta_elf *elf = NULL; 1347509ff7cSJens Wiklander 1354e994fd8SJelle Sels DMSG("Loading TS %pUl", (void *)&arg->uuid); 1367509ff7cSJens Wiklander res = sys_map_zi(mpool_size, 0, &mpool_base, 0, 0); 1377509ff7cSJens Wiklander if (res) { 1387509ff7cSJens Wiklander EMSG("sys_map_zi(%zu): result %"PRIx32, mpool_size, res); 1397509ff7cSJens Wiklander panic(); 1407509ff7cSJens Wiklander } 1417509ff7cSJens Wiklander malloc_add_pool((void *)mpool_base, mpool_size); 1427509ff7cSJens Wiklander 1437509ff7cSJens Wiklander /* Load the main binary and get a list of dependencies, if any. */ 144c35dfd95SJens Wiklander ta_elf_load_main(&arg->uuid, &arg->is_32bit, &arg->stack_ptr, 145c35dfd95SJens Wiklander &arg->flags); 1467509ff7cSJens Wiklander 1477509ff7cSJens Wiklander /* 1487509ff7cSJens Wiklander * Load binaries, ta_elf_load() may add external libraries to the 1497509ff7cSJens Wiklander * list, so the loop will end when all the dependencies are 1507509ff7cSJens Wiklander * satisfied. 1517509ff7cSJens Wiklander */ 1527509ff7cSJens Wiklander TAILQ_FOREACH(elf, &main_elf_queue, link) 1537509ff7cSJens Wiklander ta_elf_load_dependency(elf, arg->is_32bit); 1547509ff7cSJens Wiklander 1557509ff7cSJens Wiklander TAILQ_FOREACH(elf, &main_elf_queue, link) { 1567509ff7cSJens Wiklander ta_elf_relocate(elf); 1577509ff7cSJens Wiklander ta_elf_finalize_mappings(elf); 1587509ff7cSJens Wiklander } 1597509ff7cSJens Wiklander 160*af78e1b1SImre Kis ta_elf_finalize_load_main(&arg->entry_func, &arg->load_addr); 161c35dfd95SJens Wiklander 162c86f218cSJens Wiklander arg->ftrace_entry = 0; 163099918f6SSumit Garg #ifdef CFG_FTRACE_SUPPORT 164f90488afSSumit Garg if (ftrace_init(&arg->fbuf)) 165c86f218cSJens Wiklander arg->ftrace_entry = (vaddr_t)(void *)ftrace_dump; 166c86f218cSJens Wiklander #endif 167c86f218cSJens Wiklander 1687509ff7cSJens Wiklander TAILQ_FOREACH(elf, &main_elf_queue, link) 1697509ff7cSJens Wiklander DMSG("ELF (%pUl) at %#"PRIxVA, 1707509ff7cSJens Wiklander (void *)&elf->uuid, elf->load_addr); 1717509ff7cSJens Wiklander 17265137432SJens Wiklander #if TRACE_LEVEL >= TRACE_ERROR 17365137432SJens Wiklander arg->dump_entry = (vaddr_t)(void *)dump_ta_state; 17465137432SJens Wiklander #else 17565137432SJens Wiklander arg->dump_entry = 0; 17665137432SJens Wiklander #endif 177ebef121cSJerome Forissier arg->dl_entry = (vaddr_t)(void *)dl_entry; 17865137432SJens Wiklander 1797509ff7cSJens Wiklander sys_return_cleanup(); 1807509ff7cSJens Wiklander } 181