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模式通信接口:

  1. 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的信息
  1. 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启动流程

  1. recovery bin 启动流程
    bootloader检测到recovery模式后会加载recovery.img启动,recovery.img类似于boot.img,包含标准kernel和recovery特有的根文件系统。init进程解析执行bootable/recovery/etc/init.rc。init.rc启动recovery服务。

  2. 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

  1. 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
  1. 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

  1. 组合键
    VolumeUp + Power进入Recovery
    VolumeDown + Power组合键,进入BootMenu菜单(fastboot mode),选择进入Recovery

  2. 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

posted @ 2020-12-05 17:05  bobfly1984  阅读(1143)  评论(0编辑  收藏  举报