bl31 进入bl32的过程
来源:互联网 发布:java 哈希表 编辑:程序博客网 时间:2024/05/21 09:44
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
从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
阅读全文
0 0
- bl31 进入bl32的过程
- bl31的执行
- bl31 runtime service的注册和查找
- 离开和进入trusted os的过程
- 4. ATF(ARM Trusted firmware)启动---bl2到bl31的跳转
- 进入/退出过程指令
- 从开机到进入操作系统的引导过程详解
- 在进入Mapper之前的输入分片处理过程详解
- 从S0状态进入sleep状态的过程
- Liinux 系统无法进入图形界面的解决过程
- Asp.net MVC进入请求管道的过程
- 必须快速进入具体的编程方式的学习过程中
- 无法进入系统的三星Android手机恢复联系人、短信数据并重置手机的过程
- [精华] Linux的发行版制作简要过程--------不知者进入:-)
- uboot 的启动过程及工作原理 进入 C 代码部分
- freeswitch 两方通话过程中,按*3进入指定的会议
- mapreduce 过程中关于 0-length 数据进入reducer 时的处理
- mac帧进入交换机后如何添加去除vlan信息的过程
- 【2015年第六届蓝桥杯C/C++程序设计本科B组决赛 关联账户(代码填空) 】+ 并查集
- MySQL中的表中增加删除字段
- 打开sns AP侧log输出
- win7登录cent6.7 samba服务器失败问题解决
- 算法导论程序16--基数排序(Python)
- bl31 进入bl32的过程
- 代理模式
- 【工具类】-转换人民币大小金额
- MVCC原理探究及MySQL源码实现分析
- Spring+EhCache缓存实例
- 解决VS2013单元测试调用Oracle时出现32位兼容问题
- phpcms v9调用指定栏目名称、url、图片、描述、子栏目、文章
- 半是转载半是自己代码与总结
- hash map 的工作原理。转