Android 系统开发之-----bootloader (lk) 分析
2017-02-04 13:38
369 查看
什么是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)
源码片段:
void
acpu_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); //升频
}
void
target_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两个分区表整合起来
}
void
apps_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 过程) 后面会补上。
转自:http://blog.csdn.net/goldfighter/article/details/7651887
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)
源码片段:
void
acpu_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); //升频
}
void
target_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两个分区表整合起来
}
void
apps_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 过程) 后面会补上。
转自:http://blog.csdn.net/goldfighter/article/details/7651887
相关文章推荐
- Android 系统开发之-----bootloader (lk) 分析
- Android 系统开发之-----bootloader (lk) 分析
- Android 系统开发之-----bootloader (lk) 分析
- Android 系统开发之-----bootloader (lk) 分析
- Android 系统开发之-----bootloader (lk) 分析
- Android 系统开发之-----bootloader (lk) 分析
- Android 开发之 ---- bootloader (LK)
- Android平台开发 -Android build system-编译系统分析
- Android底层开发之旅—蓝牙系统分析
- Android 开发之 ---- bootloader (LK)
- 深入浅出 - Android系统移植与平台开发(十三) - Sensor HAL框架分析之三
- Android底层开发之旅—蓝牙系统分析
- 深入浅出 - Android系统移植与平台开发(八)- HAL Stub框架分析
- Android bootloader—LK的分析之如何解析boot.img
- Android底层开发之旅—蓝牙系统分析
- 深入浅出 - Android系统移植与平台开发(十一) - Sensor HAL框架分析之一
- Android 开发之 ---- bootloader (LK)
- android系统开发(四)-触摸屏tslib移植(内核)和原理分析
- Android 开发之 ---- bootloader (LK)
- Android 开发之 ---- bootloader (LK)