Android开发 -- Bootloader

摘要:
thread_ init_ early();2.执行一些工作,例如关闭缓存以启用mmu手臂。arch_ early_ init();3.相关平台的早期初始化平台_ Early_init();4.现在跳转到一个函数并初始化UARTtarget_eearly_init();5.与constructor_constructor()相关的初始化调用;6.lk系统相关堆栈初始化heap_init();7.短初始化计时器对象thread_init();8.lk系统控制器初始化dpc_init();9.初始化lk_init()中的计时器;10.为boot(key)thread_resume创建线程入口函数bootstrap2;}上述与启动初始化相关的函数是arch_eearly_init、platform_eearlyInit和bootstrap2,它们是启动的关键点。让我们慢慢来看看。

本文转载自:http://blog.csdn.net/jmq_0000/article/details/7378348

LK是什么

           LK 是 Little Kernel 它是 appsbl (Applications ARM Boot Loader)流程代码  ,little kernel 是小内核小操作系统

           LK 代码 在 bootable/bootloadler/lk 目录下

           LK 代码结构

           +app            // 应用相关

           +arch           // arm 体系 

           +dev            // 设备相关

           +include      // 头文件

           +kernel        // lk系统相关   

           +platform    // 相关驱动

           +projiect     // makefile文件

           +scripts      // Jtag 脚本

           +target        // 具体板子相关

LK 流程分析

          在 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 中

kmain()

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

            kmain 源码分析:

             void kmain()

          {

           1.初始化进程(lk 中的简单进程)相关结构体。

             thread_init_early();

           2.做一些如 关闭 cache,使能 mmu 的 arm 相关工作。

            arch_early_init();

           3.相关平台的早期初始化

            platform_early_init();

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

            target_early_init();

           5.构造函数相关初始化

            call_constructors();

           6.lk系统相关的堆栈初始化

            heap_init();

           7.简短的初始化定时器对象

            thread_init();

           8.lk系统控制器初始化(相关事件初始化)

            dpc_init();

           9.初始化lk中的定时器

            timer_init();
           
10.新建线程入口函数 bootstrap2 用于boot 工作(重点)
           thread_resume(thread_create("bootstrap2", &bootstrap2, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));

         }

   以上与 boot 启动初始化相关函数是 arch_early_init、  platform_early_init 、bootstrap2,这些是启动的重点,我们下面慢慢来看。

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("mrc    p15, 0, %0, c9, c12, 0" : "=r" (en));

        en &= ~(1<<3); /*循环计算每个周期*/

        en |= 1; 

        __asm__ volatile("mcr    p15, 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 

         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 中完成的 。

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 头、kernel、ramdisk、second 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_linux 中entry(0,machtype,tags);从kernel加载在内核中的地址开始运行了。

      

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

免责声明:文章转载自《Android开发 -- Bootloader》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Markdown常用语法(二)Sqoop使用教程下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

SpringBoot启动报错:Failed to introspect Class [org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration] from ClassLoader [sun.misc.Launcher$AppClassLoader@4e0e2f2a]

SpringBoot启动服务器失败,详细的报错日志如下:   java.lang.IllegalStateException: Failed to introspect Class [org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration] from C...

快速编译system.img和boot.img的方法

快速编译system.img,可以使用这个命令: #make systemimage  快速编译boot.img,可以使用以下命令: #make bootimage  快速编译userdata.img,可以使用以下命令: # make userdataimage-nodeps 但是,对于bootimage, 在不改变内存布局的情况下,可以使用以下命令: #...

粒子群算法(1)----粒子群算法简单介绍

   一、粒子群算法的历史    粒子群算法源于复杂适应系统(Complex Adaptive System,CAS)。CAS理论于1994年正式提出,CAS中的成员称为主体。比方研究鸟群系统,每一个鸟在这个系统中就称为主体。主体有适应性,它能够与环境及其它的主体进行交流,而且依据交流的过程“学习”或“积累经验”改变自身结构与行为。整个系统的演变或进化包...

windows和ubuntu 10.4双启动顺序

改动/boot/grub/grub.cfg文件 /boot/grub/grub.cfg文件,这与旧版本号不同(9.10之前版本号/boot/grub/menu.lst),并且为了安全起见,该文件默觉得“仅仅读”属性,因此在改动启动菜单之前你必须先将其文件属性改为“可读写”后方可改动文件内容。 sudo chmod 666 /boot/grub/gru...

centos7下面安装zabbix

先声明一点,在容器里面创建会有文件缺失,就是创建数据库的sql文件没有了,不知道为啥,反复多次都是这样,在虚拟机上面做就不会。 一、环境准备工作。zabbix的安装需要LAMP环境1、关闭SELinux首先查看SELinux状态:方法一:输入命令 /usr/sbin/sestatus -v 结果如下方法二:直接输入命令 getenforce1)、临时关闭(...

STM32学习笔记——USART串口(向原子哥和火哥学习)

一、USART简介 通用同步异步收发器(USART)提供了一种灵活的方法与使用工业标准NRZ异步串行数据格式的外部设备之间进行全双工数据交换。USART利用分数波特率发生器提供宽范围的波特率选择。 STM32 的串口资源相当丰富的,功能也相当强劲。STM32F103ZET6 最多可提供 5 路串口,有分数波特率发生器,支持同步单向通信和半双工单线通信,支持...