Overview

LK 是 Little Kernel

它是 appsbl(Applications ARM Boot Loader)流程代码,

little kernel 是小内核小操作系统。

Code structure

code directory

bootable/bootloadler/lk

folders

       +app            // 应用相关
       +arch           // arm 体系
       +dev            // 设备相关
       +include      // 头文件
       +kernel        // lk系统相关  
       +platform    // 相关驱动
       +projiect     // makefile文件
       +scripts      // Jtag 脚本
       +target        // 具体板子相关

building

bootup sequence

ENTRY(start)指定 LK 从start 函数开始

bootable/bootloadler/lk/arch/arm/ssystem-onesegment.ld 

_start

lk/arch/arm/crt0.S中

reset->Lstack_setup->kmain

crt0.S 主要做一些基本的 CPU 的初始化再通过 bl kmain ;跳转到 C 代码中。

kmain

lk/kernel/main.c 中

kmain works

  • 1、本身 lk 这个系统模块的初始化
  • 2、boot 的启动初始化动作。

analyze

// 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");

// deal with any static constructors
dprintf(SPEW, "calling constructors\n");
call_constructors();

// bring up the kernel heap
dprintf(SPEW, "initializing heap\n");
heap_init();

// 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

thread_resume(thread_create("bootstrap2", &bootstrap2, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));

bootstrap2

arch_init();

// initialize the rest of the platform
dprintf(SPEW, "initializing platform\n");
platform_init();
dprintf(SPEW, "calling apps_init()\n");
apps_init();

apps_init

/* call all the init routines */
for (app = &__apps_start; app != &__apps_end; app++) {
    if (app->init)
        app->init(app);
}

Aboot.c (app\aboot) 42379 11/23/2012

APP_START(aboot)
    .init = aboot_init,

aboot_init

key checking and enter recovery||fastboot || normal boot

/* Check if we should do something other than booting up */
if (keys_get_state(KEY_HOME) != 0)
    boot_into_recovery = 1;
if (keys_get_state(KEY_VOLUMEUP) != 0)
    boot_into_recovery = 1;
if(!boot_into_recovery)
{
    if (keys_get_state(KEY_BACK) != 0)
        goto fastboot;
    if (keys_get_state(KEY_VOLUMEDOWN) != 0)
        goto fastboot;
}

boot_linux from XXX

if (target_is_emmc_boot())
{
    ...
    boot_linux_from_mmc();
}
else
{
    recovery_init();
    ...
    boot_linux_from_flash();
}

boot_linux_from_mmc

if (!boot_into_recovery) {
    index = partition_get_index("boot");
    ptn = partition_get_offset(index);
    if(ptn == 0) {
        dprintf(CRITICAL, "ERROR: No boot partition found\n");
                return -1;
    }
}
else {
    index = partition_get_index("recovery");
    ptn = partition_get_offset(index);
    if(ptn == 0) {
        dprintf(CRITICAL, "ERROR: No recovery partition found\n");
                return -1;
    }
}

    image_addr = (unsigned char *)target_get_scratch_address();

    /* Move kernel, ramdisk and device tree to correct address */
    memmove((void*) hdr->kernel_addr, (char *)(image_addr + page_size), hdr->kernel_size);
    memmove((void*) hdr->ramdisk_addr, (char *)(image_addr + page_size + kernel_actual), hdr->ramdisk_size);



boot_linux((void *)hdr->kernel_addr, (unsigned *) hdr->tags_addr,
       (const char *)cmdline, board_machtype(),
       (void *)hdr->ramdisk_addr, hdr->ramdisk_size);

boot_linux

void (*entry)(unsigned, unsigned, unsigned*) = kernel;
entry(0, machtype, tags);

machine type is stored in R1?

Reference