optee是从ATF中启动的,是作为一个svc来启动,启动玩后在optee中又通过smc返回到ATF中.
从core/arch/arm/kernel/kern.ld.S 中可以发现optee的入口,这也是个通用的规律,即从lds文件中找到入口函数
OUTPUT_FORMAT(CFG_KERN_LINKER_FORMAT)
OUTPUT_ARCH(CFG_KERN_LINKER_ARCH)
ENTRY(_start)
这里可以知道入口是_start,针对arm32的函数在entry_a32.S 中,针对arm64的入口函数在entry_a64.S中
_start 函数如下,这个函数中调用了很多其他函数,后面我们逐个分析.最后通过smc #0 返回到ATF中
FUNC _start , :
#if defined(CFG_CORE_SEL1_SPMC)
/*
* With OP-TEE as SPMC at S-EL1 the SPMD (SPD_spmd) in TF-A passes
* the DTB in x0, pagaeble part in x1 and the rest of the registers
* are unused
*/
mov x19, x1 /* Save pagable part */
mov x20, x0 /* Save DT address */
#else
mov x19, x0 /* Save pagable part address */
#if defined(CFG_DT_ADDR)
ldr x20, =CFG_DT_ADDR
#else
mov x20, x2 /* Save DT address */
#endif
#endif
adr x0, reset_vect_table
msr vbar_el1, x0
isb
set_sctlr_el1
isb
#ifdef CFG_WITH_PAGER
/*
* Move init code into correct location and move hashes to a
* temporary safe location until the heap is initialized.
*
* The binary is built as:
* [Pager code, rodata and data] : In correct location
* [Init code and rodata] : Should be copied to __init_start
* [struct boot_embdata + data] : Should be saved before
* initializing pager, first uint32_t tells the length of the data
*/
adr x0, __init_start /* dst */
adr x1, __data_end /* src */
adr x2, __init_end
sub x2, x2, x0 /* init len */
ldr w4, [x1, x2] /* length of hashes etc */
add x2, x2, x4 /* length of init and hashes etc */
/* Copy backwards (as memmove) in case we're overlapping */
add x0, x0, x2 /* __init_start + len */
add x1, x1, x2 /* __data_end + len */
adr x3, cached_mem_end
str x0, [x3]
adr x2, __init_start
copy_init:
ldp x3, x4, [x1, #-16]!
stp x3, x4, [x0, #-16]!
cmp x0, x2
b.gt copy_init
#else
/*
* The binary is built as:
* [Core, rodata and data] : In correct location
* [struct boot_embdata + data] : Should be moved to __end, first
* uint32_t tells the length of the struct + data
*/
adr_l x0, __end /* dst */
adr_l x1, __data_end /* src */
ldr w2, [x1] /* struct boot_embdata::total_len */
/* Copy backwards (as memmove) in case we're overlapping */
add x0, x0, x2
add x1, x1, x2
adr x3, cached_mem_end
str x0, [x3]
adr_l x2, __end
copy_init:
ldp x3, x4, [x1, #-16]!
stp x3, x4, [x0, #-16]!
cmp x0, x2
b.gt copy_init
#endif
/*
* Clear .bss, this code obviously depends on the linker keeping
* start/end of .bss at least 8 byte aligned.
*/
adr_l x0, __bss_start
adr_l x1, __bss_end
clear_bss:
str xzr, [x0], #8
cmp x0, x1
b.lt clear_bss
#设置SP
/* Setup SP_EL0 and SP_EL1, SP will be set to SP_EL0 */
set_sp
#线程的初始化
bl thread_init_thread_core_local
/* Enable aborts now that we can receive exceptions */
msr daifclr, #DAIFBIT_ABT
/*
* Invalidate dcache for all memory used during initialization to
* avoid nasty surprices when the cache is turned on. We must not
* invalidate memory not used by OP-TEE since we may invalidate
* entries used by for instance ARM Trusted Firmware.
*/
adr_l x0, __text_start
ldr x1, cached_mem_end
sub x1, x1, x0
bl dcache_cleaninv_range
#使能串口
/* Enable Console */
bl console_init
#ifdef CFG_CORE_ASLR
mov x0, x20
bl get_aslr_seed
#else
mov x0, #0
#endif
adr x1, boot_mmu_config
bl core_init_mmu_map
#使能mmu
bl __get_core_pos
bl enable_mmu
mov x0, x19 /* pagable part address */
mov x1, #-1
bl boot_init_primary_early
mov x0, x20 /* DT address */
bl boot_init_primary_late
/*
* In case we've touched memory that secondary CPUs will use before
* they have turned on their D-cache, clean and invalidate the
* D-cache before exiting to normal world.
*/
adr_l x0, __text_start
ldr x1, cached_mem_end
sub x1, x1, x0
bl dcache_cleaninv_range
/*
* Clear current thread id now to allow the thread to be reused on
* next entry. Matches the thread_init_boot_thread in
* boot.c.
*/
#ifdef CFG_CORE_FFA
adr x0, cpu_on_handler
/*
* Compensate for the load offset since cpu_on_handler() is
* called with MMU off.
*/
ldr x1, boot_mmu_config + CORE_MMU_CONFIG_LOAD_OFFSET
sub x0, x0, x1
bl ffa_secondary_cpu_ep_register
b thread_ffa_msg_wait
#else
/*
* Pass the vector address returned from main_init
* Compensate for the load offset since cpu_on_handler() is
* called with MMU off.
*/
ldr x0, boot_mmu_config + CORE_MMU_CONFIG_LOAD_OFFSET
adr x1, thread_vector_table
sub x1, x1, x0
mov x0, #TEESMC_OPTEED_RETURN_ENTRY_DONE
smc #0
b . /* SMC should not return */
#endif
END_FUNC _start
DECLARE_KEEP_INIT _start