android recovery介绍
概要
recovery.img=recovery_ramdisk.img+kernel。recovery模式有自己的根文件系统,与normal根文件系统不同。相应的有自己的
init.rc以及fstab文件。
recovery模块功能:恢复出厂设置和升级。
recovery升级方式有两种如下所示,不管哪种方式都会重启进入recovery模式启动执行init.rc里的recovery服务执行安装升级。
- 离线升级即手动拷贝升级包到SD卡通过settings-->About phone-->System Update-->选择从SD卡升级。
- 在线升级即OTA (over the air)。用户通过在线下载升级包到本地。
recovery模式工作原理
recovery模式涉及三个实体:main system、recovery、bootloader。
recovery模式通信接口:
- cache分区
/cache/recovery/command文件, 此文件保存了main system传给recovery的命令行,每一行就是一条命令。
--wipe_cache //擦除cache分区
-wipe_data //擦除用户数据。擦除data分区时必须要擦除cache分区
--update_package=root:path // Main system将这条命令写入时,代表系统需要升级,在进入Recovery模式后,将该文件中的命令读取并写入BCB中,然后进行相应的更新update.zip包的操作
--send_intent=anystring //在Recovery结束时在finish_recovery函数中将定义的intent字符串作为参数传进来,并写入到/cache/recovery/intent中
/cache/recovery/log文件, //Recovery模式在工作中的log打印
/cache/recovery/intent文件,//Recovery传递给Main system的信息
- MISC分区BCB
struct bootloader_message{
char command[32];
char status[32];
char recovery[1024];
}
recovery字段格式为:
“recovery\n
<recovery command>\n
<recovery command>\n
<recovery command>”
就是一个字符串,必须以recovery\n开头,否则这个字段的所有内容域会被忽略。同时每条指令都是以“\n”结尾,每条指令各占一行。
“recovery\n”之后的部分,是/cache/recovery/command支持的命令。可以将其理解为Recovery操作过程中对命令操作的备份。
Recovery操作过程为:先读取BCB然后读取/cache/recovery/command,然后将二者重新写回BCB,这样在进入Main system之前,确保操作被执行。
在操作之后进入Main system之前,Recovery又会清空BCB的command域和recovery域,这样确保重启后不再进入Recovery模式。
recovery启动流程
-
recovery bin 启动流程
bootloader检测到recovery模式后会加载recovery.img启动,recovery.img类似于boot.img,包含标准kernel和recovery特有的根文件系统。init进程解析执行bootable/recovery/etc/init.rc。init.rc启动recovery服务。 -
recovery main流程
-
加载recovery.fstab分区表
-
获取recovery 命令:get_args()
获取命令位置的优先级是:命令行参数、misc分区、cache/recovery/command。
如果从命令行获取到命令,就不会再解析misc和cache命令,如果从misc分区获取到命令,就不会再解析cache/recovery/command文件。
最后把命令又更新到misc分区 BCB块的recovery字段,把boot-recovery字符串写到BCB块的command字段。系统重启又进入到recovery。 -
recovery界面设置
-
执行命令
-
如果没有命令,等待用户输入
-
finish_recovery
-
recovery debug
- recovery模式使用adb
bootable/recovery/etc/init.rc
on property:ro.debuggable=1
write /sys/class/android_usb/android0/enable 1
start adbd
userdebug或eng版本,启动adbd。
adb shell命令需要mount system。
其它adb命令可以使用:
adb devices
adb root
adb push/pull
- recovery模式下log 打印
有两种方式打印log:printf 和 ui->print
ui->print:t调用screen_ui的print函数,将信息显示在屏幕上
printf输出到stdout,stdout重定向到下面文件:
freopen(TEMPORARY_LOG_FILE, "a", stdout); setbuf(stdout, NULL);
freopen(TEMPORARY_LOG_FILE, "a", stderr); setbuf(stderr, NULL);
static const char *TEMPORARY_LOG_FILE = "/tmp/recovery.log";
recovery输出log到/tmp/recovery.log文件,finish_recovery()函数把/tmp里临时日志拷贝到cache分区:
static const char *LAST_LOG_FILE = "/cache/recovery/last_log";
static const char *LAST_INSTALL_FILE = "/cache/recovery/last_install";
copy_log_file(TEMPORARY_LOG_FILE, LOG_FILE, true);
copy_log_file(TEMPORARY_LOG_FILE, LAST_LOG_FILE, false);
copy_log_file(TEMPORARY_INSTALL_FILE, LAST_INSTALL_FILE, false);
/cache/recovery/last_log:recovery log
/cache/recovery/last_install:最后一次更新OTA升级包的日志
android系统boot mode
-
组合键
VolumeUp + Power进入Recovery
VolumeDown + Power组合键,进入BootMenu菜单(fastboot mode),选择进入Recovery -
BCB (Bootloader Control Block)
启动过程中用户没有按下任何组合键,bootloader读取MISC分区的BCB,BCB存放启动命令。
struct bootloader_message{
char command[32]; //存放不同的启动命令
char status[32]; //升级完成后存放执行结果
char recovery[1024]; //存放/cache/recovery/command
};1:command=="boot-recovery"时,系统会进入Recovery模式。Recovery服务会具体根据/cache/recovery/command中的命令执行相应的操作(例如,升级update.zip或擦除cache、data等)。
2:command为空时,即没有任何命令,系统会进入正常的启动,最后进入主系统(main system)
参考文档
https://www.cnblogs.com/xiaolei-kaiyuan/p/5456227.html
https://blog.csdn.net/ShuttleCheng/article/details/79186756