bl31的执行

来源:互联网 发布:免费看书软件哪个好 编辑:程序博客网 时间:2024/04/30 16:47
之前没有atf的时候,一般的bootflow是rom code ->uboot->kernel
有了atf后,其bootflow 改为rom code ->uboot->atf->kernel.加入没有secure os的话,这里的atf就仅仅之bl31.bin
在arm64的时候一般从rom code ->uboot的时候cpu处于el3,32bit模式,然后uboot中设置好warm reset的地址,这样在warm reset后就到atf中,将cpu且到64 bit后执行完bl31.bin 后,切到el1后返回到kernel中执行.
从bl31 中的bl31.ld.S 中SECTIONS定义可以知道,bl31的入口函数是在bl31_entrypoint
SECTIONS
{
    . = BL31_BASE;
    ASSERT(. == ALIGN(4096),
           "BL31_BASE address is not aligned on a page boundary.")

#if SEPARATE_CODE_AND_RODATA
    .text . : {
        __TEXT_START__ = .;
        *bl31_entrypoint.o(.text*)
        *(.text*)
        *(.vectors)
        . = NEXT(4096);
        __TEXT_END__ = .;
    } >RAM

func bl31_entrypoint
#if !RESET_TO_BL31
    /* ---------------------------------------------------------------
     * Preceding bootloader has populated x0 with a pointer to a
     * 'bl31_params' structure & x1 with a pointer to platform
     * specific structure
     * ---------------------------------------------------------------
     */
    mov    x20, x0
    mov    x21, x1

    /* ---------------------------------------------------------------------
     * For !RESET_TO_BL31 systems, only the primary CPU ever reaches
     * bl31_entrypoint() during the cold boot flow, so the cold/warm boot
     * and primary/secondary CPU logic should not be executed in this case.
     *
     * Also, assume that the previous bootloader has already set up the CPU
     * endianness and has initialised the memory.
     * ---------------------------------------------------------------------
     */
    el3_entrypoint_common                    \
        _set_endian=0                    \
        _warm_boot_mailbox=0                \
        _secondary_cold_boot=0                \
        _init_memory=0                    \
        _init_c_runtime=1                \
        _exception_vectors=runtime_exceptions

    /* ---------------------------------------------------------------------
     * Relay the previous bootloader's arguments to the platform layer
     * ---------------------------------------------------------------------
     */
    mov    x0, x20
    mov    x1, x21
#else
    /* ---------------------------------------------------------------------
     * For RESET_TO_BL31 systems which have a programmable reset address,
     * bl31_entrypoint() is executed only on the cold boot path so we can
     * skip the warm boot mailbox mechanism.
     * ---------------------------------------------------------------------
     */
    el3_entrypoint_common                    \
        _set_endian=1                    \
        _warm_boot_mailbox=!PROGRAMMABLE_RESET_ADDRESS    \
        _secondary_cold_boot=!COLD_BOOT_SINGLE_CPU    \
        _init_memory=1                    \
        _init_c_runtime=1                \
        _exception_vectors=runtime_exceptions

    /* ---------------------------------------------------------------------
     * For RESET_TO_BL31 systems, BL31 is the first bootloader to run so
     * there's no argument to relay from a previous bootloader. Zero the
     * arguments passed to the platform layer to reflect that.
     * ---------------------------------------------------------------------
     */
    mov    x0, 0
    mov    x1, 0
#endif /* RESET_TO_BL31 */

    /* ---------------------------------------------
     * Perform platform specific early arch. setup
     * ---------------------------------------------
     */
//分别调用bl31_early_platform_setup 和 bl31_plat_arch_setup函数,完成后返回这里继续调用bl31_main
    bl    bl31_early_platform_setup
    bl    bl31_plat_arch_setup

    /* ---------------------------------------------
     * Jump to main function.
     * ---------------------------------------------
     */
    bl bl31_main    

    /* -------------------------------------------------------------
     * Clean the .data & .bss sections to main memory. This ensures
     * that any global data which was initialised by the primary CPU
     * is visible to secondary CPUs before they enable their data
     * caches and participate in coherency.
     * -------------------------------------------------------------
     */
    adr    x0, __DATA_START__
    adr    x1, __DATA_END__
    sub    x1, x1, x0
    bl    clean_dcache_range

    adr    x0, __BSS_START__
    adr    x1, __BSS_END__
    sub    x1, x1, x0
    bl    clean_dcache_range
//执行完bl31_main 后通过el3_exit 返回
    b    el3_exit
endfunc bl31_entrypoint

其中bl31_early_platform_setup和bl31_plat_arch_setup 都是对应的平台自己需要实现的函数。我们直接看公共的code
void bl31_main(void)
{
    NOTICE("BL31: %s\n", version_string);
    NOTICE("BL31: %s\n", build_message);

    /* Perform platform setup in BL31 */
    bl31_platform_setup();

    /* Initialise helper libraries */
    bl31_lib_init();

    /* Initialize the runtime services e.g. psci. */
    INFO("BL31: Initializing runtime services\n");
    runtime_svc_init();

    /*
     * All the cold boot actions on the primary cpu are done. We now need to
     * decide which is the next image (BL32 or BL33) and how to execute it.
     * If the SPD runtime service is present, it would want to pass control
     * to BL32 first in S-EL1. In that case, SPD would have registered a
     * function to intialize bl32 where it takes responsibility of entering
     * S-EL1 and returning control back to bl31_main. Once this is done we
     * can prepare entry into BL33 as normal.
     */

    /*
     * If SPD had registerd an init hook, invoke it.
     */
//看起来bl32 是从这里跑起来的,执行完成后再回到这里继续执行bl31
    if (bl32_init) {
        INFO("BL31: Initializing BL32\n");
        (*bl32_init)();
    }
    /*
     * We are ready to enter the next EL. Prepare entry into the image
     * corresponding to the desired security state after the next ERET.
     */
// 本例中这里就是准备kernel Image
    bl31_prepare_next_image_entry();

    console_flush();

    /*
     * Perform any platform specific runtime setup prior to cold boot exit
     * from BL31
     */
//准备runtime service
    bl31_plat_runtime_setup();
}