androidLK启动过程

andoid的启动过程

通过audio口所吐出的log,我们可以发现android的启动还是非常之有趣的,因而在此对它的启动做相应的分析。

在此分析LK的启动过程,LK就是bootloader。

现在只截取一部分的Log

[0] welcome to lk
[10] platform_init()
[10] target_init()
[60] SDHC Running in HS400 mode
[60] Done initialization of the card
[70] pm8x41_get_is_cold_boot: Warm boot
[70] Unsupported platform id
[70] Qseecom Init Done in Appsbl
[70] secure app region addr=0x85b00000 size=0x800000[80] TZ App region notif returned with status:0 addr:85b00000 size:8388608
[90] TZ App log region register returned with status:0 addr:8f6a9000 size:4096
[90] Qseecom TZ Init Done in Appsbl
[100] Loading cmnlib done
[110] qseecom_start_app: Loading app keymaster for the first time'
[120] <8>keymaster: "\"KEYMASTER Init \""
[130] Waiting for the RPM to populate smd channel table

现在可以根据这部分的log来看LK是如何加载的。

当android加载完fileware时,LK会通过crt0.s的跳转命令,跳转到main.c中的kmain函数中去。

#ifdef ARM_CPU_CORTEX_A8
    DSB
    ISB
#endif
    bl      kmain
    b       .
.ltorg

那么kmain又做了什么?

/* called from crt0.S */
void kmain(void) __NO_RETURN __EXTERNALLY_VISIBLE;
void kmain(void)
{
    // get us into some sort of thread context
    thread_init_early();
    // early arch stuff
    arch_early_init();
    // do any super early platform initialization
    platform_early_init();
    // do any super early target initialization
    target_early_init();
    dprintf(INFO, "welcome to lk\n\n");
    bs_set_timestamp(BS_BL_START);
    // deal with any static constructors
    dprintf(SPEW, "calling constructors\n");
    call_constructors();
    // bring up the kernel heap
    dprintf(SPEW, "initializing heap\n");
    heap_init();
    __stack_chk_guard_setup();
    // initialize the threading system
    dprintf(SPEW, "initializing threads\n");
    thread_init();
    // initialize the dpc system
    dprintf(SPEW, "initializing dpc\n");
    dpc_init();
    // initialize kernel timers
    dprintf(SPEW, "initializing timers\n");
    timer_init();
    #if (!ENABLE_NANDWRITE)
    // create a thread to complete system initialization
    dprintf(SPEW, "creating bootstrap completion thread\n");
    thread_resume(thread_create("bootstrap2", &bootstrap2, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
    // enable interrupts
    exit_critical_section();
    // become the idle thread
    thread_become_idle();
    #else
        bootstrap_nandwrite();
    #endif
}

在这里,我们充分看到了Lk在kmain()中做了大量的初始化动作,其中thread_init_early()主要的工作是初始化线程系统,就是创建队列,然后系统根据CPU的不同架构进入不同的init线程

/**
 * @brief  Initialize threading system
 *
 * This function is called once, from kmain()
 */
void thread_init_early(void)
{
    int i;
    /* initialize the run queues */
    for (i=0; i < NUM_PRIORITIES; i++)
        list_initialize(&run_queue[i]);
    /* initialize the thread list */
    list_initialize(&thread_list);
    /* create a thread to cover the current running state */
    thread_t *t = &bootstrap_thread;
    init_thread_struct(t, "bootstrap");
    /* half construct this thread, since we're already running */
    t->priority = HIGHEST_PRIORITY;
    t->state = THREAD_RUNNING;
    t->saved_critical_section_count = 1;
    list_add_head(&thread_list, &t->thread_list_node);
    current_thread = t;
}

arch_early_init()函数,一般采用的高通的芯片,因而会导向lk/arch/arm/arch.c,那么其主要的工作设置基本CPU属性

    void arch_early_init(void)
    {
        /* turn off the cache */
        arch_disable_cache(UCACHE);
        /* set the vector base to our exception vectors so we dont need to double map at 0 */
    #if ARM_CPU_CORTEX_A8
        set_vector_base(MEMBASE);
    #endif
    #if ARM_WITH_MMU
        arm_mmu_init();
    #endif
        /* turn the cache back on */
        arch_enable_cache(UCACHE);
    #if ARM_WITH_NEON
        /* enable cp10 and cp11 */
        uint32_t val;
        __asm__ volatile("mrc   p15, 0, %0, c1, c0, 2" : "=r" (val));
        val |= (3<<22)|(3<<20);
        __asm__ volatile("mcr   p15, 0, %0, c1, c0, 2" :: "r" (val));
        isb();
        /* set enable bit in fpexc */
        __asm__ volatile("mrc  p10, 7, %0, c8, c0, 0" : "=r" (val));
        val |= (1<<30);
        __asm__ volatile("mcr  p10, 7, %0, c8, c0, 0" :: "r" (val));
    #endif
    #if ARM_CPU_CORTEX_A8
        /* enable the cycle count register */
        uint32_t en;
        __asm__ volatile("mrc   p15, 0, %0, c9, c12, 0" : "=r" (en));
        en &= ~(1<<3); /* cycle count every cycle */
        en |= 1; /* enable all performance counters */
        __asm__ volatile("mcr   p15, 0, %0, c9, c12, 0" :: "r" (en));
        /* enable cycle counter */
        en = (1<<31);
        __asm__ volatile("mcr   p15, 0, %0, c9, c12, 1" :: "r" (en));
    #endif
    }

/lk/platform/msmtitanium/platform.c中的platform_early_init()首先会调用board_init(),它会去调用lk/platform/msm_shared/board.c中的Platform_detect函数来检测平台信息,平台信息包含主要信息(format_major)与次要信息(format_minor)。通过信息来初始化平台版本\hw\type,lk/target/msmtitanium/init.c中target_detect()不做任何事情,而target_baseband_detect函数会测试modem type

void platform_early_init(void)
{
    board_init();
    platform_clock_init();
    qgic_init();
    qtimer_init();
    scm_init();
}

platform_clock_init会初始化一些时钟信息,qgic_init(void)初始化qgic(qgic是什么?),qtimer_init()提供初始化频率,scm_init()是scm的初始化函数(表示小编并不了解什么是scm机制)

target_early_init()函数是对串口的初始化,因而此时可以看到lk的第一条log:welcome to lk,后面的几个函数就是对一些时序,状态等等的初始化。

你可能感兴趣的:(androidLK启动过程)