zoukankan      html  css  js  c++  java
  • Android 开发之 ---- bootloader (LK)

    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));

             }

       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));


    平台相关初始化不同平台不同的初始化下面是msm7x30

            1.初始化中断

            platform_init_interrupts();

            2.初始化定时器

            platform_init_timer();


           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 模式

           。。。。。。。。。

                 。。。。。。。。。

          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的启动过程就结束了。

  • 相关阅读:
    kettle7.0数据库迁移(MySQL迁移到Postgresql,迁移过程中自动创建表结构)
    正向代理与反向代理区别
    MySQL存储引擎相关知识点
    设计模式-装饰器模式
    设计模式-策略模式
    算法—数据结构学习笔记(二)栈
    Spring Boot2.0学习笔记(一)
    关联容器——map
    迭代器
    C风格字符串
  • 原文地址:https://www.cnblogs.com/wanghuaijun/p/7747011.html
Copyright © 2011-2022 走看看