2. Android 启动流程概览
理解 Android 设备的启动链路,是进行 GKI 设备树与启动适配的前提。Android 设备的启动并不是“一按电源键就进系统”,而是由多个阶段逐级接力完成的:每一级都负责初始化一部分硬件、校验下一级镜像、传递启动参数,最终把控制权交给 Linux 内核,再由内核启动 Android 用户空间。整条链路可以概括为 BootROM → Preloader → LK → Kernel → Android 用户空间,其中前三级通常运行在 SoC 内部的 SRAM 或片上存储中,后两级才真正进入外部 DDR 与文件系统。
下面这张图展示了各阶段的执行位置、关键动作与交接关系,是本节的核心结构图:
一、核心原理:为什么启动要分这么多级
SoC 上电后,CPU 只能访问一小块片内 SRAM,外部 DDR 尚未初始化,因此不可能直接运行体积庞大的 Linux 内核。启动分级本质上是一个“由小到大、由固化到可变”的引导过程:BootROM 是芯片出厂即固化的最小可信根,它只做最少的事——校验并加载 Preloader;Preloader 负责把 DDR 训练起来,让系统拥有大容量内存;LK(Little Kernel,很多平台也用 U-Boot)则具备显示、Fastboot、分区管理等较完整能力,负责选择启动槽位并加载内核镜像;内核接管后完成驱动初始化与根文件系统挂载;最后由 Android 的 init 拉起用户空间服务。
每一级都遵循“校验下一级、加载下一级、跳转下一级”的模式,这也是 Android Verified Boot(AVB)信任链的基础。任何一级校验失败,启动就会中断或回退到备用槽位。
二、方法流程:各阶段的关键动作
- BootROM:上电复位后从固定地址执行,读取启动引脚或 eFuse 决定从 eMMC/UFS/SD 启动,验证 Preloader 签名后跳转。
- Preloader:初始化 DDR、时钟、PMIC、串口,从分区表读取 LK 镜像并搬入 DRAM,然后跳转。
- LK / U-Boot:初始化显示与 USB,进入 Fastboot 或正常启动;读取 misc 分区决定 slot,加载 boot.img、vendor_boot.img、dtbo。
- Kernel:自解压后解析 DTB,匹配 compatible 字符串,probe 各驱动,挂载 system、vendor、product 等分区。
- Android 用户空间:init 读取 init.rc,启动 servicemanager、Zygote、SystemServer,最终显示 Launcher。
在调试时,串口日志是观察这条链路最直接的手段,典型日志片段如下:
[BOOTROM] jump to preloader
[Preloader] DRAM init done, load lk @ 0x4A000000
[LK] boot mode: normal, slot: _a
[LK] loading boot.img ... OK
[Kernel] Booting Linux on physical CPU 0x0
[Kernel] Machine model: MyVendor MyBoard
[Kernel] OF: fdt: dtb overlay applied
[init] init first stage started
[init] starting service 'zygote'
三、案例场景:一次典型的启动适配排查
假设某 GKI 设备在替换内核后卡在开机 Logo,串口停在 [LK] loading boot.img ... OK 之后没有任何内核输出。这说明 LK 已成功加载镜像,但内核没有跑起来。常见原因有三类:一是 boot.img 的 header 版本与 LK 预期不符;二是 DTB 未正确附加或 dtbo 未叠加,导致内核在早期无法识别内存与串口;三是内核与 vendor 模块版本不匹配,导致 init 阶段挂载失败。排查顺序应遵循“先看串口、再看分区、最后看配置”的原则。
四、误区与复盘
很多初学者会把“内核启动”和“Android 启动”混为一谈,认为看到内核 Logo 就算启动成功。实际上,内核只是提供了硬件与文件系统基础,Android 用户空间的 init、Zygote、SystemServer 才是应用可见的部分。另一个常见误区是忽略 dtbo 与 vendor_boot 的作用,在 GKI 架构下,设备树往往不再全部塞进 boot.img,而是拆分到 vendor_boot 与 dtbo 分区,适配时必须同时关注。
| 阶段 | 运行位置 | 关键产物 | 失败典型现象 |
|---|---|---|---|
| BootROM | SoC 片内 ROM | Preloader 镜像 | 无串口输出,进入 EDL |
| Preloader | 片内 SRAM | DDR 初始化参数 | 串口停在 DRAM init |
| LK / U-Boot | DRAM | boot.img、dtbo | 卡在 Logo,Fastboot 可用 |
| Kernel | DRAM | DTB、驱动模块 | 内核 panic 或无法挂载根分区 |
| Android 用户空间 | DRAM + 存储 | init.rc、系统服务 | 反复重启,停在开机动画 |