Android系统Recovery工作原理之使用update.zip升级过程分析(六)---Recovery服务流程细节

来源:互联网 发布:h5 js 跳转到原生界面 编辑:程序博客网 时间:2024/06/05 06:53

    Android系统Recovery工作原理之使用update.zip升级过程分析(六)---Recovery服务流程细节

转自:http://blog.csdn.net/mu0206mu/article/details/7465439

         Recovery服务毫无疑问是Recovery启动模式中最核心的部分。它完成Recovery模式所有的工作。Recovery程序对应的源码文件位于:/gingerbread0919/bootable/recovery/recovery.c。


一、 Recovery的三类服务:

         先看一下在这个源码文件中开始部分的一大段注释,这将对我们理解Recovery服务的主要功能有很大帮助。代码如下:

         

[cpp] view plain copy
  1. /* 
  2.  * The recovery tool communicates with the main system through /cache files. 
  3.  *   /cache/recovery/command - INPUT - command line for tool, one arg per line 
  4.  *   /cache/recovery/log - OUTPUT - combined log file from recovery run(s) 
  5.  *   /cache/recovery/intent - OUTPUT - intent that was passed in 
  6.  * 
  7.  * The arguments which may be supplied in the recovery.command file: 
  8.  *   --send_intent=anystring - write the text out to recovery.intent 
  9.  *   --update_package=path - verify install an OTA package file 
  10.  *   --wipe_data - erase user data (and cache), then reboot 
  11.  *   --wipe_cache - wipe cache (but not user data), then reboot 
  12.  *   --set_encrypted_filesystem=on|off - enables / diasables encrypted fs 
  13.  * 
  14.  * After completing, we remove /cache/recovery/command and reboot. 
  15.  * Arguments may also be supplied in the bootloader control block (BCB). 
  16.  * These important scenarios must be safely restartable at any point: 
  17.  * 
  18.  * FACTORY RESET 
  19.  * 1. user selects "factory reset" 
  20.  * 2. main system writes "--wipe_data" to /cache/recovery/command 
  21.  * 3. main system reboots into recovery 
  22.  * 4. get_args() writes BCB with "boot-recovery" and "--wipe_data" 
  23.  *    -- after this, rebooting will restart the erase -- 
  24.  * 5. erase_volume() reformats /data 
  25.  * 6. erase_volume() reformats /cache 
  26.  * 7. finish_recovery() erases BCB 
  27.  *    -- after this, rebooting will restart the main system -- 
  28.  * 8. main() calls reboot() to boot main system 
  29.  * 
  30.  * OTA INSTALL 
  31.  * 1. main system downloads OTA package to /cache/some-filename.zip 
  32.  * 2. main system writes "--update_package=/cache/some-filename.zip" 
  33.  * 3. main system reboots into recovery 
  34.  * 4. get_args() writes BCB with "boot-recovery" and "--update_package=..." 
  35.  *    -- after this, rebooting will attempt to reinstall the update -- 
  36.  * 5. install_package() attempts to install the update 
  37.  *    NOTE: the package install must itself be restartable from any point 
  38.  * 6. finish_recovery() erases BCB 
  39.  *    -- after this, rebooting will (try to) restart the main system -- 
  40.  * 7. ** if install failed ** 
  41.  *    7a. prompt_and_wait() shows an error icon and waits for the user 
  42.  *    7b; the user reboots (pulling the battery, etc) into the main system 
  43.  * 8. main() calls maybe_install_firmware_update() 
  44.  *    ** if the update contained radio/hboot firmware **: 
  45.  *    8a. m_i_f_u() writes BCB with "boot-recovery" and "--wipe_cache" 
  46.  *        -- after this, rebooting will reformat cache & restart main system -- 
  47.  *    8b. m_i_f_u() writes firmware image into raw cache partition 
  48.  *    8c. m_i_f_u() writes BCB with "update-radio/hboot" and "--wipe_cache" 
  49.  *        -- after this, rebooting will attempt to reinstall firmware -- 
  50.  *    8d. bootloader tries to flash firmware 
  51.  *    8e. bootloader writes BCB with "boot-recovery" (keeping "--wipe_cache") 
  52.  *        -- after this, rebooting will reformat cache & restart main system -- 
  53.  *    8f. erase_volume() reformats /cache 
  54.  *    8g. finish_recovery() erases BCB 
  55.  *        -- after this, rebooting will (try to) restart the main system -- 
  56.  * 9. main() calls reboot() to boot main system 
  57.  * 
  58.  * SECURE FILE SYSTEMS ENABLE/DISABLE 
  59.  * 1. user selects "enable encrypted file systems" 
  60.  * 2. main system writes "--set_encrypted_filesystems=on|off" to 
  61.  *    /cache/recovery/command 
  62.  * 3. main system reboots into recovery 
  63.  * 4. get_args() writes BCB with "boot-recovery" and 
  64.  *    "--set_encrypted_filesystems=on|off" 
  65.  *    -- after this, rebooting will restart the transition -- 
  66.  * 5. read_encrypted_fs_info() retrieves encrypted file systems settings from /data 
  67.  *    Settings include: property to specify the Encrypted FS istatus and 
  68.  *    FS encryption key if enabled (not yet implemented) 
  69.  * 6. erase_volume() reformats /data 
  70.  * 7. erase_volume() reformats /cache 
  71.  * 8. restore_encrypted_fs_info() writes required encrypted file systems settings to /data 
  72.  *    Settings include: property to specify the Encrypted FS status and 
  73.  *    FS encryption key if enabled (not yet implemented) 
  74.  * 9. finish_recovery() erases BCB 
  75.  *    -- after this, rebooting will restart the main system -- 
  76.  * 10. main() calls reboot() to boot main system 
  77.  */  

          从注释中我们可以看到Recovery的服务内容主要有三类:

         FACTORY RESET,恢复出厂设置。

         OTA INSTALL,即我们的update.zip包升级。

         ENCRYPTED FILE SYSTEM ENABLE/DISABLE,使能/关闭加密文件系统。具体的每一类服务的大概工作流程,注释中都有,我们在下文中会详细讲解OTA INSTALL的工作流程。这三类服务的大概的流程都是通用的,只是不同操作体现与不同的操作细节。下面我们看Recovery服务的通用流程。


二、Recovery服务的通用流程:

        在这里我们以OTA INSTALL的流程为例具体分析。并从相关函数的调用过程图开始,如下图:


          

          我们顺着流程图分析,从recovery.c的main函数开始:

          1.    ui_init():Recovery服务使用了一个基于framebuffer的简单ui(miniui)系统。这个函数对其进行了简单的初始化。在Recovery服务的过程中主要用于显示一个背景图片(正在安装或安装失败)和一个进度条(用于显示进度)。另外还启动了两个线程,一个用于处理进度条的显示(progress_thread),另一个用于响应用户的按键(input_thread)。

          2.    get_arg():这个函数主要做了上图中get_arg()往右往下直到parse arg/v的工作。我们对照着流程一个一个看。

                get_bootloader_message():主要工作是根据分区的文件格式类型(mtd或emmc)从MISC分区中读取BCB数据块到一个临时的变量中。

                然后开始判断Recovery服务是否有带命令行的参数(/sbin/recovery,根据现有的逻辑是没有的),若没有就从BCB中读取recovery域。如果读取失败则从/cache/recovery/command中读取然后。这样这个BCB的临时变量中的recovery域就被更新了。在将这个BCB的临时变量写回真实的BCB之前,又更新的这个BCB临时变量的command域为“boot-recovery”。这样做的目的是如果在升级失败(比如升级还未结束就断电了)时,系统在重启之后还会进入Recovery模式,直到升级完成。

                在这个BCB临时变量的各个域都更新完成后使用set_bootloader_message()写回到真正的BCB块中。

                这个过程可以用一个简单的图来概括,这样更清晰:

                                 


          3.     parserargc/argv:解析我们获得参数。注册所解析的命令(register_update_command),在下面的操作中会根据这一步解析的值进行一步步的判断,然后进行相应的操作。

          4.    if(update_package):判断update_package是否有值,若有就表示需要升级更新包,此时就会调用install_package()(即图中红色的第二个阶段)。在这一步中将要完成安装实际的升级包。这是最为复杂,也是升级update.zip包最为核心的部分。我们在下一节详细分析这一过程。为从宏观上理解Recovery服务的框架,我们将这一步先略过,假设已经安装完成了。我们接着往下走,看安装完成后Recovery怎样一步步结束服务,并重启到新的主系统的。

          5.    if(wipe_data/wipe_cache):这一步判断实际是两步,在源码中是先判断是否擦除data分区(用户数据部分)的,然后再判断是否擦除cache分区。值得注意的是在擦除data分区的时候必须连带擦除cache分区。在只擦除cache分区的情形下可以不擦除data分区。

          6.    maybe_install_firmware_update():如果升级包中包含/radio/hboot firmware的更新,则会调用这个函数。查看源码发现,在注释中(OTA INSTALL)有这一个流程。但是main函数中并没有显示调用这个函数。目前尚未发现到底是在什么地方处理。但是其流程还是向上面的图示一样。即,① 先向BCB中写入“boot-recovery”和“—wipe_cache”之后将cache分区格式化,然后将firmware image 写入原始的cache分区中。②将命令“update-radio/hboot”和“—wipe_cache”写入BCB中,然后开始重新安装firmware并刷新firmware。③之后又会进入图示中的末尾,即finish_recovery()。

          7.    prompt_and_wait():这个函数是在一个判断中被调用的。其意义是如果安装失败(update.zip包错误或验证签名失败),则等待用户的输入处理(如通过组合键reboot等)。

          8.    finish_recovery():这是Recovery关闭并进入Main System的必经之路。其大体流程如下:

                                               

                将intent(字符串)的内容作为参数传进finish_recovery中。如果有intent需要告知Main System,则将其写入/cache/recovery/intent中。这个intent的作用尚不知有何用。

                将内存文件系统中的Recovery服务的日志(/tmp/recovery.log)拷贝到cache(/cache/recovery/log)分区中,以便告知重启后的Main System发生过什么。

                擦除MISC分区中的BCB数据块的内容,以便系统重启后不在进入Recovery模式而是进入更新后的主系统。

                删除/cache/recovery/command文件。这一步也是很重要的,因为重启后Bootloader会自动检索这个文件,如果未删除的话又会进入Recovery模式。原理在上面已经讲的很清楚了。


          9.    reboot():这是一个系统调用。在这一步Recovery完成其服务重启并进入Main System。这次重启和在主系统中重启进入Recovery模式调用的函数是一样的,但是其方向是不一样的。所以参数也就不一样。查看源码发现,其重启模式是RB_AUTOBOOT。这是一个系统的宏。

 

            至此,我们对Recovery服务的整个流程框架已有了大概的认识。下面就是升级update.zip包时特有的也是Recovery服务中关于安装升级包最核心的第二个阶段。即我们图例中的红色2的那个分支。


           我们将在下一篇详细讲解这一部分,即Recovery服务的核心部分install_package函数

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 电焊把脸烤了痒的不行怎么办? 还没满月的宝宝吐奶怎么办 周岁宝宝发烧腹泻吃药老吐怎么办 生完宝宝后肚皮很黑怎么办 两个月宝宝抵抗力差总生病怎么办 两岁宝宝只会说几个简单的词怎么办 两岁宝宝对绘本不感兴趣怎么办 一岁十个月宝宝不爱吃饭怎么办 孩子上三年级学习太差应该怎么办 mac系统打数字出显符号怎么办 我太粗心了工作中总犯错怎么办 四年级的孩子数学计算总粗心怎么办 小孩做作业拖拉的很厉害怎么办 二年级孩子做作业太粗心怎么办 发现孩子做作业时玩手机怎么办 高三孩子考试时慌乱老粗心怎么办 助班面试你的学生不喜欢你怎么办 上三年级的小孩不愿做作业怎么办 快一年了孩子上幼儿园总哭怎么办 宝宝吃多了吐了很多怎么办 一岁宝宝只吃母乳不吃辅食怎么办 孩子平常考得好正式考不好怎么办 平常成绩好期末却考不好怎么办 初中生去国外上学国内的学校怎么办 孩子在学校不受老师的重视怎么办 孩子上二年级了不爱学习怎么办 接别人的班被学生讨厌怎么办 孩子在学校老师打孩子家长怎么办? 宝宝不听话我老忍不住打他怎么办 两岁宝宝断母乳不愿意喝奶粉怎么办 2岁半的宝宝叛逆不听话怎么办? 2岁半宝宝说什么不听话怎么办? 误把脱毛膏当牙膏用了刷牙怎么办 儿子1岁5个月了不说话怎么办 两岁小儿不会说话和智商低怎么办 宝宝不会说话教他说他不愿意怎么办 25个月宝宝不愿意学说话怎么办 老师说小孩在幼儿园老是说话怎么办 在外留学想领养一个外国小孩怎么办 三岁半的宝宝想去美国上学怎么办 农村新房边的老老祖坟不搬怎么办