9、自定义Bootloader:Little Kernel简介、U-Boot在Android中的应用、编译与烧录自定义Bootloader

好,咱们进入第九章。这一章我打算聊聊自定义Bootloader。说实话,做Android底层开发这么多年,Bootloader一直是个“既熟悉又陌生”的东西。熟悉是因为每次开机它都在跑,陌生是因为大部分时候我们直接用厂商提供的就完事了。但如果你想深入理解Android启动流程,或者想给设备做深度定制,那自定义Bootloader就是绕不开的一关。

今天咱们重点聊两个东西:Little Kernel(LK)和U-Boot。嗯,这两个在Android生态里是最常见的开源Bootloader。

9.1 Little Kernel(LK)简介

Little Kernel,简称LK。名字里带个“Little”,但它干的事可不小。它是Google在Android早期阶段就开始使用的Bootloader,很多高通平台的设备默认就是它。

我个人习惯把LK看作一个“轻量级的小型操作系统”。它有自己的线程管理、内存管理、甚至还有简单的设备驱动框架。你想想看,一个Bootloader能做到这个程度,已经很不简单了。

核心特点:

  • 代码量小,结构清晰,适合嵌入式环境
  • 支持ABL(Android Bootloader)规范
  • 内置Fastboot协议支持
  • 支持多种启动设备:eMMC、UFS、SD卡等

我在项目中遇到过一个问题:某款高通平台的设备,在低温环境下偶尔无法正常启动。排查到最后,发现是LK阶段对eMMC的初始化时序不够稳健。说白了,就是Bootloader在低温下读eMMC时,时序参数没适配好。后来我们在LK的板级配置里调整了时钟延迟参数,问题就解决了。所以你看,Bootloader虽然小,但硬件相关的坑一个都不少。

LK的启动流程

LK的启动流程其实不复杂,我简单梳理一下:

  1. CPU复位:从ROM代码跳转到LK入口
  2. 早期初始化:设置栈、清零BSS段
  3. 平台初始化:时钟、GPIO、UART等
  4. 设备探测:检测eMMC、显示屏、按键等
  5. 启动模式判断:正常启动还是进入Fastboot
  6. 加载并跳转:读取boot.img并跳转到kernel

这里有个细节我想提一下:LK的启动模式判断,通常是通过检测按键组合来实现的。比如音量减+电源键进入Fastboot。我曾经调试过一个设备,按键检测的GPIO配置错了,导致怎么按都进不了Fastboot模式。嗯,这种问题排查起来其实挺费时间的。

9.2 U-Boot在Android中的应用

U-Boot,全称是Das U-Boot。它比LK更老牌,在嵌入式Linux领域几乎是标配。Android早期也有不少设备用U-Boot,现在主要在一些非高通平台(比如瑞芯微、全志、MTK部分平台)上还能看到它的身影。

U-Boot和LK最大的区别是什么?我个人觉得有两点:

  • U-Boot更“重”:功能更丰富,支持更多文件系统、网络协议、命令行工具
  • U-Boot更“开放”:它的驱动模型和配置系统非常灵活,适配新板子相对容易

我的建议:如果你是在做基于Linux的嵌入式产品(非Android),U-Boot几乎是首选。但如果是做Android手机/平板,尤其是高通平台,LK更常见。当然,现在Google也在推ABL(基于UEFI的Bootloader),那是另一个话题了。

U-Boot在Android中的典型用法

U-Boot在Android设备上,通常承担以下职责:

功能 说明
加载内核 从boot分区读取kernel并跳转
Fastboot支持 通过fastboot协议刷写分区
环境变量管理 存储启动参数、分区表等
多系统启动 支持Android + Linux双系统
OTA升级辅助 在升级失败时提供恢复机制

我记得有一次帮客户调试一个基于RK3399的Android平板,U-Boot阶段死活加载不了内核。最后发现是环境变量里的bootargs参数写错了,少了一个关键的dma参数。你想想看,就一个字符串的差异,导致整个系统起不来。所以我说,做底层开发,细节决定成败。

9.3 编译与烧录自定义Bootloader

好,到了实操环节。咱们聊聊怎么编译和烧录自定义Bootloader。这里我以LK为例,因为它的编译系统相对简单,适合入门。

编译LK

LK的编译系统基于Makefile,没有复杂的Kconfig。你只需要配置好交叉编译工具链,然后指定目标平台即可。

# 设置交叉编译工具链
export PATH=/path/to/your/toolchain/bin:$PATH
export CROSS_COMPILE=aarch64-linux-android-

# 编译LK
make -j4 PROJECT=<your_project_name>

这里的PROJECT变量指定了目标平台。LK的源码里有一个project目录,里面存放了各个平台的板级配置。比如高通某平台的配置可能是msm8998sm8250

注意:编译LK时,一定要确保你的交叉编译工具链版本与目标平台匹配。我曾经用了一个太新的GCC版本编译LK,结果链接出来的二进制在目标板上跑不起来。后来换回厂商推荐的GCC版本,问题就解决了。工具链版本这事,真的不能马虎。

烧录自定义Bootloader

编译完成后,你会得到一个lk.binbootloader.img文件。烧录方式取决于你的设备:

  • 通过Fastboot烧录: fastboot flash bootloader lk.bin
  • 通过下载工具烧录: 比如高通的QFIL、瑞芯微的RKDevTool
  • 通过JTAG/SWD烧录: 用于变砖后的救砖场景

我个人最常用的是Fastboot方式。前提是你的设备当前还能正常进入Fastboot模式。如果Bootloader已经刷坏了,那就只能上JTAG或者拆机用SPI Flash编程器了。

避坑指南:我曾经在调试阶段频繁刷写Bootloader,结果有一次不小心把分区表也擦掉了。设备直接变砖,只能拆机用编程器恢复。从那以后,我每次刷Bootloader之前都会先备份原始分区表。嗯,这个习惯救过我很多次。

9.4 知识体系结构图

下面这张图是我整理的本章知识体系,方便你理解各个概念之间的关系:

自定义Bootloader知识体系 自定义Bootloader Little Kernel (LK) • 轻量级,高通平台常用 • 内置Fastboot协议 • 启动流程:复位→初始化→加载 U-Boot • 功能丰富,嵌入式Linux标配 • 支持多文件系统/网络协议 • 环境变量管理灵活 编译与烧录 • 编译:make PROJECT=xxx • 烧录:fastboot / 下载工具 / JTAG • 注意:工具链版本、分区表备份

这张图把本章的三个核心内容串起来了。左边是LK,右边是U-Boot,下面是编译烧录的实操要点。你可以把它当作一个快速索引,复习的时候瞄一眼就能想起来。

9.5 小结

这一章我们聊了LK和U-Boot这两个主流的开源Bootloader。LK轻量、简洁,适合高通平台;U-Boot功能丰富,适合非高通平台和嵌入式Linux场景。编译和烧录方面,我分享了一些实际项目中的经验和教训,希望能帮你少走弯路。

自定义Bootloader这件事,说难不难,说简单也不简单。关键是要理解它的启动流程、熟悉编译工具链、以及掌握烧录和救砖的方法。嗯,这些都需要在实际项目中慢慢积累。

一句话总结:Bootloader是Android启动的第一道关卡,自定义它需要你对硬件、编译系统和启动流程都有足够的理解。别怕踩坑,每个坑都是成长的机会。


公众号:蓝海资料掘金营,微信deep3321