mtk-lk代码分析

本文简单介绍了mtk-lk阶段的启动流程。

1.crt0.S的_start跳转到kmain执行

.section ".text.boot"
.globl _start
_start:
        ......
    bl        kmain

2.kmain函数在kernel/main.c中定义

void kmain(void)
{
//初始化线程系统,初始化run_queue& thread链表,初始化bootstrap线程,并标记为当前线程  
    thread_init_early();

//设置异常向量表基地址,使能mmu和neon,neon为多媒体应用优化设计
    arch_early_init();

//平台相关初始化,中断、uart、gpio、wdt、i2c、pmic等,很多在preloader阶段已经完成的无需重复初始化    
    platform_early_init();

//目标板子前期初始化,这里并未定义
    target_early_init();
    
//调用构造函数,调用.ctors段中的函数,使用objdump反汇编lk文件,并不存在.ctors段,这里直接跳过
    call_constructors();

//初始化堆空间,插入空闲堆空间,并进行整合,减少碎片化
    heap_init();

//timer线程初始化,这里跳过这步
    thread_init();

//初始化dpc线程,调用dpc_queue将callback函数加入线程中,有时间触发时,线程会顺序执行回调函数
    dpc_init();
//初始化timer_queue,并设置每隔10ms产生中断调用timer_tick函数 timer_init(); #if (!ENABLE_NANDWRITE) //创建并执行bootstrap2线程 dprintf(SPEW, "creating bootstrap completion thread\n"); thread_resume(thread_create("bootstrap2", &bootstrap2, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE)); //退出临界区,使能中断 exit_critical_section(); //标记当前线程为空闲状态,即bootstrap线程空闲 thread_become_idle(); #else bootstrap_nandwrite(); #endif }
  • platform_early_init
void platform_early_init(void)
{
//初始化gic controller platform_init_interrupts();
//timer前期初始化 platform_early_init_timer();
//gpio设置为default状态 mt_gpio_set_default();
//串口初始化,从bootarg中获取串口和波特率并进行设置 uart_init_early();
//wdt初始化 mtk_wdt_init();
//i2c初始化,preloader阶段已经完成,这里忽略 i2c_hw_init();
//pmic初始化,preloader阶段完成,这里忽略 pmic_init(); }
  • call_constructors,遍历.ctors(__ctor_list到__ctor_end)段中所有的函数,并执行,通过objdump反编译lk并不存在.ctors段,这里直接忽略
static void call_constructors(void)
{
    void **ctor;
   
    ctor = &__ctor_list;
    while(ctor != &__ctor_end) {
        void (*func)(void);

        func = (void (*)())*ctor;

        func();
        ctor++;
    }
}
  • heap_init,堆初始化
void heap_init(void)
{
    LTRACE_ENTRY;
//设置堆空间范围
    theheap.base = (void *)HEAP_START;
    theheap.len = HEAP_LEN;

//初始化空闲堆链表
    list_initialize(&theheap.free_list);

//创建空闲堆块,并插入空闲堆链表中,并与前后相邻空闲堆合并,初始化阶段就一个空闲堆
    heap_insert_free_chunk(heap_create_free_chunk(theheap.base, theheap.len));
#ifdef MTK_3LEVEL_PAGETABLE
//标记堆初始化标志位为1
extern ld_tt_l2_info_t ld_tt_l2_info; ld_tt_l2_info.heap_init_done = 1; #endif }
  • dpc_init,初始化dpc线程,该线程负责顺序执行dpc链表中的cb函数,thread_exit函数调用dpc_queue,负责处理线程退出时的清理工作,包括从线程链表中删除节点并释放线程的栈空间
void dpc_init(void)
{
 //初始化dpc_event  
    event_init(&dpc_event, false, 0);
//创建并启用dpc线程,调用dpc_thread_routine函数,等待dpc_event事件发生
    thread_resume(thread_create("dpc", &dpc_thread_routine, NULL, DPC_PRIORITY, DEFAULT_STACK_SIZE));
}

static int dpc_thread_routine(void *arg)
{
//循环等待dpc事件发生
    for (;;) {
        event_wait(&dpc_event);
//关闭中断,进入临界区
        enter_critical_section();
//将该dpc从链表中删除
        struct dpc *dpc = list_remove_head_type(&dpc_list, struct dpc, node);
        if (!dpc)
//dpc信号触发标志清零
            event_unsignal(&dpc_event);
//打开中断,退出临界区
        exit_critical_section();

        if (dpc) {
//执行dpc的callback函数
            dpc->cb(dpc->arg);

            free(dpc);
        }
    }

    return 0;
}

//通过dpc_queue将需要执行的操作加入dpc链表中
status_t dpc_queue(dpc_callback cb, void *arg, uint flags)
{
    struct dpc *dpc;

    dpc = malloc(sizeof(struct dpc));

    dpc->cb = cb;
    dpc->arg = arg;
    enter_critical_section();
    list_add_tail(&dpc_list, &dpc->node);
    event_signal(&dpc_event, (flags & DPC_FLAG_NORESCHED) ? false : true);
    exit_critical_section();

    return NO_ERROR;
}

timer_init

ongoing......

 3.bootstrap2代码分析

static int bootstrap2(void *arg)
{
//arch初始化,这里忽略直接返回
    arch_init();
//平台其余部分初始化
    platform_init();
//target初始化,这里忽略直接返回    
    target_init();
//调用app->init函数,加载并启动kernel
    apps_init();

    return 0;
}
  • platform_init
void platform_init(void)
{
//mmc初始化 mmc_legacy_init(
1);
//led初始化 leds_init();
//env初始化 env_init();
//设置framebuffer的起始地址和大小 g_fb_size
= mt_disp_get_vram_size(); g_fb_base = mblock_reserve(&g_boot_arg->mblock_info, g_fb_size, 0x10000, 0xa0000000, RANKMAX);
//display&lcm初始化 mt_disp_init((
void *)g_fb_base);
//填充fb为黑画面 mt_disp_fill_rect(
0, 0, CFG_DISPLAY_WIDTH, CFG_DISPLAY_HEIGHT, 0x0);
   mt_disp_update(
0, 0, CFG_DISPLAY_WIDTH, CFG_DISPLAY_HEIGHT);
//初始化console drv_video_init();
//这里直接返回 set_kpd_pmic_mode();
//启动模式 boot_mode_select();
//加载开机动画 mboot_common_load_logo((unsigned
long)mt_get_logo_db_addr_pa(), "logo");
//安全相关 sec_func_init(pl_start_addr); seclib_set_oemkey(g_oemkey, OEM_PUBK_SZ);
//pll设置 mt_pll_turn_off();
//battery,charge相关 mt65xx_bat_init();
//rtc开机检测 rtc_boot_check(
false); //关机充电启动则显示充电图标,否则显示正常开机画面 if (kernel_charging_boot() == 1) {   mt_disp_power(TRUE);   mt_disp_show_low_battery();   mt65xx_leds_brightness_set(6, 110); } else if (g_boot_mode != KERNEL_POWER_OFF_CHARGING_BOOT && g_boot_mode != LOW_POWER_OFF_CHARGING_BOOT) { if (g_boot_mode != ALARM_BOOT && (g_boot_mode != FASTBOOT)) { mt_disp_show_boot_logo(); } } //打开背光 mt65xx_backlight_on(); mt_disp_update(0, 0, CFG_DISPLAY_WIDTH, CFG_DISPLAY_HEIGHT);
//在LCM上显示开机模式文字,正常开机显示"=> NORMAL BOOT",user版本该文字不显示 sw_env(); }
  • app_init
void apps_init(void)
{
    const struct app_descriptor *app;
//调用.apps段中的app_init函数
    for (app = &__apps_start; app != &__apps_end; app++) {
        if (app->init)
            app->init(app);
    }
    /* start any that want to start on boot */
    for (app = &__apps_start; app != &__apps_end; app++) {
        if (app->entry && (app->flags & APP_FLAG_DONT_START_ON_BOOT) == 0) {
            start_app(app);
        }
    }
}

mt_boot.c文件中定义了app,调用mt_boot_init函数,APP_START宏定义的内容放入.apps段中
APP_START(mt_boot)
.init = mt_boot_init,
 APP_END
#define APP_START(appname) struct app_descriptor _app_##appname __SECTION(".apps") = { .name = #appname,
#define APP_END };
  • mt_boot_init,主要调用boot_linux_from_storage函数加载并启动内核
boot_linux_from_storage();
boot_linux_from_storage
int boot_linux_from_storage(void)
{
//加载bootimage header ret
= mboot_android_load_bootimg_hdr(PART_BOOTIMG, CFG_BOOTIMG_LOAD_ADDR);
//加载bootimage ret
= mboot_android_load_bootimg(PART_BOOTIMG, kimg_load_addr); #ifndef SKIP_LOADING_RAMDISK if (g_rimg_sz == 0) { if (g_boot_hdr != NULL) { g_rimg_sz = g_boot_hdr->ramdisk_size; } } #ifdef MTK_3LEVEL_PAGETABLE /* rootfs addr */ if (g_boot_hdr != NULL) { arch_mmu_map((uint64_t)g_boot_hdr->ramdisk_addr, (uint32_t)g_boot_hdr->ramdisk_addr, MMU_MEMORY_TYPE_NORMAL_WRITE_BACK | MMU_MEMORY_AP_P_RW_U_NA, ROUNDUP(g_rimg_sz, PAGE_SIZE)); } #endif /* relocate rootfs (ignore rootfs header) */ memcpy((g_boot_hdr!=NULL) ? (char *)g_boot_hdr->ramdisk_addr : (char *)CFG_RAMDISK_LOAD_ADDR, (char *)(g_rmem_off), g_rimg_sz); g_rmem_off = (g_boot_hdr!=NULL) ? g_boot_hdr->ramdisk_addr : CFG_RAMDISK_LOAD_ADDR; #endif custom_port_in_kernel(g_boot_mode, cmdline_get()); boot_linux((void *)g_boot_hdr->kernel_addr, (unsigned *)g_boot_hdr->tags_addr, (char *)cmdline_get(), board_machtype(), (void *)g_boot_hdr->ramdisk_addr, g_rimg_sz); }

猜你喜欢

转载自www.cnblogs.com/ant-man/p/9102055.html
MTK