lk:littlekernel-概述

little kernel做为Android系统的bootloader,最早用google工程师实现,其后由高通,MTK等芯片厂商做了各自平台的适配。
lk的主要功能:

    初始化硬件模块,如时钟,中断,UART,USB,LCD,PMIC,eMMC/UFS等。
    更新cmdline。其中重要的是区分启动模式。
    选择和更新device tree。
    设置好系统状态,跳转到kernel。 MMU = off, D-cache = off, I-cache = on or off,x0 = physical address to the FDT blob。
    fastboot功能。
    鉴权。

 

           LK 代码结构
           +app              // 应用相关
           +arch             // arm 体系 
           +dev              // 设备相关
           +include          // 头文件
           +kernel           // lk系统相关   
           +platform         // 相关驱动
           +projiect         // makefile文件
           +scripts          // Jtag 脚本
           +target           // 具体板子相关
在 bootable/bootloadler/lk/arch/arm/ssystem-onesegment.ld 连接文件中 ENTRY(_start)指定 LK 从_start 函数开始,_start 在 lk/arch/crt0.S中 。
crt0.S 主要做一些基本的 CPU 的初始化再通过 bl  kmain ;
跳转到 C 代码中。kmain 在 lk/kernel/main.c 中

转自https://www.cnblogs.com/LoongEmbedded/p/5298331.html

 

c语言的入口函数为kmain,在lk/kernel/main.c:

kmain 主要做两件事:1、本身 lk 这个系统模块的初始化;2、boot 的启动初始化动作。

/* called from crt0.S */
void kmain(void) __NO_RETURN __EXTERNALLY_VISIBLE;
void kmain(void)
{
	thread_t *thr;

	// get us into some sort of thread context
	thread_init_early();  /*1.初始化进程(lk 中的简单进程)相关结构体。*/

	// early arch stuff
	arch_early_init();    /*2.使能 mmu 的 arm 相关工作。其中会开关cache,这里分x86或者arm架构。*/

	// do any super early platform initialization
	platform_early_init();/*3.相关平台的早期初始化 	board_init();platform_clock_init();qgic_init();qtimer_init();scm_init();不同平台大同小异*/

	// do any super early target initialization
	target_early_init();  /*  4.现在就一个函数跳转,初始化UART(板子相关)uart_dm_init*/

	dprintf(INFO, "welcome to lk\n\n");
	bs_set_timestamp(BS_BL_START);/*5.背光点亮时间戳?*/

	// deal with any static constructors
	dprintf(SPEW, "calling constructors\n");
	call_constructors();/*6.构造函数初始化*/

	// bring up the kernel heap
	dprintf(SPEW, "initializing heap\n");
	heap_init();            /*7.lk系统相关的堆栈初始化*/

	__stack_chk_guard_setup();/*8.初始化堆栈保护*/

	// initialize the threading system
	dprintf(SPEW, "initializing threads\n");
	thread_init();        /*9.简短的初始化定时器对象*/

	// initialize the dpc system
	dprintf(SPEW, "initializing dpc\n");
	dpc_init();            /*10.lk系统控制器初始化(相关事件初始化)*/

	// initialize kernel timers
	dprintf(SPEW, "initializing timers\n");
	timer_init();            /*11.初始化lk中的定时器*/

#if (!ENABLE_NANDWRITE)
	// create a thread to complete system initialization
	dprintf(SPEW, "creating bootstrap completion thread\n");
	thr = thread_create("bootstrap2", &bootstrap2, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE);
	if (!thr)
	{
		panic("failed to create thread bootstrap2\n");
	}
	thread_resume(thr);/* 12.新建线程入口函数 bootstrap2 用于boot 工作(重点)arch_init platform_int target_init apps_init*/


	// enable interrupts
	exit_critical_section();

	// become the idle thread
	thread_become_idle();
#else
        bootstrap_nandwrite();
#endif
}
static int bootstrap2(void *arg)
{
	dprintf(SPEW, "top of bootstrap2()\n");

	arch_init();

	// XXX put this somewhere else
#if WITH_LIB_BIO
	bio_init();
#endif
#if WITH_LIB_FS
	fs_init();
#endif

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

	// initialize the target
	dprintf(SPEW, "initializing target\n");
	target_init();

	dprintf(SPEW, "calling apps_init()\n");
	apps_init();

	return 0;
}
 bootstrap2 
         bootstrap2 在kmain的末尾以线程方式开启。主要分三步:platform_init、target_init、apps_init。
        1.platform_init
               platform_init 中主要是函数 acpu_clock_init。
               在 acpu_clock_init 对 arm11 进行系统时钟设置,超频 
        2.target_init
              针对硬件平台进行设置。主要对 arm9 和 arm11 的分区表进行整合,初始化flash和读取FLASH信息
        3.apps_init  
             apps_init 是关键,对 LK 中所谓 app 初始化并运行起来,而 aboot_init 就将在这里开始被运行,android linux 内核的加载工作就在 aboot_init 中完成的 。
grep -rn "APP_START"  //这个宏用来往app_descriptor塞入需要启动的进程

include/app.h:45:#define APP_START(appname) struct app_descriptor _app_##appname __SECTION(".apps") = { .name = #appname,

app/stringtests/string_tests.c:283:APP_START(stringtests)
app/clocktests/clock_tests.c:119:APP_START(clocktests)
app/pcitests/pci_tests.c:247:APP_START(pcitests)
app/shell/shell.c:37:APP_START(shell)
app/aboot/aboot.c:4690:APP_START(aboot)   ///这个是我们的aboot
app/tests/tests.c:42:APP_START(tests)

 

然后用apps_init()函数调用lk中的另一个关键的c语言函数aboot_init()。由aboot_init()调用boot_linux_from_mmc()。
再由boot_linux_from_mmc()调用boot_linux()。
最后由boot_linux()调用entry()函数(32位kernel)或者scm_elexec_call()(64位kernel),完成lk到kernel的跳转。
lk初始化调用流程如下图:


---------------------  
作者:viewsky11  
来源:CSDN  
原文:https://blog.csdn.net/viewsky11/article/details/53906070  
版权声明:本文为博主原创文章,转载请附上博文链接!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值