美文网首页
androidLK启动过程

androidLK启动过程

作者: AlexKing阁下 | 来源:发表于2016-06-09 23:17 被阅读880次

    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启动过程

          本文链接:https://www.haomeiwen.com/subject/gzhsdttx.html