目录
-
第一部分:基础概念
(图片来源网络,侵删)- 什么是 Recovery Ramdisk?
- 它与完整的 Recovery Image 有什么区别?
- 为什么需要制作自定义 Recovery Ramdisk?
-
第二部分:准备工作
- 硬件要求
- 软件与环境
- 知识储备
-
第三部分:制作 Recovery Ramdisk (以 AOSP 为例)
- 步骤 1: 获取 AOSP 源码
- 步骤 2: 编译 Recovery 源码
- 步骤 3: 打包 Recovery Ramdisk
- 步骤 4: 编译完整的 Recovery Image (可选,但推荐)
-
第四部分:刷入与测试
- 如何刷入 Recovery Ramdisk
- 如何在 Recovery 模式下验证 Ramdisk
-
第五部分:高级用法与技巧
(图片来源网络,侵删)- 修改
recovery.fstab挂载点 - 添加自定义脚本或二进制文件
- 制作支持
adb sideload的 Ramdisk - 调试技巧
- 修改
-
第六部分:常见问题与故障排除
mkbootfs或mkbootimg找不到- 编译失败
- 刷入后无法进入 Recovery
第一部分:基础概念
什么是 Recovery Ramdisk?
Recovery Ramdisk 是 Android 启动过程中的一个关键组件,它是一个被压缩的内存文件系统(通常为 cpio 格式),包含了使设备进入恢复模式 所需的最小化操作系统环境。
当你长按 电源键 + 音量上键(组合键因设备而异)时,设备的 Bootloader 会加载两个核心文件:
- Kernel (内核): 操作系统的核心,负责管理硬件资源。
- Ramdisk (内存盘): 一个临时的文件系统,包含了启动到特定模式(如 Recovery 或 System)所需的初始化脚本和工具。
对于 Recovery 这个 Ramdisk 就是我们所说的 Recovery Ramdisk,它内部包含了:

init可执行文件:Recovery 模式的“主进程”,负责挂载分区、启动服务等。recovery.rc和recovery.fstab:定义了 Recovery 模式的行为和需要挂载的分区。recovery-binary:执行恢复操作(如安装 OTA 包、Wipe 数据等)的核心程序。- 其他必要的工具,如
adbd(用于 ADB 调试)、busybox等。
它与完整的 Recovery Image 有什么区别?
- Recovery Ramdisk: 仅仅是恢复模式的内存盘部分,它是一个
ramdisk.cpio.gz文件。 - Recovery Image: 是一个完整的镜像文件,包含了 Kernel + Recovery Ramdisk,一个
recovery.img文件就是使用mkbootimg工具将内核和 ramdisk 打包在一起的结果。
Recovery Image = Kernel + Recovery Ramdisk,我们通常刷入设备的都是 recovery.img,但制作它的第一步就是制作出 recovery_ramdisk.cpio.gz。
为什么需要制作自定义 Recovery Ramdisk?
- 修复设备: 当设备无法开机或进入系统时,一个定制的 Recovery 可以用来修复分区表、恢复系统或重置设备。
- 添加功能: 你可以在 Recovery Ramdisk 中添加自定义脚本、工具或修改现有逻辑,
- 自动备份 NVRAM 数据。
- 添加特殊的安装选项(如只清除缓存)。
- 集成高级的诊断工具。
- 适配硬件: 为新硬件或修改了分区表的设备创建一个能正确识别所有分区的 Recovery。
- 研究与学习: 深入理解 Android 的启动流程和 Recovery 的工作原理。
第二部分:准备工作
硬件要求
- 一台可以正常运行的电脑(推荐 Linux,如 Ubuntu,因为 AOSP 编译环境在 Linux 下最稳定)。
- 你的 Android 设备(需要已解锁 Bootloader,并获取
boot.img以获取内核信息)。
软件与环境
- 操作系统: Linux (强烈推荐 Ubuntu 20.04/22.04) 或 Windows (WSL2 亦可)。
- AOSP 源码: 你需要下载对应设备或 Android 版本的 AOSP 源码。
- 编译工具链: AOSP 自带的
make和build/envsetup.sh脚本会自动处理大部分依赖。 - 工具:
git: 用于下载源码。repo: AOSP 的代码管理工具。python: 通常需要 Python 3。unzip,lz4,zstd等压缩工具。
知识储备
- 基本的 Linux 命令行操作:
cd,ls,cp,mv,mkdir,chmod等。 - 了解 Android 目录结构:知道
system,bootloader,recovery等分区的作用。 - 了解 AOSP 编译流程:知道如何使用
lunch,make等命令。
第三部分:制作 Recovery Ramdisk (以 AOSP 为例)
我们将以编译 AOSP 官方 Recovery 为例,这个过程适用于大多数基于 AOSP 的设备。
步骤 1: 获取 AOSP 源码
在你的电脑上设置好 AOSP 编译环境,打开终端,执行以下命令:
# 创建一个目录存放源码 mkdir aosp-recovery cd aosp-recovery # 初始化 repo repo init -u https://android.googlesource.com/platform/manifest -b main # 同步源码 (这步会很久,请耐心等待或使用 -j 参数加速) repo sync -j4
注意:
main分支对应最新的 Android 14,如果你需要编译其他版本,请使用对应的分支名,如android-13.0.0_r1。
步骤 2: 编译 Recovery 源码
AOSP 的 Recovery 源码位于 bootable/recovery 目录,我们需要编译它来生成二进制文件和资源。
# 加载编译环境 source build/envsetup.sh # 选择一个编译目标 (这里以 aosp_cf_x86_64-userdebug 为例,是一个模拟器目标) # 对于真机,你需要使用你设备的 lunch combo,astra-userdebug lunch aosp_cf_x86_64-userdebug # 开始编译 Recovery # 这会编译 recovery 模块,生成 recovery 可执行文件和相关资源 make -j$(nproc) recoveryimage
说明:
lunch命令用于配置编译目标。userdebug是一个适合开发和调试的版本。make recoveryimage会编译整个 Recovery Image,如果你只想编译 recovery 二进制本身,可以用make recovery,但前者更完整。-j$(nproc)会使用你电脑的所有 CPU核心来加速编译。
编译成功后,你会在 out/target/product/<设备名>/ 目录下找到生成的文件。
步骤 3: 打包 Recovery Ramdisk
我们从编译好的 Recovery Image 中提取出 Ramdisk,AOSP 已经提供了工具。
# 进入输出目录 cd out/target/product/aosp_cf_x86_64/ # 使用 AOSP 自带的工具解包 recovery.img # 这个脚本会解包出 kernel, ramdisk 等 ./../../../../../system/core/mkbootimg/unpack_bootimg.py --input recovery.img
执行后,你会得到一个 recovery.img-ramdisk 目录,里面就是解压出来的 Ramdisk 内容。
如果你想修改 Ramdisk 内容,现在就是最佳时机:
-
解压 Ramdisk:
# 进入 ramdisk 目录 cd recovery.img-ramdisk # 解压 cpio 文件 cpio -i -d < ramdisk.cpio
ramdisk目录下就是 Recovery Ramdisk 的所有文件和文件夹了。 -
进行修改:
- 修改
recovery.fstab以适配你的分区。 - 在
sbin目录下放入你自己的二进制文件。 - 在
etc或init.rc中添加启动脚本。 - 修改
default.prop更改默认属性。
- 修改
-
重新打包 Ramdisk:
# 回到 ramdisk 目录 cd ramdisk # 重新打包成 cpio find . | cpio -o -H newc -O ../ramdisk_new.cpio # 回到上一级目录 cd .. # 重新压缩成 gz gzip -f ramdisk_new.cpio
你就有了一个新的、修改过的 Ramdisk 文件:
ramdisk_new.cpio.gz。
步骤 4: 编译完整的 Recovery Image (可选,但推荐)
如果你修改了 Ramdisk,你需要用新的 Ramdisk 和原来的内核重新打包成一个完整的 recovery.img 才能刷入。
你需要从原始的 boot.img 或 recovery.img 中获取内核信息,可以使用 unpack_bootimg.py 来获取。
假设你已经知道了内核信息:
kernel: 内核文件路径ramdisk: 新的 Ramdisk 路径 (ramdisk_new.cpio.gz)base: 通常为0x10000000cmdline: 内核启动参数pagesize: 分页大小 (2048)ramdisk_offset: ramdisk 在镜像中的偏移量tags_offset: tags 在镜像中的偏移量
使用 mkbootimg 工具打包:
# 确保你在 out/target/product/<设备名>/ 目录下
# 使用你自己的参数替换下面的占位符
mkbootimg \
--kernel <path_to_kernel> \
--ramdisk ramdisk_new.cpio.gz \
--base <base_address> \
--cmdline "<kernel_command_line>" \
--pagesize <page_size> \
--ramdisk_offset <ramdisk_offset> \
--tags_offset <tags_offset> \
--output recovery_custom.img
提示:
mkbootimg工具通常在out/host/linux-x86/bin/目录下,你可以把它加入PATH或者使用绝对路径。
第四部分:刷入与测试
如何刷入 Recovery Ramdisk
你刷入的应该是我们刚刚生成的 recovery_custom.img (或者 recovery.img 如果你没有修改)。
- 将
recovery_custom.img传输到设备:可以通过adb push或存入 SD 卡。 - 重启到 Bootloader 模式:
adb reboot bootloader
- 使用 fastboot 刷入:
fastboot flash recovery recovery_custom.img fastboot reboot recovery
fastboot flash recovery: 将镜像刷入recovery分区。fastboot reboot recovery: 重启并进入 Recovery 模式。
如何在 Recovery 模式下验证 Ramdisk
进入 Recovery 后,你可以进行以下验证:
- 检查挂载点: 进入
Advanced->Partition Menu,看看是否能正确识别和挂载/system,/data,/cache等分区。 - 检查 ADB: 如果你的 Ramdisk 包含了
adbd,在 Recovery 界面应该可以通过adb devices看到设备,并使用adb sideload功能。 - 运行自定义脚本: 如果你添加了自定义脚本,检查它是否按预期执行。
第五部分:高级用法与技巧
修改 recovery.fstab
这是最常见的需求。recovery.fstab 定义了 Recovery 模式下需要挂载的分区。
- 表示该分区是可移动的(如 SD 卡)。
/system是系统分区。/data是用户数据分区。/cache是缓存分区。mnt是一个通用挂载点。
修改后,确保你的设备分区名称和路径与 fstab 中定义的一致。
添加自定义脚本或二进制文件
- 脚本: 将你的 Shell 脚本(
post-install.sh)放入ramdisk/etc目录,并确保它有执行权限 (chmod +x),然后在init.rc中通过exec或service调用它。 - 二进制文件: 将编译好的二进制文件(如
magisk,twrp的工具)放入ramdisk/sbin目录,并同样赋予执行权限。
制作支持 adb sideload 的 Ramdisk
adb sideload 是一个非常有用的功能,允许你通过 ADB 直接从电脑推送和安装 ZIP 包。
- 确保你的 Ramdisk 中包含
adbd(通常包含)。 - 在
init.rc中,需要有一个service来启动adbd,并且设置seclabel为u:r:adbd:s0(根据 SELinux 策略可能不同)。 - 在 Recovery 的主界面(通常是文本界面),按菜单键(或物理按键)应该能看到 "Apply update from ADB" 的选项。
调试技巧
- 开启详细日志: 在
default.prop中添加ro.secure=0和ro.debuggable=1可以开启更多调试信息。 - 使用
logcat: 在 Recovery 模式下连接 ADB,运行adb logcat -b main -b system -b crash可以查看 Recovery 的详细日志输出,对排查问题非常有帮助。 - Ramdisk 模拟: 你可以在电脑上使用
chroot进入之前解压出来的ramdisk目录,模拟运行环境来测试你的脚本和修改。
第六部分:常见问题与故障排除
mkbootfs 或 mkbootimg 找不到
这些工具是 AOSP 编译过程的一部分,确保你已经成功执行了 source build/envsetup.sh 和 lunch 命令,并且当前在 AOSP 源码的根目录下编译,如果还是找不到,检查 out/host/linux-x86/bin/ 目录是否存在。
编译失败
- 检查依赖: 确保你的系统安装了所有必要的编译库和工具。
- 清理环境: 有时候编译缓存会导致问题,尝试执行
make clobber清理out目录后重新编译。 - 查看错误信息: 编译器输出的最后几行通常包含最关键的错误信息,仔细阅读并搜索网络解决方案。
刷入后无法进入 Recovery
- 分区表错误: 你刷入的 Recovery 可能与你设备的 Bootloader 不兼容,或者分区表被修改过,尝试从官方或社区提供的 Recovery 开始修改。
- 内核不匹配: 确保你打包时使用的内核是从设备正确的
boot.img或recovery.img中提取的。 - Ramdisk 损坏: 重新打包 Ramdisk 时可能出错,尝试用原始的 Ramdisk 打包,看是否能正常进入,如果能,问题就出在你修改的内容上。
最后提醒: 修改 Recovery Ramdisk 是一项高风险操作,操作不当可能导致设备变砖(无法启动)。请务必在操作前备份好所有重要数据,并确保你清楚每一步操作的含义。 对于普通用户,直接使用成熟的第三方 Recovery(如 TWRP)通常是更安全、更方便的选择,本教程主要面向开发者和希望深入理解 Android 底层原理的用户。
