日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

optee中User TA的加载和运行

發布時間:2025/3/21 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 optee中User TA的加载和运行 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

        • 1、optee中的TA簡介
        • 2、TA的調用
        • 2、tee_entry_std :std smc的調用
        • 3、open_session

思考:

  • User TA是怎樣編譯的?
  • User TA是怎樣簽名的?
  • User TA是怎樣被load到內存的?
  • 怎樣驗證TA簽名的?
  • 如何解析TA header,如何給TA分配內存,分配棧地址,分配堆地址,設置棧地址、設置堆地址?
  • TA是怎樣執行的?
  • CA/TA的initilization、openssion、inovke、closession的流程?

1、optee中的TA簡介

在optee環境中,TA分為

  • PTA : psudo TA, 屬于secure EL1, 不能調用GP Internal Core API,可以調用secure drivers等
  • TA : User TA,屬于secure EL0
    (1) early TA : 在TEE啟動的時候就需要加載到內存中的TA,或者說是打包在tee.img中的TA
    (2) ree_fs TA : 最常用的一種TA,TA Binary存在與REE的磁盤中
    (3) secstor TA : TA binary存在于安全磁盤中

CA/TA/PTA之間的調用模型如下所示

2、TA的調用

2、tee_entry_std :std smc的調用

在linux kernel中,通過GP標準調用的與TA通信的命令(opensession\invoke\closession)其實都是std smc call。
該smc調用后,會進入到TEE中的tee_entry_std中:

/** Note: this function is weak just to make it possible to exclude it from* the unpaged area.*/ void __weak tee_entry_std(struct thread_smc_args *smc_args) {paddr_t parg;struct optee_msg_arg *arg = NULL; /* fix gcc warning */uint32_t num_params = 0; /* fix gcc warning */struct mobj *mobj;if (smc_args->a0 != OPTEE_SMC_CALL_WITH_ARG) {EMSG("Unknown SMC 0x%" PRIx64, (uint64_t)smc_args->a0);DMSG("Expected 0x%x\n", OPTEE_SMC_CALL_WITH_ARG);smc_args->a0 = OPTEE_SMC_RETURN_EBADCMD;return;}parg = (uint64_t)smc_args->a1 << 32 | smc_args->a2;/* Check if this region is in static shared space */if (core_pbuf_is(CORE_MEM_NSEC_SHM, parg,sizeof(struct optee_msg_arg))) {mobj = get_cmd_buffer(parg, &num_params);} else {if (parg & SMALL_PAGE_MASK) {smc_args->a0 = OPTEE_SMC_RETURN_EBADADDR;return;}mobj = map_cmd_buffer(parg, &num_params);}if (!mobj || !ALIGNMENT_IS_OK(parg, struct optee_msg_arg)) {EMSG("Bad arg address 0x%" PRIxPA, parg);smc_args->a0 = OPTEE_SMC_RETURN_EBADADDR;mobj_free(mobj);return;}arg = mobj_get_va(mobj, 0);assert(arg && mobj_is_nonsec(mobj));/* Enable foreign interrupts for STD calls */thread_set_foreign_intr(true);switch (arg->cmd) {case OPTEE_MSG_CMD_OPEN_SESSION:entry_open_session(smc_args, arg, num_params); --------------------------open_sessionbreak;case OPTEE_MSG_CMD_CLOSE_SESSION:entry_close_session(smc_args, arg, num_params); --------------------------close_sessionbreak;case OPTEE_MSG_CMD_INVOKE_COMMAND:entry_invoke_command(smc_args, arg, num_params); --------------------------invoke cmdbreak;case OPTEE_MSG_CMD_CANCEL:entry_cancel(smc_args, arg, num_params);break;case OPTEE_MSG_CMD_REGISTER_SHM:register_shm(smc_args, arg, num_params);break;case OPTEE_MSG_CMD_UNREGISTER_SHM:unregister_shm(smc_args, arg, num_params);break;default:EMSG("Unknown cmd 0x%x\n", arg->cmd);smc_args->a0 = OPTEE_SMC_RETURN_EBADCMD;}mobj_free(mobj); }

3、open_session

open_session---->entry_open_session

tee_ta_init_user_ta_session
load_elf_from_store

static TEE_Result load_elf_from_store(const TEE_UUID *uuid,const struct user_ta_store_ops *ta_store,struct user_ta_ctx *utc) {struct user_ta_store_handle *handle = NULL;struct elf_load_state *elf_state = NULL;struct ta_head *ta_head;struct user_ta_elf *exe;struct user_ta_elf *elf;struct user_ta_elf *prev;TEE_Result res;size_t vasize;void *p;size_t n;size_t num_segs = 0;struct load_seg *segs = NULL;res = ta_store->open(uuid, &handle);if (res){if (res != TEE_ERROR_ITEM_NOT_FOUND)EMSG("[%s %d] Error res=0x%x",__func__, __LINE__, res);return res;}elf = ta_elf(uuid, utc);if (!elf) {res = TEE_ERROR_OUT_OF_MEMORY;goto out;}exe = TAILQ_FIRST(&utc->elfs);prev = TAILQ_PREV(elf, user_ta_elf_head, link);res = elf_load_init(ta_store, handle, elf == exe, &utc->elfs,resolve_symbol, &elf_state);if (res){EMSG("[%s %d] Error res=0x%x",__func__, __LINE__, res);goto out;}elf->elf_state = elf_state;res = elf_load_head(elf_state,---------------------------load header, header中包含vasize和stack_sizeelf == exe ? sizeof(struct ta_head) : 0,&p, &vasize, &utc->is_32bit);if (res){EMSG("[%s %d] Error res=0x%x",__func__, __LINE__, res);goto out;}ta_head = p;elf->mobj_code = alloc_ta_mem(vasize);--------------------------在TA RAM中分配內存,給TA的代碼段使用if (!elf->mobj_code) {res = TEE_ERROR_OUT_OF_MEMORY;goto out;}if (elf == exe) {/* Ensure proper alignment of stack */size_t stack_sz = ROUNDUP(ta_head->stack_size,STACK_ALIGNMENT);utc->mobj_stack = alloc_ta_mem(stack_sz);-------------------在TA RAM中分配內存,給TA的棧使用if (!utc->mobj_stack) {res = TEE_ERROR_OUT_OF_MEMORY;goto out;}}/** Map physical memory into TA virtual memory*/if (elf == exe) {res = vm_info_init(utc);---------------------------------map codeif (res != TEE_SUCCESS){EMSG("[%s %d] Error res=0x%x",__func__, __LINE__, res);goto out;}/* Add stack segment */utc->stack_addr = 0;res = vm_map(utc, &utc->stack_addr, utc->mobj_stack->size,--------------------------------map stackTEE_MATTR_URW | TEE_MATTR_PRW, utc->mobj_stack,0);if (res){EMSG("[%s %d] Error res=0x%x",__func__, __LINE__, res);goto out;}}res = get_elf_segments(elf, &segs, &num_segs);if (res != TEE_SUCCESS){EMSG("[%s %d] Error res=0x%x",__func__, __LINE__, res);goto out;}if (prev) {elf->load_addr = prev->load_addr + prev->mobj_code->size;elf->load_addr = ROUNDUP(elf->load_addr,CORE_MMU_USER_CODE_SIZE);}for (n = 0; n < num_segs; n++) {uint32_t prot = elf_flags_to_mattr(segs[n].flags) |TEE_MATTR_PRW;segs[n].va = elf->load_addr - segs[0].offs + segs[n].offs;segs[n].size = segs[n].oend - segs[n].offs;res = vm_map(utc, &segs[n].va, segs[n].size, prot,elf->mobj_code, segs[n].offs);if (res){EMSG("[%s %d] Error res=0x%x",__func__, __LINE__, res);goto out;}if (!n) {elf->load_addr = segs[0].va;DMSG("ELF load address %#" PRIxVA, elf->load_addr);}}tee_mmu_set_ctx(&utc->ctx);res = elf_load_body(elf_state, elf->load_addr);if (res){EMSG("[%s %d] Error res=0x%x",__func__, __LINE__, res);goto out;}/* Find any external dependency (dynamically linked libraries) */res = add_deps(utc, elf_state, elf->load_addr); out:if (res) {free(segs);EMSG("[%s %d] Error res=0x%x",__func__, __LINE__, res);} else {elf->segs = segs;elf->num_segs = num_segs;}ta_store->close(handle);/* utc is cleaned by caller on error */return res; }

elf_load_head其實就是從TA binary中讀取ta_head結構體,里面包含uuid、stack_size、ta_entry

struct ta_head {TEE_UUID uuid;uint32_t stack_size;uint32_t flags;union ta_head_func_ptr entry; };

我們打開一個TA的反匯編文件查看,

ta_head占用0x20字節,.txt從0x20處開始,ta_entry應該就等于0x20

architecture: aarch64, flags 0x00000150: HAS_SYMS, DYNAMIC, D_PAGED start address 0x0000000000000020Program Header:LOAD off 0x0000000000010000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**16filesz 0x000000000000777c memsz 0x000000000000777c flags r-xLOAD off 0x0000000000017780 vaddr 0x0000000000007780 paddr 0x0000000000007780 align 2**16filesz 0x0000000000001c34 memsz 0x0000000000001c34 flags r--LOAD off 0x000000000001a000 vaddr 0x000000000000a000 paddr 0x000000000000a000 align 2**16filesz 0x0000000000001cfc memsz 0x000000000000c740 flags rw-DYNAMIC off 0x0000000000019040 vaddr 0x0000000000009040 paddr 0x0000000000009040 align 2**3filesz 0x00000000000000f0 memsz 0x00000000000000f0 flags rw-Dynamic Section:HASH 0x0000000000009360STRTAB 0x00000000000092b0SYMTAB 0x0000000000009130STRSZ 0x00000000000000acSYMENT 0x0000000000000018DEBUG 0x0000000000000000RELA 0x0000000000008d38RELASZ 0x00000000000002a0RELAENT 0x0000000000000018RELACOUNT 0x0000000000000013Sections: Idx Name Size VMA LMA File off Algn0 .ta_head 00000020 0000000000000000 0000000000000000 00010000 2**3CONTENTS, ALLOC, LOAD, DATA1 .text 0000775c 0000000000000020 0000000000000020 00010020 2**2CONTENTS, ALLOC, LOAD, READONLY, CODE2 .rodata 000015b4 0000000000007780 0000000000007780 00017780 2**3CONTENTS, ALLOC, LOAD, READONLY, DATA3 .dynsym 00000180 0000000000009130 0000000000009130 00019130 2**3CONTENTS, ALLOC, LOAD, READONLY, DATA4 .rela.dyn 000001c8 0000000000008d38 0000000000008d38 00018d38 2**3CONTENTS, ALLOC, LOAD, READONLY, DATA5 .got 00000068 0000000000008f00 0000000000008f00 00018f00 2**3CONTENTS, ALLOC, LOAD, DATA6 .rela.got 000000d8 0000000000008f68 0000000000008f68 00018f68 2**3CONTENTS, ALLOC, LOAD, READONLY, DATA7 .dynamic 000000f0 0000000000009040 0000000000009040 00019040 2**3CONTENTS, ALLOC, LOAD, DATA8 .dynstr 000000ac 00000000000092b0 00000000000092b0 000192b0 2**0CONTENTS, ALLOC, LOAD, READONLY, DATA9 .hash 00000054 0000000000009360 0000000000009360 00019360 2**3CONTENTS, ALLOC, LOAD, READONLY, DATA10 .data 00001cfc 000000000000a000 000000000000a000 0001a000 2**3CONTENTS, ALLOC, LOAD, DATA11 .bss 0000aa40 000000000000bd00 000000000000bd00 0001bcfc 2**3ALLOC12 .debug_info 000103be 0000000000000000 0000000000000000 0001bcfc 2**0CONTENTS, READONLY, DEBUGGING13 .debug_abbrev 00003fbb 0000000000000000 0000000000000000 0002c0ba 2**0CONTENTS, READONLY, DEBUGGING14 .debug_loc 00015e83 0000000000000000 0000000000000000 00030075 2**0CONTENTS, READONLY, DEBUGGING15 .debug_aranges 00000b70 0000000000000000 0000000000000000 00045f00 2**4CONTENTS, READONLY, DEBUGGING16 .debug_ranges 00000ea0 0000000000000000 0000000000000000 00046a70 2**4CONTENTS, READONLY, DEBUGGING17 .debug_line 00003bde 0000000000000000 0000000000000000 00047910 2**0CONTENTS, READONLY, DEBUGGING18 .debug_str 0000267d 0000000000000000 0000000000000000 0004b4ee 2**0CONTENTS, READONLY, DEBUGGING19 .comment 0000003c 0000000000000000 0000000000000000 0004db6b 2**0CONTENTS, READONLY20 .debug_frame 00002220 0000000000000000 0000000000000000 0004dba8 2**3CONTENTS, READONLY, DEBUGGING

alloc_ta_mem就是從tee_mm_sec_ddr的pool中分配內存(tee_mm_sec_ddr的pool其實就是MEM_AREA_TA_RAM類型的內存,也就是TA RAM)

static struct mobj *alloc_ta_mem(size_t size) { #ifdef CFG_PAGED_USER_TAreturn mobj_paged_alloc(size); #elsestruct mobj *mobj = mobj_mm_alloc(mobj_sec_ddr, size, &tee_mm_sec_ddr);if (mobj)memset(mobj_get_va(mobj, 0), 0, size);return mobj; #endif }

tee_mm_sec_ddr的pool就是MEM_AREA_TA_RAM類型的內存,也就是TA RAM

void teecore_init_ta_ram(void) {vaddr_t s;vaddr_t e;paddr_t ps;paddr_t pe;/* get virtual addr/size of RAM where TA are loaded/executedNSec* shared mem allcated from teecore */core_mmu_get_mem_by_type(MEM_AREA_TA_RAM, &s, &e);ps = virt_to_phys((void *)s);pe = virt_to_phys((void *)(e - 1)) + 1;if (!ps || (ps & CORE_MMU_USER_CODE_MASK) ||!pe || (pe & CORE_MMU_USER_CODE_MASK))panic("invalid TA RAM");/* extra check: we could rely on core_mmu_get_mem_by_type() */if (!tee_pbuf_is_sec(ps, pe - ps))panic("TA RAM is not secure");if (!tee_mm_is_empty(&tee_mm_sec_ddr))panic("TA RAM pool is not empty");/* remove previous config and init TA ddr memory pool */tee_mm_final(&tee_mm_sec_ddr);tee_mm_init(&tee_mm_sec_ddr, ps, pe, CORE_MMU_USER_CODE_SHIFT,TEE_MM_POOL_NO_FLAGS); }

vm_info_init會調用到vm_map,在map物理內存到TA的虛擬內存之后,然后又會調用到core_mmu_set_user_map,創建頁表,講頁表寫入到MMU寄存器.
有下列代碼可值,User TA程序也是使用的TTBR0. 頁表也是使用的l1_xlation_table,其中user_va_idx宏=-1,也就是數組中的最后一個。

void core_mmu_set_user_map(struct core_mmu_user_map *map) {uint64_t ttbr;uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL);assert(user_va_idx != -1);ttbr = read_ttbr0_64bit();/* Clear ASID */ttbr &= ~((uint64_t)TTBR_ASID_MASK << TTBR_ASID_SHIFT);write_ttbr0_64bit(ttbr);isb();/* Set the new map */if (map && map->user_map) {l1_xlation_table[0][get_core_pos()][user_va_idx] =map->user_map; #ifdef CFG_CORE_UNMAP_CORE_AT_EL0l1_xlation_table[1][get_core_pos()][user_va_idx] =map->user_map; #endifdsb(); /* Make sure the write above is visible */ttbr |= ((uint64_t)map->asid << TTBR_ASID_SHIFT);write_ttbr0_64bit(ttbr);isb();} else {l1_xlation_table[0][get_core_pos()][user_va_idx] = 0; #ifdef CFG_CORE_UNMAP_CORE_AT_EL0l1_xlation_table[1][get_core_pos()][user_va_idx] = 0; #endifdsb(); /* Make sure the write above is visible */}tlbi_all();thread_unmask_exceptions(exceptions); }

總結

以上是生活随笔為你收集整理的optee中User TA的加载和运行的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。