第3章:分区布局与镜像详解
好,咱们今天聊聊分区布局。说实话,这是OTA升级里最基础也最容易踩坑的地方。我记得刚接触AOSP那会儿,看着一堆分区名就头大——boot、system、vendor、super……每个都长得差不多,但作用天差地别。
你想想看,如果连分区都搞不清楚,后面做差分升级、AB切换肯定要翻车。所以这一章,我带你把这些分区和镜像彻底吃透。
3.1 Boot分区:系统的启动引擎
Boot分区,说白了就是手机开机时第一个加载的东西。它里面装着Linux内核和ramdisk。没有它,系统根本跑不起来。
Boot镜像的结构:
+------------------+
| Boot Header | // 头部信息,包含内核大小、ramdisk地址等
+------------------+
| Kernel | // zImage或Image.gz
+------------------+
| Ramdisk | // 根文件系统,包含init.rc等
+------------------+
| Second Stage | // 可选,某些平台用
+------------------+
| DT (Device Tree)| // 设备树,描述硬件信息
+------------------+
我在项目中遇到过一个问题:某款设备刷了第三方ROM后死活开不了机。查了半天,发现是boot分区里的设备树和硬件不匹配。嗯,这种坑你遇到了就知道有多头疼。
关键点:Boot分区的大小通常由厂商定义,一般在32MB到64MB之间。如果你自己编译内核,记得别超了。
3.2 System分区:系统的核心
System分区装着Android框架、系统应用、库文件等。说白了,它就是Android系统的本体。
不过从Android 10开始,Google强推了动态分区(Dynamic Partition),System分区被合并到了Super分区里。但老设备上,它还是独立存在的。
System镜像的生成:
# 编译后生成system.img
make systemimage
# 或者直接生成稀疏格式
make systemimage-sparse
我个人习惯在编译前先检查一下分区大小:
# 查看当前system分区大小
du -sh out/target/product/你的设备/system
# 如果超了,调整BoardConfig.mk中的BOARD_SYSTEMIMAGE_PARTITION_SIZE
注意:System分区不能随便改大。它的大小在分区表里是固定的,改大了会挤占其他分区的空间。我曾经因为没注意这个,导致刷机后vendor分区装不下,折腾了两天。
3.3 Vendor分区:硬件适配的关键
Vendor分区,这是厂商最关心的分区。它装着硬件相关的驱动、HAL(硬件抽象层)、固件等。
为什么要单独分一个Vendor分区?说白了就是为了解耦。系统升级时,vendor分区可以不动,只更新system分区。这样厂商不用每次升级都重新适配驱动。
Vendor镜像的内容:
- lib64/hw/ 下的硬件HAL库(比如gralloc、hwcomposer)
- etc/ 下的配置文件(比如audio_policy.conf)
- firmware/ 下的固件文件
- bin/ 下的硬件相关可执行文件
我记得有一次移植设备,WiFi死活打不开。查log发现是vendor分区里的WiFi固件版本不对。后来把正确的固件放进去,问题就解决了。这种问题在OTA升级里特别常见,因为固件和驱动版本必须匹配。
3.4 Super分区:动态分区的核心
Super分区是Android 10引入的新概念。它把system、vendor、product等分区合并成一个大的逻辑分区。这样做的好处是:分区大小可以动态调整,不用再担心某个分区不够用。
Super分区的布局:
+------------------+
| Super Header | // 超级头部,描述逻辑分区信息
+------------------+
| System | // 逻辑分区1
+------------------+
| Vendor | // 逻辑分区2
+------------------+
| Product | // 逻辑分区3
+------------------+
| ... | // 其他逻辑分区
+------------------+
生成Super镜像的命令:
# 编译后生成super.img
make superimage
# 或者生成vendor_boot等
make vendorbootimage
小技巧:如果你在调试阶段,可以用lpdump命令查看Super分区的实际布局:
lpdump /dev/block/by-name/super
这样能清楚看到每个逻辑分区的起始位置和大小。
3.5 DTBO与VBMeta:容易被忽略的配角
这两个分区虽然小,但作用不小。我刚开始做移植时经常忽略它们,结果吃了不少亏。
DTBO(Device Tree Blob Overlay)
DTBO是用来覆盖设备树的。说白了,就是允许你在不修改内核的情况下,调整硬件配置。比如你想换一个显示屏,只需要更新DTBO分区就行。
DTBO镜像的生成:
# 编译DTBO
make dtboimage
# 查看DTBO内容
mkdtimg dump out/target/product/你的设备/dtbo.img
VBMeta(Verified Boot Metadata)
VBMeta是Android Verified Boot(AVB)的核心。它存储着各个分区的哈希值和签名信息。系统启动时,会校验这些哈希值,确保分区没有被篡改。
我遇到过一个问题:刷了第三方ROM后,手机一直提示"Your device is corrupt"。查了半天,发现是VBMeta里的哈希值和实际分区不匹配。解决办法是重新生成VBMeta镜像。
生成VBMeta的命令:
# 编译时自动生成
make vbmetaimage
# 手动生成(调试用)
avbtool make_vbmeta_image \
--include_descriptors_from_image boot.img \
--include_descriptors_from_image system.img \
--output vbmeta.img
重要提醒:在开发阶段,你可以用--disable_verity参数关闭校验,方便调试。但正式发布时一定要开启,否则设备的安全性会大打折扣。
3.6 分区布局的实战建议
好了,理论知识讲完了。我来总结一下实际移植时的经验:
- 先看分区表:拿到一个新设备,第一件事就是看它的分区表。用
cat /proc/partitions或者ls -l /dev/block/by-name/查看。 - 确认分区大小:每个分区的大小必须和BoardConfig.mk里定义的一致。否则刷机时会报错。
- 注意AB分区:如果你的设备支持AB升级,那每个分区都有两份(比如boot_a和boot_b)。OTA升级时,系统会更新非活跃的那一份。
- 备份原始镜像:在刷机前,一定要备份原始设备的镜像。万一出了问题,还能恢复。
核心总结:分区布局是OTA升级的地基。地基不稳,后面全是白搭。我建议你花时间把每个分区的作用和生成方式搞清楚,这样后面做差分升级、AB切换时才不会手忙脚乱。
下一章,我们会聊到OTA升级的完整流程。到时候你会看到,这些分区是怎么协同工作的。嗯,做好准备,后面才是真正的硬仗。