android 固件升级/复位实现方法分析

 

android 固件升级/复位实现方法分析


android behavior 嵌入式操作系统 linux内核 产品设计 cache

多功能的智能化嵌入式设备大量增长的应用对嵌入式设备的系统设计提出了更多挑战,传统的一次成型已经无法适应快速变化的市场,设备供应商在产品设计阶段就必须考虑软件每一部分如何升级。在系统开发阶段,系统设计人员会频繁替换软件进行测试、验证和调试,如固件开发人员对引导区的调试,系统工程师进行系统调试等。产品设计过程中快速方便的升级更新方法是加快开发进度的必要手段;而对于发布到用户手中的最终产品也会存有潜在的可通过软件升级解决的缺陷或系统可完善的部分,供应商需要提供升级包给客户进行自行升级修正以解决成本 / 性能问题。一般而言,升级设计必须遵循的原则为: 1 尽量消除或最大程度减少升级过程对辅助工具特别是专用工具的依赖。如需要特别编程器、需要物理焊接拆除某些部件等。 2 符合使用人群的操作习惯和知识体系。针对专业人士则可以开放更多底层接口,而对于普通消费者则要求做到操作简单直接。 3 具备防止误操作和自我修复功能。系统不应该由于一次升级误操作而导致需要返厂修理。嵌入式操作系统 Android 的固件升级方法可以作为类似升级的一个例子。

系统恢复模式启动

 

正常启动

 
基于 android 系统的设备一般将存储区间逻辑上分为:引导区、内核区、 ramdisk 区间、 recovery 区、系统区、cache 区间和数据区。其中 reocvery 区间为系统修复时候使用,其他区间功能如下:引导区为处理器上电固定的加载点,其存储位置依据处理器不同而变化,对于支持从 nand 加载引导固件的处理器,可以将引导区域直接放置到

图一

 
                                 nandflash 中,一般占据从 nand 的 block0 开始的

一些区域。否则必放置到处理器支持的加载点如 norflash 等。 Boot代码负责操作系统的加载和升级,由于 boot 才能从一些基本的数据源如串口、 usb 获取升级数据,作为处理器上电即加载和运行的这一区域一旦损坏则系统升级只能凭借处理器内建原生的引导能力,这个过程大都需要专用工具或软件才能完成。该部分的好坏直接涉及是否返厂维修,所以对该区域的改动操作必须十分谨慎;内核区即linux 内核保存位置,其和引导区在最终系统中对一般用户都设计为不能进行升级以维护基本系统的安全性。Ramdisk 和 recovery 区间同标准 linux 中的 initrd ,引导程序根据启动参数决定加载正常的 ramdisk 还是recovery 作为 initrd 传递给内核,其中 recovery 区间为修复系统使用,由于其为修复 / 升级系统的核心组件,一般也都设计为对用户不可改变。系统区为正常的 android 应用保存位置,一般设计为对普通用户属只读系统以保护主要系统的安全性,数据区为用户设置信息、优化后的 DEX 和系统数据库保存位置,清空该区域会清除用户的所有数据以及优化过的 DEX 文件,导致下一次启动过程很长(需要重新创建 data 目录中的缺省信息)。 Cache区间为升级过程使用的临时存储区。 Android 系统正常启动和 recovery 方式启动过程各区间操作使用情况如图一。图中箭头所指区域为操作区域,箭头的源为发起者。 android 的系统复位过程实际就是清除 data/cache 区域。

Android 升级分为两种,一种是对系统中单个文件升级,一种是对 mtd 整个分区进行升级,升级包是用 zip格式压缩的经过签名的压缩文件。升级过程主要流程描述如下:

1 boot 发现用户按住升级按键,将 recovery.img 作为 ramdisk 读取到内存。

2 内核根据 ramdisk 中的 init.rc 执行 recovery 脚本。 Recovery 脚本在 sdcard 中找到升级文件后调用recovery 程序依次做以下操作:

A 检查升级文件的数字签名是否可靠。检查签名使用的本地密钥为 /res/keys

B 如果签名合法则执行提取压缩包中 META-INF/com/google/android/update-binary 文件重命名到/tmp/update_binary 并执行该文件。

C update_binary 解析压缩文件中的 META-INF/com/google/android/updater-script 文件并执行。其升级进度通过管道回传给 recovery 程序。升级 / 更新可以直接覆盖目标文件,也可采用二进制补丁形式以减少升级文件的容量,采用的工具为 bsdiff 和 imgdiff 。对于补丁包升级形式,升级数据源可靠性鉴别的依据为 sha1 校验和数据长度比对。具体要求为: 1 升 级包提供的目标文件的 sha1 值和目标文件计算值符合,即目标正确。 2 进行补丁后的文件 sha1 值和长度符合升级包提供的补丁后的目标文件的长度和 sha1 数值,保证结果正确。两项有一项不符合则升级过程停止。为保证第二项操作不损毁最终目标,打补丁的文件会先临时存储到 cache 中,等到结果比对正确才进行实际写入 / 替换目标文件操作。所以此过程要求 cache 目录必须有足够空间能够保存临时文件。

理论上 recovery 的 ramdisk 可以并入 ramdisk ,由系统传递不同参数给 recovery 来决定其行为。 Android的启动脚本中已经加入对 recovery 的调用,但是该脚本具体执行的动作留给不同厂家自行补充。这一过程的好处是减少 recovery 区间,缺点是如果希望更新 ramdisk 本身,一旦更新失败(如突然断电),则系统的恢复只能依靠引导系统有限的能力,而这个操作一般都需要专业操作 / 工具才能进行。由于 recovery 包本身尺寸并不大,单独隔离出一个区间作为 recovery ,间接的对 ramdisk 的双备份 , 所以单独划分一个区间是值得的。

固件的复位可以通过引导程序传递给 recovery 参数或 android 系统中用户选择 Settings->SD card& phone storage->Factory data reset 两个地方发起。对于开放给用户的后者,该选项仅仅创建文件 /cache/recovery/command, 里面包含命令参数 —wipe_data ,当重新启动系统时候, recovery 程序缺省会解析该文件内容并执行对应的擦除数据区间的操作。如果厂家希望开发更多更强大的功能给用户,比如可以添加升级菜单,然后修改 recovery 程序可以让系统重新启动时候不需按键直接进入升级界面。

你可能感兴趣的:(android 固件升级/复位实现方法分析)