Android原⽣OTA和Recovery升级过程步骤
本⽂介绍了原⽣OTA和Recovery升级过程步骤.
进⼊升级
- 1.1 正常启动和进⼊Recovery的区别
下⾯给出了升级流程的简单⽰意图。
上图中的上下两个部分,上⾯⼀部分是正常的启动模式,下⾯⼀部分为Recovery模式。正常的启动模式是从boot.img启动系统(Main System),⽽recovery模式则是从reovery.img启动系统;(reovery.img只包含内核、简单的⽂件管理系统和图形系统)
Boot分区包括linux内核和Ramdisk,Recovery分区也包括Linux内核和Ramdisk,⼀般来说内核是⼀样的,但Ramdisk区别则⾮常
⼤,recovery中的ramdisk会有更多的recovery需要使⽤的程序和数据。
- 1.2 分区介绍
这⾥说到的boot.img和recovery.img,其实就对应了⼀个设备中的分区,⼀般来说,android设备会包含以下⼏个分区
Boot:包含Linux内核和⼀个最⼩的root⽂件系统(装载到RAM disk中),⽤于挂载系统和其他的分区,并开始Runtime
System:包括了系统应⽤和库⽂件(AOSP中可以获取到源代码),在运⾏的过程中,这个分区是read-only的,只有在OTA升级的时候才会发⽣变化
Vendor:包括了系统应⽤和库⽂件(AOSP中不能获取到源代码),和System分区⼀样,只有在OTA升级的时候才会发⽣变化 Userdata:⽤户安装的应⽤程序会把数据保存在这⾥,正常情况下OTA是不会清除这⾥的数据的,指定要删除出具的除外
Cache:临时的保存应⽤数据(要把数据保存在这⾥,需要特地的app permission),OTA的升级包也可以保存在这⾥。OTA升级过程可能会清楚这个分区的数据。
Recovery:包括了⼀个完整Linux内核和⼀些特殊的recovery binary,可以读取升级⽂件⽤这些⽂件来更新其他的分区
Misc:⼀个⾮常⼩的分区,recovery⽤这个分区来保存⼀些关于升级的信息,应对升级过程中的设备掉电重启的状况
这些分区是Google官⽅的标准,实际的情况可能不太⼀样,就Find 7⽽⾔,刷机包⾥⾯的分区只有以下⼏个 :芯⽚⼚商和⼿机⼚商会根据⾃⼰的需要加⼀些其他的分区,如下⾯的persist.img是⾼通的,reserve4是我们⾃⼰加的保留分区,MTK还有preloader、lk,⾼通的还有NON-HLOS.bin、sbl、emms_aboot等。
Bootloader
- 2.1 什么是Bootloader?
在嵌⼊式操作系统中,Bootloader在操作系统内核运⾏之前运⾏,可以初始化硬件设备、建⽴内存空间映射图,为调⽤操作系统内核准备好正确的环境。Bootloader和硬件是强相关的,且⼚商⼀般都会
对bootloader加锁,这样就不能随便刷机了。
当然bootloader也是可以解锁的,这⾥不得不提⼀下root和bootloader解锁分别是怎么⼀回事:root是通过内核漏洞获取最⾼的权限,也就是所谓的超级⽤户(su,superuser),属于系统层⾯,root之后就可以修改system分区的数据;bootloader解锁则属于硬件层⾯的解锁boot和recovery分区,解锁bootloader不会root⼿机。
- 2.2 Fastboot和recovery的区别?
Bootloader过程中,先做⼀些初始化,然后根据组合键做不同的事情,这个过程内核没有加载,机器知识在按顺序执⾏指令。
Fastboot:在这种模式下,可以修改⼿机的硬件,并且允许我们发送⼀些命令给Bootloader。如使⽤电脑刷机,则需要进⼊fastboot模式,通过电脑执⾏命令将系统镜像刷到通过USB刷到⼿机中。
Recovery:Recovery是⼀个⼩型的操作系统,并且会加载部分⽂件系统,这样才能从sdcard中读取升级包。
Bootloader.cpp
Bootloader(bootable/recovery/bootloader.cpp)会读取位于MISC分区的启动控制信息块BCB(Bootloader Control Block),通过函数:
<code class="hljs cs has-numbering" Source Code Pro", monospace; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" >int</span> get_bootloader_message(<span
class="hljs-keyword" >struct</span> bootloader_message *<span
class="hljs-keyword" >out</span>);
<span class="hljs-keyword" >int</span> set_bootloader_message(<span class="hljs-keyword" >const</span> <span class="hljs-keyword"
>struct</span> bootloader_message *<span class="hljs-keyword"
>in</span>);</code><ul class="pre-numbering" ><li >1</li><li >2</li></ul><ul class="pre-numbering"
><li
>1</li><li >2</li></ul>
如果command的值为“boot-recovery”时,就进⼊recovery模式。Recovery升级过程中掉电,下次按power键开机也会进⼊recovery模式就是因为misc分区依然存在recovery信息(掉电保护)。
Recovery模式
-
3.1 Recovery、Bootloader以及Main System通信⽅法
图1中给出模式⽐较简单,实际上三个实体的交互过程并不是图1那种单向的顺序流程,⽽是⼀个双向的流程,于是就涉及到个三个部分的通信⽅法的实现。
Recovery和Main System交互
这⼀部分源代码(bootable/recovery/recovery.cpp)注释中有详细的介绍,这⾥⼤致总结⼀下:这两个部分交互是通过/cache⽂件来实现的,涉及到的⽂件如下表。
Recovery、Main System和Bootloader交互
这个交互过程是通过BCB来完成的,BCB其实就是⼀个struct(在misc分区),在(bootable/recovery/bootloader.h)中定义。
<code class="hljs scss has-numbering" Source Code Pro", monospace; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">struct bootloader_message {
<span class="hljs-value" >char</span> <span class="hljs-tag" >command</span><span class="hljs-attr_selector" >[32]</span>;<span class="hljs-comment" >//command存储在这个field⾥⾯</span>
<span class="hljs-value" >char</span> status<span class="hljs-attr_selector" >[32]</span>;
<span class="hljs-value" >char</span> recovery<span class="hljs-attr_selector"
>[768]</span>;
<span class="hljs-value" >char</span> stage<span class="hljs-attr_selector" >[32]</span>;
<span class="hljs-value" >char</span> reserved<span class="hljs-attr_selector"
>[224]</span>;
};</code><ul class="pre-numbering" ><li >1</li><li >2</li><li >3</li><li >4</li><li >5</li><li style="box-sizing: border-box; padding: 0px
5px;">6</li><li >7</li></ul><ul class="pre-numbering" ><li >1</li><li >2</li><li >3</li><li >4</li><li >5</li><li >6</li><li >7</li></ul>
Command:重启进⼊recovery或者是更新radio或Bootloader硬件时,会更新这个域;
Status:在bootloader完成“update-radio”和”update-hboot”命令之后更新;
Recovery:⽤于system和recovery之间的通信;
Stage:需要重启多次的packages会写⼊这个值,表⽰所处的状态。
上⾯的过程可以总结为如下的⽰意图:
cache/recovery/command中command有哪些?
下表给出⼀些常⽤的命令和其含义。
- 3.3 Factory Reset—恢复出⼚设置
恢复出⼚设置也在recovery.cpp中完成,具体的流程如下:
1) ⽤户选择恢复出⼚设置
2) Main System会在cache/recovery/command中写⼊—wipe-data的命令,然后重启进⼊recovery
3) 通过get_args在BCB中写⼊boot-recovery和wipe-data命令
4) 然后重启进⾏erase_volume
5) 擦除数据之后调⽤finish_recovery将BCB中的数据清除
6) main()函数调⽤reboot()进⼊Main System;
OTA安装
4.1 OTA简介
OTA,即Over the air,它可以实现完整的版本升级,也可以是增量升级。⽤户可以选择在SD卡中作本地升级,也可以直接采⽤⽹络在线升级。不管是哪种⽅式,都有⼏个过程:⽣成升级包、获取升级包、执⾏升级包,⽣成升级包不做介绍,。
实际上,所谓OTA的整个过程可以⽤如下⽰意图表⽰。
⾸先,⽤户⽤⼿机的OTA检查更新(或者是⾃动更新),发送查询数据给服务器,然后服务器查询到
相应的包,并返回下载地址给OTA.apk,然后OTA.apk进⾏下载,把下载的数据存储在⼿机的某个分区。完成之后⽤于选择是否升级,升级的时候OTA会发送命令给Main System,进⼊recovery,recovery根据利⽤下载下来的升级包完成升级过程。
从图中,我们可以看出OTA.apk实际上只是完成了从服务下下载安装包,以及发送升级命令,功能似乎很容易描述,但是实际上要做的事情却是⾮常多的,特别是OTA 2.0将Applypatch功能移植到OTA.apk之后,复杂度进⼀步增加了。
4.2 OTA安装流程
下⾯对Recovery的升级步骤做⼀个梳理:
1) Main System下载OTA升级包,官⽅推荐下载到/cache分区下,但是实际上可以⾃⼰选择存储地⽅;
2) Main System在/cache/recovery/command中写⼊“—update_package=安装包路径”
3) 系统重启进⼊recovery,这⼀步是通过PowerManager的reboot(“recovery”)实现的
4) Get_args()在BCB中写⼊“boot-recovery”和”—update_package“,这样就保证了即便是设备出故障重启了,只有这两个命
令还在,就会尝试重新安装OTA升级包
5) Install_package尝试开始安装OTA升级包
6) Finish_package擦除BCB
7) 如果升级失败
Prompt_and_wait显⽰错误,并等待⽤户响应
⽤户重启
8) 设备重启进⼊MainSystem
此外,还有个maybe_install_firmware_upadate,具体过程不做介绍了。
borderbox下⾯是Recovery的代码的区别,实际上2.3/3.0/4.4和5.0的代码差别还是⾮常⼤的,原因是5.0的recovery⽤C++改写了⼀遍,官⽅⽂档两者改写的函数进⾏了对⽐
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论