optee的ld文件在如下路径os/core/arch/arm/kernel/kern.ld.S
ENTRY(_start)
SECTIONS
{
. = CFG_TEE_LOAD_ADDR;
__text_start = .;
/*
* Memory between CFG_TEE_LOAD_ADDR and page aligned rounded down
* value will be mapped with unpaged "text" section attributes:
* likely to be read-only/executable.
*/
__flatmap_unpg_rx_start = ROUNDDOWN(__text_start, SMALL_PAGE_SIZE);
.text : {
KEEP(*(.text.boot.vectab1))
KEEP(*(.text.boot.vectab2))
KEEP(*(.text.boot))
}
从这里可以知道optee的第一行指令是_start,optee 只是arm32和arm64.这里以arm64为例
arm64的_start 定义在os/core/arch/arm/kernel/generic_entry_a64.S 中
/*
* Setup SP_EL0 and SPEL1, SP will be set to SP_EL0.
* SP_EL0 is assigned stack_tmp + (cpu_id + 1) * stack_tmp_stride -
* stack_tmp_offset
* SP_EL1 is assigned thread_core_local[cpu_id]
*/
.macro set_sp
bl get_core_pos
cmp x0, #CFG_TEE_CORE_NB_CORE
/* Unsupported CPU, park it before it breaks something */
bge unhandled_cpu
add x0, x0, #1
adr x2, stack_tmp_stride
ldr w1, [x2]
mul x2, x0, x1
adrp x1, stack_tmp
add x1, x1, :lo12:stack_tmp
add x1, x1, x2
adr x2, stack_tmp_offset
ldr w2, [x2]
sub x1, x1, x2
msr spsel, #0
mov sp, x1
bl thread_get_core_local
msr spsel, #1
mov sp, x0
msr spsel, #0
.endm
.section .text.boot
入口地址从这里开始执行optee os
FUNC _start , :
mov x19, x0 /* Save pagable part address */
mov x20, x2 //x2传递过来DT address /* Save DT address */
adr x0, reset_vect_table
msr vbar_el1, x0
isb
mrs x0, sctlr_el1
mov x1, #(SCTLR_I | SCTLR_A | SCTLR_SA)
orr x0, x0, x1
msr sctlr_el1, x0
isb
#ifdef CFG_WITH_PAGER
/*
* Move init code into correct location
*
* The binary is built as:
* [Pager code, rodata and data] : In correct location
* [Init code and rodata] : Should be copied to __init_start
* [Hashes] : Should be saved before clearing bss
*
* When we copy init code and rodata into correct location we don't
* need to worry about hashes being overwritten as size of .bss,
* .heap, .nozi and .heap3 is much larger than the size of init
* code and rodata and hashes.
*/
adr x0, __init_start /* dst */
adr x1, __data_end /* src */
adr x2, __init_end /* dst limit */
copy_init:
ldp x3, x4, [x1], #16
stp x3, x4, [x0], #16
cmp x0, x2
b.lt copy_init
#endif
/* Setup SP_EL0 and SP_EL1, SP will be set to SP_EL0 */
set_sp
/* Enable aborts now that we can receive exceptions */
msr daifclr, #DAIFBIT_ABT
adr x0, __text_start
#ifdef CFG_WITH_PAGER
adrp x1, __init_end
add x1, x1, :lo12:__init_end
#else
adrp x1, __end
add x1, x1, :lo12:__end
#endif
sub x1, x1, x0
bl inv_dcache_range
/* Enable Console */
bl console_init //初始化串口
bl core_init_mmu_map //初始化mmu
bl core_init_mmu_regs //初始化mmu 寄存器
bl cpu_mmu_enable //经过前两步后可以使能mmu
bl cpu_mmu_enable_icache //使能icache
bl cpu_mmu_enable_dcache 使能Dcache
mov x0, x19 /* pagable part address */
mov x1, #-1
mov x2, x20 /* DT address */
bl generic_boot_init_primary // 执行主要初始化
/*
* 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.
*/
mov x19, x0
adr x0, __text_start
#ifdef CFG_WITH_PAGER
adrp x1, __init_end
add x1, x1, :lo12:__init_end
#else
adrp x1, __end
add x1, x1, :lo12:__end
#endif
sub x1, x1, x0
bl flush_dcache_range
/*
* Clear current thread id now to allow the thread to be reused on
* next entry. Matches the thread_init_boot_thread in
* generic_boot.c.
*/
bl thread_clr_boot_thread //调用thread_clr_boot_thread清理current thread id
/* Pass the vector address returned from main_init */
mov x1, x19
mov x0, #TEESMC_OPTEED_RETURN_ENTRY_DONE
//通过smc 返回到ATF的el3中,通知atf optee已经启动完成.
smc #0
b . /* SMC should not return */
END_FUNC _start
ENTRY(_start)
SECTIONS
{
. = CFG_TEE_LOAD_ADDR;
__text_start = .;
/*
* Memory between CFG_TEE_LOAD_ADDR and page aligned rounded down
* value will be mapped with unpaged "text" section attributes:
* likely to be read-only/executable.
*/
__flatmap_unpg_rx_start = ROUNDDOWN(__text_start, SMALL_PAGE_SIZE);
.text : {
KEEP(*(.text.boot.vectab1))
KEEP(*(.text.boot.vectab2))
KEEP(*(.text.boot))
}
从这里可以知道optee的第一行指令是_start,optee 只是arm32和arm64.这里以arm64为例
arm64的_start 定义在os/core/arch/arm/kernel/generic_entry_a64.S 中
/*
* Setup SP_EL0 and SPEL1, SP will be set to SP_EL0.
* SP_EL0 is assigned stack_tmp + (cpu_id + 1) * stack_tmp_stride -
* stack_tmp_offset
* SP_EL1 is assigned thread_core_local[cpu_id]
*/
.macro set_sp
bl get_core_pos
cmp x0, #CFG_TEE_CORE_NB_CORE
/* Unsupported CPU, park it before it breaks something */
bge unhandled_cpu
add x0, x0, #1
adr x2, stack_tmp_stride
ldr w1, [x2]
mul x2, x0, x1
adrp x1, stack_tmp
add x1, x1, :lo12:stack_tmp
add x1, x1, x2
adr x2, stack_tmp_offset
ldr w2, [x2]
sub x1, x1, x2
msr spsel, #0
mov sp, x1
bl thread_get_core_local
msr spsel, #1
mov sp, x0
msr spsel, #0
.endm
.section .text.boot
入口地址从这里开始执行optee os
FUNC _start , :
mov x19, x0 /* Save pagable part address */
mov x20, x2 //x2传递过来DT address /* Save DT address */
adr x0, reset_vect_table
msr vbar_el1, x0
isb
mrs x0, sctlr_el1
mov x1, #(SCTLR_I | SCTLR_A | SCTLR_SA)
orr x0, x0, x1
msr sctlr_el1, x0
isb
#ifdef CFG_WITH_PAGER
/*
* Move init code into correct location
*
* The binary is built as:
* [Pager code, rodata and data] : In correct location
* [Init code and rodata] : Should be copied to __init_start
* [Hashes] : Should be saved before clearing bss
*
* When we copy init code and rodata into correct location we don't
* need to worry about hashes being overwritten as size of .bss,
* .heap, .nozi and .heap3 is much larger than the size of init
* code and rodata and hashes.
*/
adr x0, __init_start /* dst */
adr x1, __data_end /* src */
adr x2, __init_end /* dst limit */
copy_init:
ldp x3, x4, [x1], #16
stp x3, x4, [x0], #16
cmp x0, x2
b.lt copy_init
#endif
/* Setup SP_EL0 and SP_EL1, SP will be set to SP_EL0 */
set_sp
/* Enable aborts now that we can receive exceptions */
msr daifclr, #DAIFBIT_ABT
adr x0, __text_start
#ifdef CFG_WITH_PAGER
adrp x1, __init_end
add x1, x1, :lo12:__init_end
#else
adrp x1, __end
add x1, x1, :lo12:__end
#endif
sub x1, x1, x0
bl inv_dcache_range
/* Enable Console */
bl console_init //初始化串口
bl core_init_mmu_map //初始化mmu
bl core_init_mmu_regs //初始化mmu 寄存器
bl cpu_mmu_enable //经过前两步后可以使能mmu
bl cpu_mmu_enable_icache //使能icache
bl cpu_mmu_enable_dcache 使能Dcache
mov x0, x19 /* pagable part address */
mov x1, #-1
mov x2, x20 /* DT address */
bl generic_boot_init_primary // 执行主要初始化
/*
* 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.
*/
mov x19, x0
adr x0, __text_start
#ifdef CFG_WITH_PAGER
adrp x1, __init_end
add x1, x1, :lo12:__init_end
#else
adrp x1, __end
add x1, x1, :lo12:__end
#endif
sub x1, x1, x0
bl flush_dcache_range
/*
* Clear current thread id now to allow the thread to be reused on
* next entry. Matches the thread_init_boot_thread in
* generic_boot.c.
*/
bl thread_clr_boot_thread //调用thread_clr_boot_thread清理current thread id
/* Pass the vector address returned from main_init */
mov x1, x19
mov x0, #TEESMC_OPTEED_RETURN_ENTRY_DONE
//通过smc 返回到ATF的el3中,通知atf optee已经启动完成.
smc #0
b . /* SMC should not return */
END_FUNC _start