Android 系统Recovery工作原理

http://www.lai18.com/content/1012274.html

一、 Recovery模式中的三个部分

Recovery的工作需要整个软件平台的配合,从通信架构上来看,主要有三个部分。
①MainSystem:即上面提到的正常启动模式(BCB中无命令),是用boot.img启动的系统,Android的正常工作模式。更新时,在这种模式中我们的上层操作就是使用OTA或者从SD卡中升级update.zip包。在重启进入Recovery模式之前,会向BCB中写入命令,以便在重启后告诉bootloader进入Recovery模式。
②Recovery:系统进入Recovery模式后会装载Recovery分区,该分区包含recovery.img(同boot.img相同,包含了标准的内核和根文件系统)。进入该模式后主要是运行Recovery服务(/sbin/recovery)来做相应的操作(重启、升级update.zip、擦除cache分区等)。
③Bootloader:除了正常的加载启动系统之外,还会通过读取MISC分区(BCB)获得来至Mainsystem和Recovery的消息。

Recovery对其操作的过程为:先读取BCB然后读取/cache/recovery/command,然后将二者重新写回BCB,这样在进入Main system之前,确保操作被执行。

先从Main System开始看,当我们在Main System使用update.zip包进行升级时,系统会重启并进入Recovery模式。在系统重启之前,我们可以看到,Main System定会向BCB中的command域写入boot-recovery(粉红色线),用来告知Bootloader重启后进入recovery模式。这一步是必须的。至于Main System是否向recovery域写入值我们在源码中不能肯定这一点。即便如此,重启进入Recovery模式后Bootloader会从/cache/recovery/command中读取值并放入到BCB的recovery域。而Main
System在重启之前肯定会向/cache/recovery/command中写入Recovery将要进行的操作命令。
至此,我们就大概知道了,在上层使用update.zip升级时,主系统是怎样告知重启后的系统进入Recovery模式的,以及在Recovery模式中完成什么样的操作。

在重启之前会向BCB中写入信息,以告知bootloader如何启动,具体操作是这样的:

       • 向command域中写入“boot-recovery”      // 此操作必做

       • 向recovery域写入“recovery\n”         // 此操作也可不做

       这些操作很可能在kernel_restart(char *cmd)中完成,因为这一部分与体系结构无关,如果要实现完整的Recovery,这部分工作是必须做的。

       Bootloader得到进入Recovery模式的指示,用recovery.img启动,进入Recovery模式,init.rc (bootable/recovery/etc/init.rc)的内容比Main system的要短的多,最重要的是把recovery程序作为服务启动:

service recovery /sbin/recovery

而recovery[1024]中则存放着升级包路径,其存储结构如下:第一行存放字符串“recovery”;第二行存放路径信息“--update=/mnt/sdcard/update.zip”等。

2.get_arg():这个函数主要做了上图中get_arg()往右往下直到parse arg/v的工作。我们对照着流程一个一个看。
①read_bootloader_message():主要工作是根据分区的文件格式类型(mtd或emmc)从MISC分区中读取BCB数据块到一个临时的变量中。
②然后开始判断Recovery服务是否有带命令行的参数(/sbin/recovery,根据现有的逻辑是没有的),若没有就从BCB中读取recovery域。如果读取失败则从/cache/recovery/command中读取然后(LOGI("Got arguments from boot message\n");)。这样这个BCB的临时变量中的recovery域就被更新了。在将这个BCB的临时变量写回真实的BCB之前,又更新的这个BCB临时变量的command域为“boot-recovery”。这样做的目的是如果在升级失败(比如升级还未结束就断电了)时,系统在重启之后还会进入Recovery模式,直到升级完成。
③在这个BCB临时变量的各个域都更新完成后使用write_bootloader_message()写回到真正的BCB块中。
这个过程可以用一个简单的图来概括,这样更清晰:

猜你喜欢

转载自blog.csdn.net/lf12345678910/article/details/72876454
今日推荐