赞
踩
BL2 image将会为后续image的加载执行相关的初始化操作。主要是内存,MMU,串口以及EL3软件运行环境的设置,并且加载bl3x的image到RAM中。通过查看bl2.ld.S文件就可以发现,bl2 image的入口函数是bl2_entrypoint。该函数定义在bl2/aarch64/bl2_entrypoint.S文件中。
该函数的内容如下,该函数最终会出发smc操作,从bl1中将CPU的控制权转交给bl31:
func bl2_entrypoint /*--------------------------------------------- * Save from x1 the extents of the tzram * available to BL2 for future use. * x0 is not currently used. * --------------------------------------------- */ mov x20, x1 /* --------------------------------------------- * Set the exception vector to something sane. * --------------------------------------------- */ adr x0, early_exceptions //设定异常向量 msr vbar_el1, x0 isb /* --------------------------------------------- * Enable the SError interrupt now that the * exception vectors have been setup. * --------------------------------------------- */ msr daifclr, #DAIF_ABT_BIT /* --------------------------------------------- * Enable the instruction cache, stack pointer * and data access alignment checks * --------------------------------------------- */ mov x1, #(SCTLR_I_BIT | SCTLR_A_BIT | SCTLR_SA_BIT) mrs x0, sctlr_el1 orr x0, x0, x1 msr sctlr_el1, x0 isb /* --------------------------------------------- * Invalidate the RW memory used by the BL2 * image. This includes the data and NOBITS * sections. This is done to safeguard against * possible corruption of this memory by dirty * cache lines in a system cache as a result of * use by an earlier boot loader stage. * --------------------------------------------- */ adr x0, __RW_START__ adr x1, __RW_END__ sub x1, x1, x0 bl inv_dcache_range /* --------------------------------------------- * Zero out NOBITS sections. There are 2 of them: * - the .bss section; * - the coherent memory section. * --------------------------------------------- */ ldr x0, =__BSS_START__ ldr x1, =__BSS_SIZE__ bl zeromem #if USE_COHERENT_MEM ldr x0, =__COHERENT_RAM_START__ ldr x1, =__COHERENT_RAM_UNALIGNED_SIZE__ bl zeromem #endif /* -------------------------------------------- * Allocate a stack whose memory will be marked * as Normal-IS-WBWA when the MMU is enabled. * There is no risk of reading stale stack * memory after enabling the MMU as only the * primary cpu is running at the moment. * -------------------------------------------- */ bl plat_set_my_stack //初始化bl2运行的栈 /* --------------------------------------------- * Initialize the stack protector canary before * any C code is called. * --------------------------------------------- */ #if STACK_PROTECTOR_ENABLED bl update_stack_protector_canary #endif /* --------------------------------------------- * Perform early platform setup & platform * specific early arch. setup e.g. mmu setup * --------------------------------------------- */ mov x0, x20 bl bl2_early_platform_setup //设置平台相关 bl bl2_plat_arch_setup //设置架构相关 /* --------------------------------------------- * Jump to main function. * --------------------------------------------- */ bl bl2_main //跳转到BL2的主要函数执行,从该函数中跳转到bl31以及bl31, /* --------------------------------------------- * Should never reach this point. * --------------------------------------------- */ no_ret plat_panic_handler endfunc bl2_entrypoint
该函数主要实现将bl3x的image加载RAM中,并通过smc调用执行bl1中指定的smc handle将CPU的全向交给bl31。
void bl2_main(void) { entry_point_info_t *next_bl_ep_info; NOTICE("BL2: %s\n", version_string); NOTICE("BL2: %s\n", build_message); /* Perform remaining generic architectural setup in S-EL1 */ bl2_arch_setup(); #if TRUSTED_BOARD_BOOT /* Initialize authentication module */ auth_mod_init(); //初始化image验证模块 #endif /* TRUSTED_BOARD_BOOT */ /* Load the subsequent bootloader images. */ next_bl_ep_info = bl2_load_images(); //加载bl3x image到RAM中并返回bl31的入口地址 #ifdef AARCH32 /* * For AArch32 state BL1 and BL2 share the MMU setup. * Given that BL2 does not map BL1 regions, MMU needs * to be disabled in order to go back to BL1. */ disable_mmu_icache_secure(); #endif /* AARCH32 */ console_flush(); /* * Run next BL image via an SMC to BL1. Information on how to pass * control to the BL32 (if present) and BL33 software images will * be passed to next BL image as an argument. */ /* 调用smc指令,触发在bl1中设定的smc异常中断处理函数,跳转到bl31 */ smc(BL1_SMC_RUN_IMAGE, (unsigned long)next_bl_ep_info, 0, 0, 0, 0, 0, 0); }
该函数用来加载bl3x的image到RAM中,返回一个具有image入口信息的变量。smc handle根据该变量跳转到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; /* * Get information about the images to load. */ /* 获取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) { /* * Perform platform setup before loading the image, * if indicated in the image attributes AND if NOT * already done before. */ /* 在加载特定的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 setup\n"); 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 %d\n", 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 %d\n", bl2_node_info->image_id); } /* Allow platform to handle image information. */ /* 可以根据实际需要更改,通过给定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); } /* Go to next image */ bl2_node_info = bl2_node_info->next_load_info; } /* * Get information to pass to the next image. */ /* 获取下一个执行的Image的入口信息,并且将以后会被执行的image的入口信息组合成链表 ,t通过判断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); /* Flush the parameters to be passed to next image */ plat_flush_next_bl_params(); /* 返回下一个进入的image的入口信息,即bl31的入口信息 */ return bl2_to_next_bl_params->head->ep_info; }
该宏的执行将会初始化组成bl2加载bl3x image的列表使用到的重要全局变量,其中bl2_mem_params_descs变量的定义如下:
static bl_mem_params_node_t bl2_mem_params_descs[] = { #ifdef SCP_BL2_BASE /* Fill SCP_BL2 related information if it exists */ { .image_id = SCP_BL2_IMAGE_ID, SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY, VERSION_2, entry_point_info_t, SECURE | NON_EXECUTABLE), SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY, VERSION_2, image_info_t, 0), .image_info.image_base = SCP_BL2_BASE, .image_info.image_max_size = PLAT_CSS_MAX_SCP_BL2_SIZE, .next_handoff_image_id = INVALID_IMAGE_ID, }, #endif /* SCP_BL2_BASE */ #ifdef EL3_PAYLOAD_BASE /* Fill EL3 payload related information (BL31 is EL3 payload)*/ { .image_id = BL31_IMAGE_ID, SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2, entry_point_info_t, SECURE | EXECUTABLE | EP_FIRST_EXE), .ep_info.pc = EL3_PAYLOAD_BASE, .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS), SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2, image_info_t, IMAGE_ATTRIB_PLAT_SETUP | IMAGE_ATTRIB_SKIP_LOADING), .next_handoff_image_id = INVALID_IMAGE_ID, }, #else /* EL3_PAYLOAD_BASE */ /* Fill BL31 related information */ { .image_id = BL31_IMAGE_ID, SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2, entry_point_info_t, SECURE | EXECUTABLE | EP_FIRST_EXE), .ep_info.pc = BL31_BASE, .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS), #if DEBUG .ep_info.args.arg1 = ARM_BL31_PLAT_PARAM_VAL, #endif SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2, image_info_t, IMAGE_ATTRIB_PLAT_SETUP), .image_info.image_base = BL31_BASE, .image_info.image_max_size = BL31_LIMIT - BL31_BASE, # ifdef BL32_BASE .next_handoff_image_id = BL32_IMAGE_ID, # else .next_handoff_image_id = BL33_IMAGE_ID, # endif }, # ifdef BL32_BASE /* Fill BL32 related information */ { .image_id = BL32_IMAGE_ID, SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2, entry_point_info_t, SECURE | EXECUTABLE), .ep_info.pc = BL32_BASE, SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2, image_info_t, 0), .image_info.image_base = BL32_BASE, .image_info.image_max_size = BL32_LIMIT - BL32_BASE, .next_handoff_image_id = BL33_IMAGE_ID, }, # endif /* BL32_BASE */ /* Fill BL33 related information */ { .image_id = BL33_IMAGE_ID, SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2, entry_point_info_t, NON_SECURE | EXECUTABLE), # ifdef PRELOADED_BL33_BASE .ep_info.pc = PRELOADED_BL33_BASE, SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING), # else .ep_info.pc = PLAT_ARM_NS_IMAGE_OFFSET, SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2, image_info_t, 0), .image_info.image_base = PLAT_ARM_NS_IMAGE_OFFSET, .image_info.image_max_size = ARM_DRAM1_SIZE, # endif /* PRELOADED_BL33_BASE */ .next_handoff_image_id = INVALID_IMAGE_ID, } #endif /* EL3_PAYLOAD_BASE */ };
在该变量中规定了SCP_BL2, EL3_payload, bl32, bl33 image的相关信息,例如:
image的入口地址信息:ep_info
image在RAM中的基地址:image_base
image的基本信息:image_info
image的ID值:image_id
</article>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。