bl31 进入bl32的过程

bl32是所谓的secure os。前面知道bl32的init函数是从bl32的main函数中调用的.在bl31中为会bl32 的secure os提供runtime service.
从arf/services/spd 下可以看到secure os 目前支持四种,分别是opteed/tlkd/trusty/tspd.我们这里以opteed为例,看opteed 这个secure os对应的runtime service 是怎么建立起来的.
/* Define an OPTEED runtime service descriptor for fast SMC calls */
DECLARE_RT_SVC(
opteed_fast,


OEN_TOS_START,
OEN_TOS_END,
SMC_TYPE_FAST,
opteed_setup,
opteed_smc_handler
);


而DECLARE_RT_SVC 这个宏是定义在services/spd/opteed/runtime_svc.h中
#define DECLARE_RT_SVC(_name, _start, _end, _type, _setup, _smch) \
static const rt_svc_desc_t __svc_desc_ ## _name \
__section("rt_svc_descs") __used = { \
.start_oen = _start, \
.end_oen = _end, \
.call_type = _type, \
.name = #_name, \
.init = _setup, \
.handle = _smch }
可以看到所有的runtime service 都要调用DECLARE_RT_SVC来声明自己,因此所有的runtime service都是放在rt_svc_descs 这个段中.
通过DECLARE_RT_SVC可以知道opteed的init 函数是opteed_setup,相应smc handler的是opteed_smc_handler。
int32_t opteed_setup(void)
{
entry_point_info_t *optee_ep_info;
uint32_t linear_id;


linear_id = plat_my_core_pos();


/*
* Get information about the Secure Payload (BL32) image. Its
* absence is a critical failure.  TODO: Add support to
* conditionally include the SPD service
*/
//获取bl32 Image的信心,optee_ep_info的定义如下:
typedef struct entry_point_info {
param_header_t h;
uintptr_t pc;
uint32_t spsr;
#ifdef AARCH32
aapcs32_params_t args;
#else
aapcs64_params_t args;
#endif
} entry_point_info_t;




optee_ep_info = bl31_plat_get_next_image_ep_info(SECURE);
if (!optee_ep_info) {
WARN("No OPTEE provided by BL2 boot loader, Booting device"
" without OPTEE initialization. SMC`s destined for OPTEE"
" will return SMC_UNK\n");
return 1;
}


/*
* If there's no valid entry point for SP, we return a non-zero value
* signalling failure initializing the service. We bail out without
* registering any handlers
*/
//optee_ep_info->pc如果为零,表示下一次要跳到0地址执行,肯定有问题,直接返回1.
if (!optee_ep_info->pc)
return 1;


/*
* We could inspect the SP image and determine it's execution
* state i.e whether AArch32 or AArch64. Assuming it's AArch32
* for the time being.
*/
opteed_rw = OPTEE_AARCH64;
opteed_init_optee_ep_state(optee_ep_info,
opteed_rw,
optee_ep_info->pc,
&opteed_sp_context[linear_id]);


/*
* All OPTEED initialization done. Now register our init function with
* BL31 for deferred invocation
*/
这里注册bl32的init函数为opteed_init
bl31_register_bl32_init(&opteed_init);


return 0;
}
void bl31_register_bl32_init(int32_t (*func)(void))
{
bl32_init = func;
}


这样在bl31_main函数中执行下面code的时候,实际会调用opteed_init
* If SPD had registerd an init hook, invoke it.
*/
if (bl32_init) {
INFO("BL31: Initializing BL32\n");
(*bl32_init)();
}
继续看看opteed_init
这个函数就会将控制权从bl31传递到bl32,执行完成后通过smc call 会带bl31_main 中.
static int32_t opteed_init(void)
{
uint32_t linear_id = plat_my_core_pos();
optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
entry_point_info_t *optee_entry_point;
uint64_t rc;


/*
* Get information about the OPTEE (BL32) image. Its
* absence is a critical failure.
*/
//再次得到BL32 Image的信息,之所以说再次,是因为在opteed_setup中已经做过同样的动作
optee_entry_point = bl31_plat_get_next_image_ep_info(SECURE);
assert(optee_entry_point);
//用optee_entry_point 初始化cpu上下文
cm_init_my_context(optee_entry_point);


/*
* Arrange for an entry into OPTEE. It will be returned via
* OPTEE_ENTRY_DONE case
*/
//设定进入bl32也就是optee的entry,当optee执行完成后通过OPTEE_ENTRY_DONE 返回
rc = opteed_synchronous_sp_entry(optee_ctx);
assert(rc != 0);


return rc;
}


uint64_t opteed_synchronous_sp_entry(optee_context_t *optee_ctx)
{
uint64_t rc;


assert(optee_ctx != NULL);
assert(optee_ctx->c_rt_ctx == 0);


/* Apply the Secure EL1 system register context and switch to it */
assert(cm_get_context(SECURE) == &optee_ctx->cpu_ctx);
cm_el1_sysregs_context_restore(SECURE);
cm_set_next_eret_context(SECURE);
//调用opteed_enter_sp 进入到optee
rc = opteed_enter_sp(&optee_ctx->c_rt_ctx);
#if DEBUG
optee_ctx->c_rt_ctx = 0;
#endif


return rc;
}




func opteed_enter_sp  
    /* Make space for the registers that we're going to save */  
    mov x3, sp  
    str x3, [x0, #0]  
    sub sp, sp, #OPTEED_C_RT_CTX_SIZE  
  
    /* Save callee-saved registers on to the stack */  
    stp x19, x20, [sp, #OPTEED_C_RT_CTX_X19]  
    stp x21, x22, [sp, #OPTEED_C_RT_CTX_X21]  
    stp x23, x24, [sp, #OPTEED_C_RT_CTX_X23]  
    stp x25, x26, [sp, #OPTEED_C_RT_CTX_X25]  
    stp x27, x28, [sp, #OPTEED_C_RT_CTX_X27]  
    stp x29, x30, [sp, #OPTEED_C_RT_CTX_X29]  
  //到这里为止,进入optee的环境已经设定好了。后面就通过el3_exit退出EL3进入OPTEE  
    /* --------------------------------------------- 
     * Everything is setup now. el3_exit() will 
     * use the secure context to restore to the 
     * general purpose and EL3 system registers to 
     * ERET into OPTEE. 
     * --------------------------------------------- 
     */  
    b   el3_exit   
endfunc opteed_enter_sp  
阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/tiantao2012/article/details/72677320
个人分类: arm-trusted-firmware
上一篇hns_mdio通过注册mdio bus对phy寄存器操作
下一篇tar
想对作者说点什么? 我来说一句
相关热词

没有更多推荐了,返回首页

关闭
关闭
关闭