Android 开发之 ---- bootloader (LK)

本文深入解析了LittleKernel(LK)的启动流程,包括其代码结构、初始化过程、平台及目标初始化,以及应用程序的启动。详细介绍了kmain函数的执行流程,arch_early_init和platform_early_init函数的作用,以及bootstrap2函数如何引导LK应用程序运行,最终加载Android Linux内核。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

  
--------------------- 
作者:jmq_0000 
来源:优快云 
原文:https://blog.youkuaiyun.com/jmq_0000/article/details/7378348 
版权声明:本文为博主原创文章,转载请附上博文链接!

<think>好的,用户问的是LK和U-Boot,我需要先分别了解这两个概念,然后组织答案。 首先,LK是Little Kernel的缩写,我之前记得它是一个轻量级的开源引导程序,主要用于嵌入式系统和移动设备。需要确认它的主要功能和适用场景。可能涉及启动流程、支持平台等。另外,它和Android的关系,比如作为早期Android设备的Bootloader,这点可能需要提到。 然后是U-Boot,全称Das U-Boot,这是一个广泛使用的开源Bootloader,常见于嵌入式系统,尤其是基于ARM、PowerPC、MIPS等架构的设备。需要说明它的功能,比如初始化硬件、加载操作系统,支持网络启动、文件系统等高级功能。应用场景如路由器、物联网设备,以及开发板如Raspberry Pi的部分版本。 接下来,要比较两者的区别。LK更轻量,适合资源有限的环境,比如手机;而U-Boot功能更全面,支持的硬件更多,适合复杂的嵌入式设备。可能还要提到历史背景,比如LKAndroid中的使用,而U-Boot在更多领域应用。 用户可能需要了解两者的使用场景和选择依据,因此需要明确它们的优缺点。例如,LK启动速度快,占用资源少,但功能相对简单;U-Boot功能丰富但更庞大。 需要检查是否有错误信息,比如LK是否真的是Android早期使用的,以及U-Boot支持的具体架构。另外,确保术语准确,比如Bootloader的作用,启动流程的阶段划分。 最后,结构要清晰,分点介绍LK和U-Boot,再比较它们的区别,帮助用户逐步理解。注意使用中文,避免专业术语过于晦涩,必要时举例说明。</think>以下是关于LK和U-Boot的详细介绍及对比分析: --- ### 一、LK(Little Kernel) #### 1. 基本定义 LK(Little Kernel)是一个轻量级开源**引导加载程序(Bootloader)**,专为嵌入式系统和移动设备设计。它最初由Android团队开发,用于早期Android设备的启动流程。 #### 2. 核心功能 - **硬件初始化**:初始化CPU、内存、时钟等关键硬件。 - **多阶段启动**:支持从低功耗模式唤醒设备,并加载后续引导阶段。 - **快速启动**:代码精简,占用资源少,适合对启动时间敏感的场景。 - **模块化设计**:可通过插件扩展功能(如文件系统、网络支持)。 #### 3. 应用场景 - 早期Android手机的Bootloader(如Nexus系列)。 - 嵌入式设备(如IoT设备)的快速启动解决方案。 --- ### 二、U-Boot(Das U-Boot) #### 1. 基本定义 U-Boot(全称Universal Boot Loader)是一个开源的**通用引导加载程序**,广泛应用于嵌入式系统,支持多种处理器架构(ARM、PowerPC、MIPS等)。 #### 2. 核心功能 - **硬件初始化**:配置CPU、内存、外设控制器等。 - **操作系统加载**:从存储介质(Flash、SD卡)或网络加载内核镜像。 - **交互式命令行**:提供丰富的调试和配置命令。 - **高级功能**:支持文件系统(FAT、EXT4)、网络协议(TFTP、NFS)、脚本执行等。 #### 3. 应用场景 - 嵌入式开发板(如树莓派、BeagleBone)。 - 工业控制设备、路由器、网络交换机等。 --- ### 三、LK与U-Boot的关键区别 | 特性 | LK | U-Boot | |---------------------|-----------------------------------------|---------------------------------------| | **设计目标** | 轻量级、快速启动 | 通用性、功能丰富 | | **代码体积** | 较小(约数万行代码) | 较大(数十万行代码) | | **硬件支持** | 专注ARM架构,适配移动设备 | 支持多架构(ARM、PowerPC、RISC-V等) | | **功能复杂度** | 基础功能为主,扩展性有限 | 功能全面,支持网络、文件系统等 | | **典型应用** | 早期Android设备、低资源嵌入式系统 | 开发板、复杂嵌入式系统 | --- ### 四、选择建议 1. **LK适用场景**: - 需要快速启动且硬件资源受限的设备(如穿戴设备)。 -Bootloader的实时性要求较高。 2. **U-Boot适用场景**: - 需要灵活配置、调试或网络功能的复杂系统。 - 多架构支持需求(如跨平台开发)。 --- ### 五、技术示例 - **LK启动流程**: $$ \text{硬件复位} \rightarrow \text{初始化时钟/内存} \rightarrow \text{加载第二阶段引导程序} \rightarrow \text{启动内核} $$ - **U-Boot命令行操作**: 通过串口输入`printenv`可查看环境变量: ```bash => printenv bootcmd=tftp 0x80008000 zImage; bootm 0x80008000 ``` --- 通过以上分析,可依据具体需求选择LK或U-Boot作为嵌入式系统的引导解决方案。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值