【转】Android 开发之----bootloader (LK)

·    LK是什么?

LK Little Kernel小内核小操作系统)的简写,在Android系统中也称为 APPSBL Applications Processor Boot Loader),相当于PC操作系统中的Bootloader,其主要作用是对硬件进行初始化,从eMMC(一种Flash存储器)中读取Linux内核,并将其加载到RAM中去;同时,为了Linux kernel的加载和跳转,LK还需要初始化寄存器和命令参数。LK代码 bootable/bootloadler/lk目录下

LK 代码结构:

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

·     LK流程分析

bootable/bootloadler/lk/arch/arm/ssystem-onesegment.ld连接文件中 ENTRY_start)指定 LK_start 函数开始,_start lk/arch/crt0.Scrt0.S主要做一些基本的 CPU的初始化再通过调用kmain;跳转到 C代码中。kmain lk/kernel/main.c中。

1.  kmain()

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

 void kmain()
{  
   thread_init_early();   //
初始化进程(LK中的简单进程)相关结构体。

 arch_early_init();    //做一些如关闭 cache,使能 mmu arm 相关工作。
platform_early_init();  //
相关平台的早期初始化

target_early_init();   //现在就一个函数跳转,初始化UART(板子相关)

call_constructors(); //.构造函数相关初始化

 heap_init(); // LK系统相关的堆栈初始化

thread_init();  //简短的初始化定时器对象

dpc_init(); // LK系统控制器初始化(相关事件初始化)

timer_init(); //初始化LK中的定时器
thread_resume(thread_create("bootstrap2",&bootstrap2, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE)); 
//新建线程入口函数bootstrap2用于boot工作(重点)

}
以上与 boot启动初始化相关函数是arch_early_init platform_early_initbootstrap2,这些是启动的重点,我们下面慢慢来看。下图1kmain()的函数调用关系图。

                         

                                                           Fig.1 the function call of kmain()

Ø  arch_early_init() ---体系架构相关的初始化我们一般用的 ARM体系
(1).关闭cache
arch_disable_cache(UCACHE);
(2).设置向量基地址(中断相关)
set_vector_base(MEMBASE);
(3).初始化MMU
arm_mmu_init();
(4).初始化MMU映射__平台相关
platform_init_mmu_mappings();

(5).开启cache
arch_enable_cache(UCACHE)
(6).使能 cp10 cp11
__asm__ volatile("mrc p15, 0, %0, c1, c0, 2" :"=r" (val)); val |= (3<<22)|(3<<20);
__asm__ volatile("mcr p15, 0, %0, c1, c0, 2" ::"r" (val));
(7).设置使能 fpexc(中断相关)
__asm__ volatile("mrc p10, 7, %0, c8, c0, 0" :"=r" (val));
val |= (1<<30);
__asm__ volatile("mcr p10, 7, %0, c8, c0, 0" ::"r" (val));

(8).
使能循环计数寄存器

_asm_volatile("mrcp15, 0, %0, c9, c12, 0" : "=r" (en)); en &=~(1<<3);  /*循环计算每个周期*/
 _asm__volatile("mcrp15, 0, %0, c9, c12, 0" :: "r" (en));

(9).使能循环计数器 en = (1<<31);
__asm__ volatile("mcr p15, 0, %0, c9, c12, 1":: "r" (en));

Ø  platform_early_init()----平台相关初始化不同平台不同的初始化下面是msm7x30
(1).
初始化中断
platform_init_interrupts();

(2).初始化定时器
platform_init_timer();

 

Ø bootstrap2
bootstrap2kmain的末尾以线程方式开启。主要分三步:platform_inittarget_initapps_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中完成的

 

Ø aboot_init
1.设置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;

     }
2.读取按键信息,判断是正常开机,还是进入 fastboot ,还是进入recovery模式
通过一系列的 if (keys_get_state()== XXX)判断

    3. nand中加载内核 boot_linux_from_flash();
  
  partition_dump(); sz =target_get_max_flash_size();  

     fastboot_init(target_get_scratch_address(),sz);              

     udc_start(); // 开始 USB 协议

Ø  boot_linux_from_flash

主要是内核的加载过程,我们的 boot.img包含:kernel头、kernelramdisksecond stage(可以没有)。

1.读取boot头部
flash_read(p, offset,raw_header, 2048)
offset += 2048;

2.读取内核
memcmp(hdr->magic,BOOT_MAGIC, BOOT_MAGIC_SIZE)
n = (hdr->kernel_size +(FLASH_PAGE_SIZE - 1)) & (~(FLASH_PAGE_SIZE - 1));

 flash_read(p, offset,(void*) hdr->kernel_addr, n) offset += n;
3.读取 ramdisk
n = (hdr->ramdisk_size +(FLASH_PAGE_SIZE - 1)) & (~(FLASH_PAGE_SIZE - 1));

flash_read(p, offset,(void*) hdr->ramdisk_addr, n) offset += n;

4.启动内核
boot_linux()//boot_linuxentry(0,machtype,tags);kernel加载在内核中的地址开始运行了。

到这里LK的启动过程就结束了。 

 

由于时间的关系,这里只简单的贴出别人的文章,希望随着学习的深入可以对其进行完善。
【文章链接】:http://blog.csdn.net/jmq_0000/article/details/7378348

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值