[热文]Android 系统开发之-----bootloader (lk) 分析

转发评论 03月19日 22:19

什么是LK

lk就是 Little Kernel ,android lk 也是appsboot 是Qualcomm平台arm11 端的 bootloader。它是类似OS一样的小操作系统。

lk源码位置在android 系统下:

boottable/bootloader/lk 目录

+app // 应用相关

+arch // arm 体系

+scripts // Jtag 脚本

+kernel // 系统相关

+platform // 驱动相关

+project // 一些 makefile 文件

+target // 板子相关

LK 分析

lk入口 在 crt0.s 中_start 函数开始 (在连接文件 system_onesegment.ld 中ENTRY(_start)指定

crt0.s :lk/arch/crt0.s

1.设置向量表

2.初始化BSS 载

3.跳到 C 函数( bl kmain )

kmain 函数: lk/kernel/main.c

1.thread_init_early() 初始化lk系统进程相关

2.arch_early_init() cpu相关的初始化 如:关闭 cache 使能mmu等

3.platform_early_init() 具体的平台相关初始化

4.target_early_init() 对平台的检测

5.call_constructors() 构造函数相关

6.heap_init(); lk系统堆栈的初始化

7.thread_init() 线程相关初始化

8.dpc_init(); LK相关控制系统初始化(涉及event 事件机制)

9.timer_init() lk定时器初始化

10.bootstrap2() 系统相关重点 下面专门分析


bootstrap2函数

它在kmain的最后被以新的简单线程的方式运行起来的。

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

bootstrap2 主要做了3件事:platform_init() , target_init() , apps_init() .

platform_init:它就一个函数调用 acpu_clock_init ,对arm 11 进行系统时钟设置http://www.itxiazai.info/,超频。

target_init: 针对不同的硬件平台进行设置,有键盘设置,和系统 分区表(partition table)的设置。

apps_init: apps_init是关键,对LK中的所谓app初始化并运行起来,而aboot_init 就在开始被运行。(aboot_init 加载linux


源码片段:

voidacpu_clock_init(void)
{

/* 初始化 PLL */
writel(0x0, SCPLL_CTL);
writel(0x00400002, SCPLL_CTL);
writel(0x00600004, SCPLL_CTL);
thread_sleep(1);
while(readl(SCPLL_STAT) & 0x2);
writel(0x0, SCPLL_CTL);

/* 使能 pll */
while(readl(SCPLL_STAT) & 0x1);
val = readl(SCPLL_CTL);
val &= ~(0x7);
val |= 0x2;
writel(val, SCPLL_CTL);
thread_sleep(1);
val = readl(SCPLL_CTL);
val |= 0x7;
writel(val, SCPLL_CTL);
thread_sleep(1);

/*先调频到 384MHz 再跳到 768MHz */

/*设置cpu频率到 384 MHz */
while(readl(SCPLL_STAT) & 0x3);
val = readl(SCPLL_CTLE);
val &= ~(0x3F << 3);
val |= (0xA << 3);
val &= ~(0x3 << 0);
val |= (4 << 0);
writel(val, SCPLL_CTLE);
writel(0x00600007, SCPLL_CTL);
thread_sleep(1);


/* 跳到 768MHz */
while(readl(SCPLL_STAT) & 0x3);
val = readl(SCPLL_CTLE);
val &= ~(0x3F << 3);
val |= (0x14 << 3);
val &= ~(0x3 << 0);
val |= (5 << 0);
writel(val, SCPLL_CTLE); //升频
writel(0x00600007, SCPLL_CTL);
thread_sleep(1);

val = readl(A11S_CLK_SEL);
val &= ~(0x3 << 1);
val |= (1 << 1);
writel(val, A11S_CLK_SEL); //升频

}

voidtarget_init(void)
{
#if (!ENABLE_NANDWRITE)

keys_init();

keypad_init();
#endif
ptable_init(&flash_ptable); //读取 arm11 端分区表
smem_ptable_init(); //读取 arm9 端分区表

............

flash_init(); //初始化flash

flash_info = flash_get_info(); //读取flash信息
............

offset = smem_get_apps_flash_start();

............

total_num_of_blocks = flash_info->num_blocks;

...........

smem_add_modem_partitions(&flash_ptable);

ptable_dump(&flash_ptable);

flash_set_ptable(&flash_ptable); //把arm9 和 arm 11两个分区表整合起来

}


voidapps_init(void)
{
const struct app_descriptor *app;

for (app = &__apps_start; app != &__apps_end; app++) {
if (app->init)
app->init(app);
} //调用的就是aboot_init函数

for (app = &__apps_start; app != &__apps_end; app++) {
if (app->entry && (app->flags & APP_FLAG_DONT_START_ON_BOOT) == 0) {
start_app(app);
}
}
}

前面分析我们可以看出来,LK在硬件,平台和系统初始化后,运行起第一个进程bootstrap2,而bootstrap2 再把注册在系统中的app(即进程)逐个运行起来。软件下载Development前面提到的Aboot就是被运行起来的其中一个app。在aboot中最终完成了linux kernel的加载运行动作。

aboot_init分析

void aboot_init(const struct app_descriptor *app)
{
/*设置NAND/EMMC的读取页面大小*/

if (target_is_emmc_boot())
{

page_size = 2048;

page_mask = page_size - 1;
}
else
{

page_size = flash_page_size();

page_mask = page_size - 1;
}
/*内核相关*/
if(target_use_signed_kernel())
{
read_device_info(&device);
}

/* 通过按键状态,判断是否正常开机,还是进入fastboot,还是recovery*/
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;
}

if (fastboot_trigger())
goto fastboot;
reboot_mode = check_reboot_mode();//恢复出厂设置,重启则走这个。
if (reboot_mode == RECOVERY_MODE) {
boot_into_recovery = 1; //进recovery
} else if(reboot_mode == FASTBOOT_MODE) {
goto fastboot;
}

。。。。。
recovery_init();
boot_linux_from_flash();//一般从nand中加载linux kernel

fastboot: // 我们平时烧写进fastboot ,就走这个。

target_fastboot_init();

if(!usb_init)
udc_init(&surf_udc_device);

fastboot_register("boot", cmd_boot);

udc_start(); //开启usb协议
}


这是Qualcomm(高通)平台android 启动过程到这里 LK 的内容就大致结束了,至于Kernel的启动和初始化,这里就不讨论了。而LK前面的过程(ARM9 过程) 后面会补上。


更多相关文章

  1. Android——Framework目录分析及系统启动过程以及目录简介
  2. android:process的最大的坑
  3. Android(安卓)SystemUI 闪烁
  4. android 软件盘相关
  5. Android(安卓)Studio相关配置Mac版
  6. android自定义view--绘制顺序及相关原理
  7. Android(安卓)音视频流媒体相关知识导航
  8. Android之Activity相关
  9. (转摘)Android腾讯微博客户端开发二:相关工具篇

随机推荐

  1. 仿作京东网页
  2. 【第767期】你不懂JS:混合(淆)“类”的对象
  3. 2021必修 CSS架构系统精讲
  4. PHP常用数组函数
  5. 0630作业
  6. 【第769期】2016 JavaScript 发展现状大
  7. Python经典面试题之前端和框架!Python学习
  8. HTML常用标签
  9. 【案例】星环科技原厂数据备份恢复软件,让
  10. 【案例】星环智能分析工具 Sophon,助力上