bl2_main函数完成了bl2阶段的主要操作,包括
该函数的主要内容和相关注释如下:
** void bl2_main(void)
{
entry_point_info_t *next_bl_ep_info;
bl2_arch_setup(); //执行平台相关初始化
#if TRUSTED_BOARD_BOOT
/* Initialize authentication module */
auth_mod_init(); //初始化image验证模块
#endif /* TRUSTED_BOARD_BOOT */
//加载bl3x image到RAM中并返回bl31的入口地址
next_bl_ep_info = bl2_load_images();
#ifdef AARCH32
disable_mmu_icache_secure(); //禁止MMU的指令cache
#endif /* AArch32 */
console_flush(); //刷新console操作
/* 调用smc指令,触发在bl1中设定的smc异常中断处理函数,跳转到bl31 */
smc(BL1_SMC_RUN_IMAGE, (unsigned long)next_bl_ep_info, 0, 0, 0, 0,0, 0);
}**
bl2_load_images函数完成将bl32和bl33的镜像文件加载到内存中并返回bl31镜像的入口地址,最终在bl2_main函数中通过触发安全监控模式调用(smc)跳转到bl31,并将CPU控制权限交给bl31。
该函数的主要内容和注释如下:
entry_point_info_t *bl2_load_images(void)
{
bl_params_t *bl2_to_next_bl_params;
bl_load_info_t *bl2_load_info;
const bl_load_info_node_t *bl2_node_info;
int plat_setup_done = 0;
int err;
/* 获取bl3x image的加载和入口函数信息 */
bl2_load_info = plat_get_bl_image_load_info();
/* 检查返回的bl2_load_info中的信息是否正确 */
assert(bl2_load_info);
assert(bl2_load_info- >head);
assert(bl2_load_info- >h.type == PARAM_BL_LOAD_INFO);
assert(bl2_load_info- >h.version >= VERSION_2);
/* 将bl2_load_info中的head变量的值赋值为bl2_node_info,即将bl31 image的入口信息
传递给bl2_node_info变量 */
bl2_node_info = bl2_load_info- >head;
/* 进入loop循环 */
while (bl2_node_info) {
/* 在加载特定的bl3x image到RAM之前先确定是否需要进行平台的初始化 */
if (bl2_node_info- >image_info- >h.attr & IMAGE_ATTRIB_PLAT_SETUP) {
if (plat_setup_done) {
WARN("BL2: Platform setup already done! ! n");
} else {
INFO("BL2: Doing platform setupn");
bl2_platform_setup();
plat_setup_done = 1;
}
}
/* 对bl3x image进行电子验签,如果通过则执行加载操作 */
if (! (bl2_node_info- >image_info- >h.attr & IMAGE_ATTRIB_SKIP_LOADING)) {
INFO("BL2: Loading image id %dn", bl2_node_info- >image_id);
err = load_auth_image(bl2_node_info- >image_id,
bl2_node_info- >image_info);
if (err) {
ERROR("BL2: Failed to load image (%i)n", err);
plat_error_handler(err);
}
} else {
INFO("BL2: Skip loading image id %dn", bl2_node_info- >image_id);
}
/* 可以根据实际需要更改,通过给定image ID来更改image的加载信息 */
err = bl2_plat_handle_post_image_load(bl2_node_info- >image_id);
if (err) {
ERROR("BL2: Failure in post image load handling (%i)n", err);
plat_error_handler(err);
}
bl2_node_info = bl2_node_info- >next_load_info;
}
/* 获取下一个执行的镜像的入口信息,并且将以后会被执行的镜像的入口信息组合成链表,通过判断
image des中的ep_info.h.attr的值是否为(EXECUTABLE|EP_FIRST_EX)来确定接下来第一个
被执行的image*/
bl2_to_next_bl_params = plat_get_next_bl_params();
assert(bl2_to_next_bl_params);
assert(bl2_to_next_bl_params- >head);
assert(bl2_to_next_bl_params- >h.type == PARAM_BL_PARAMS);
assert(bl2_to_next_bl_params- >h.version >= VERSION_2);
plat_flush_next_bl_params();
/* 返回下一个进入的镜像的入口信息,即bl31的入口信息 */
return bl2_to_next_bl_params- >head- >ep_info;
}
ATF使用bl_mem_params_node_t结构体变量数组bl_mem_params_desc_ptr来保存bl3x镜像文件的信息。该结构体内容如下:
typedef struct bl_mem_params_node {
unsigned int image_id; //镜像文件的id值
image_info_t image_info; //镜像文件的信息
entry_point_info_t ep_info; //bl3x的入口地址信息
unsigned int next_handoff_image_id; //写一个阶段bl3x的id值
bl_load_info_node_t load_node_mem; //该镜像文件需要被保存在RAM中的信息
bl_params_node_t params_node_mem; //该镜像文件启动时所需参数在RAM中的信息
} bl_mem_params_node_t;
在bl2_load_images函数中通过调用plat_get_bl_image_load_info函数来获取bl3x镜像文件的信息,ATF源代码中通过使用REGISTER_BL_IMAGE_DESCS宏将事先定义好的bl2_mem_params_descs变量中的数据保存到bl_mem_params_desc_ptr数组中,而bl2_mem_params_descs中保存的就是所有bl3x镜像文件的基本信息,开发者可根据不同平台的实际情况修改bl2_mem_params_descs变量中各镜像文件的信息。
全部0条评论
快来发表一下你的评论吧 !