android recovery

Android recovery的功能可以分成三个主要的组成部分:

         1 选择引导部分。主要功能是启动是进行选择是启动正常的android系统还是用于recovery的特殊系统。

         2 用于进行升级的recovery系统,其中recovery系统拥有自己独立的UI和菜单解析系统。

         3 希望升级的程序集合包。在这个升级包中包含升级的目标程序,一个简单的安全验证机制和验证码。一个用于控制升级的脚本和运行脚本所需要的API。


Android recovery系统升级流程:

         Chip rom

            |

         SOC

            |

         u-boot

            |

            |—— KEY and boot reason 判断——|

         正常启动                                                        recovery

            |                                                                              |

         BOOT partition                                              RECOVERY partition

            |                                                                              |

         Android                                                            recovery UI

                                                                                       |

                                                                                    Check SD or cache

                                                                                       |

                                                                                    Find update package

                                                                                       |

                                                                                    Run update script


一、Recovery是如何构成的

  说recovery的构成并不贴切,应该说recovery.img的构成,它是由boot_img_hdr + zImage + recovery-ramdisk构成。boot_img_hd是个结构体它描述了很多重要的信息。


1 struct boot_img_hdr
 2 {
 3     unsigned char magic[BOOT_MAGIC_SIZE];
 4     unsigned kernel_size;  /* size in bytes */
 5     unsigned kernel_addr;  /* physical load addr */
 6     unsigned ramdisk_size; /* size in bytes */
 7     unsigned ramdisk_addr; /* physical load addr */
 8     unsigned second_size;  /* size in bytes */
 9     unsigned second_addr;  /* physical load addr */
10     unsigned tags_addr;    /* physical addr for kernel tags */
11     unsigned page_size;    /* flash page size we assume */
12     unsigned unused[2];    /* future expansion: should be 0 */
13     unsigned char name[BOOT_NAME_SIZE]; /* asciiz product name */
14     unsigned char cmdline[BOOT_ARGS_SIZE];
15     unsigned id[8]; /* timestamp / checksum / sha1 / etc */
16 };

其中kernel_size表示zImage的实际大小;kernel_addr表示zImage载入内存的物理地址,这个地址也是bootloader跳转到内核的地址;ramdisk_size表示ramdisk(此处就是指recovery-ramdisk)的实际大小;ramdisk_addr是ramdisk加载到内存的物理地址,之后kernel会解压并把它挂在成根文件系统,我们的中枢神经-init.rc就隐藏于内;second_size,second_addr做扩展用一般都不会使用(在我的一个项目中把它扩展成另外一种功能有机会介绍给大家);tags_addr是传参数用的物理内存地址,它作用是把bootloader中的参数传递给kernel;page_size是flash(eg. nandflash)的一个页大小,一般为2K,这通常情况取决于你使用Flash芯片的页大小;cmdline就是command line它可以由bootloader传递也可以在.config(kernel)中配置。

zImage是我们熟悉的内核镜像,由kernel编译生成。recovery-ramdisk是由mkbootfs、gzip打包生成的,命令如下:

mkbootfs ramdiskdir | gzip > recovery-ramdisk.gz

FROM: http://www.cnblogs.com/becklc/archive/2012/09/24/2676600.html



recovery相关代码路径:

1 启动引导部分:

  

2 OTA package打包脚本

         build/tools/releasetools/common.py

         build/tools/releasetools/edify_generator.py

         build/tools/releasetools/ota_from_target_files

3 recovery 主控程序

         bootable/recovery/*.*

         这部分代码主要完成三部分功能:UI,安全验证,脚本解释器。



1、调用main函数

在gingerbread/bootable/recovery/recovery.c最下面有个main(),这是recovery应用的主入口,当编译recovery的时候,会生成一个名为recovery的可执行文件,我这边是放在out/目录下recovery/文件系统的/sbin目录下,调用recovery可执行文件时会传入参数,这些参数就是main函数的参数,如下

  1. int  
  2. main(int argc, char **argv)  
  3. {  
  4.     char tmp[4];  
  5.     time_t start = time(NULL);  
  6.  
  7. #if RECOVERY_DBG  
  8.     log_init();  
  9. #endif  
  10.     INFO(">>>>> Enter recovery <<<<<\n");  
argc是参数个数,argv是每个参数指针

从这里开始了recovery...


2、获取commond

  1. static void  
  2. get_args(int *argc, char ***argv) {  
  3. //  INFO("Enter get_args\n");  
  4.     struct bootloader_message boot;  
  5.     memset(&boot, 0, sizeof(boot));  
如果命令行有recovery命令,优先执行命令行的recovery命令; 否则,往下查找misc分区中的命令、/cache/recovery/command文件中的命

3、获取默认升级固件路径和名称

 int property_get(const char *key, char *value, const char *default_value);

包括U盘、SD卡和Flash升级


4、解析命令

int getopt_long(int, char * const *, const char *,   const struct option *, int *);

如 case 's': send_intent = optarg; break;

optarg是取命令中等号后面字符串

注册一些命令,register_update_commands函数是注册在update-script和recovery-script使用的升级命令

初始化一个变量,int status = INSTALL_SUCCESS;这个变量是用来标识升级是否成功,在清除misc分区命令时候作为一个判断依据


5、升级、格式化、还原

接下来,有三种需求,一是factorytest;二是update、recover;三是wipe data

  1. if (update_image != NULL) {  
  2.     status = install_update(update_image);  
  3.     if (status != 0) {  
  4.         ui_set_background(BACKGROUND_ICON_ERROR);  
  5.         if(status==-1) g_enable_item_move = false;  
  6.     }  
  7. }else if(recover_image != NULL){  
  8. atus = recover_backup(recover_image);  
  9.     if (status != 0) {  
  10.         ui_set_background(BACKGROUND_ICON_ERROR);  
  11.         if(status==-1) g_enable_item_move = false;  
  12.     }  
  13. }   
这部分代码是update\recover的需求,update走install_update分支,recovery走recover_backup分支,g_enable_item_move是在recovery升级界面条目是否可移动的一个变量,false表示不能移动
  1. if (wipe_flags) {  
  2.        if( wipe_data(wipe_flags) != 0 )  
  3.        {  
  4.            status = INSTALL_ERROR;  
  5.            ui_print("Data wipe failed.\n");  
  6.            // 不擦除misc中的命令,重启后再次格式化  
  7.            g_reset_blmsg = false;  
  8.            g_enable_item_move = false;  
  9.        }  
  10.    }  
这部分是擦除数据,就是格式化需求,根据擦除flags记录,分别去擦除需要格式化的分区或者磁盘,如果擦除失败,g_reset_blmsg 这个变量在擦除boot时候作为判别依据,false表示不擦出,这样,misc分区的内容还是recovey,下次重启后,boot引导进入recovery模式 prompt_and_wait()函数里面,关键部分
  1.   for (;;) {  
  2.       int key = 0;  
  3. INFO("wait an key\n");  
  4. key = ui_wait_key();  
  5. INFO("end wait\n");  
这个函数作用就是一直在等待用户输入是一个不断的循环,可以选择五个条目,包括恢复出厂设置和重启等;maybe_install_firmware_update(send_intent);是给用户一个机会,写入你的intent,做一些谷歌没有做的事这个就是完成升级的最后一个函数,
  1. // Reset the bootloader message to revert to a normal main system boot.  
  2.     if(g_reset_blmsg)  
  3.     {  
  4.     INFO("ready to clear cmd in misc \n");  
  5.         struct bootloader_message boot;  
  6.         memset(&boot, 0, sizeof(boot));  
  7.         set_bootloader_message(&boot);  
  8.     }  
在这之前是针对intent的一个处理,这里g_reset_blmsg是根据上文提到的清除boot的一个判据,如果需要清除boot,表明下次重启后正常启动,不进入recovery模式 6、reboot处理完boot和misc分区,重启。



fastboot协议是PC通过USB与手机上的bootloader通信的协议。适用于Linux,Windows,OSX等平台。

 

基本配置要求:

1、USB连接PC与手机。

2、对于high-speec USB,包的最大尺寸必须是512byte.对于full-speed USB,包的最大尺寸必须是64byte。

3、协议由PC端驱动。

 

协议传输过程如下:

1、PC向手机发送一个命令,命令由ASCII字符组成,必须存在在一个不大于64byte的包里。

2、手机向PC响应一个不大于64byte的包。包的最前面四个byte是“OKAY”、“FAIL”、“DATA”、“INFO”中的一个。后面如果还有byte,包含就是ASCII信息。下面具体解释

INFO:后面的60个byte代表的信息被显示完成后,跳到#2继续执行。

FAIL:命令执行失败。后面的60个byte是需要显示给用户的失败信息。

OKAY:命令执行成功。跳到#1.

DATA:命令执行成功,开始进入数据传输阶段。一个DATA响应包的大小是12byte,通常是DATA00000000这样的形式,后面的8个数字代表的要传输的数据包的总大小。

3、如果#2时,PC收到的是DATA命令的话,就开始传输数据。0byte数据会被忽略。当#2指示的数据大小被传输完成时,数据传输结束。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值