本文转载自:http://www.it610.com/article/5752570.htm
1、概述
1.1 文档概要
前段时间学习了AndroidRecovery模式及OTA升级过程,为加深理解和防止以后遗忘,所以写这篇文档进行一个总结和梳理,以便日后查阅回顾。文档主要包括两部分,第一部分为OTA升级包的制作过程分析,第二部分为Recovery模式下OTA升级包安装过程的分析,其中包括Recovery模式分析及服务流程。
1.2 参考文献
《Recovery 开发指导》
《Android系统Recovery工作原理之使用update.zip升级过程分析》
《OTA本质与实现流程分析》
《Android系统启动过程分析》
2、OTA升级包制作工程
2.1 OTA升级简介
所谓OTA(Over-the-AirTechnology)是指手机终端通过无线网络下载远程服务器上的升级包,对系统或应用进行升级的技术。有关网络部分不做过多讨论,本文重点放在系统升级这一概念上。
图1 某android手机存储设备结构图
以PC机进行类比,假设计算机操作系统装在C盘,当加电启动时,引导程序会将C盘的系统程序装入内存并运行,而系统升级或重装系统,则是将C盘中原来的系统文件部分或全部重写。对于手机及其上的ANDROID系统而言,同样如此,需要一个存储系统文件的“硬盘”。
图1 是某款手机的存储设备结构图,其存储区(红色框图部分)分为四部分:SRAM、Nand Flash、SDRAM及外设地址空间。其中Nand Flash中存储着全部系统数据(通过专门的烧写工具将编译后的映象文件download到Nand Flash中,工具由IC厂商提供),包括boot.img、system.img、recovery.img等,因此Nand Flash即是上文所说的手机上的“硬盘”。图1最右部分(图中绿色框图部分)是Nand Flash存储区更详细的划分,我们将主要关注system分区(蓝色框图),因为OTA升级主要是对这部分系统数据的重写(当然boot分区也可升级)。除此之外,蓝黑色区域标示的misc分区也应值得注意,它在OTA升级中发挥着重要的作用。
OK,一言以蔽之,所谓OTA就是将升级包(zip压缩包)写入到系统存储区,因此我们需要考虑两个问题:1、升级包是如何生成的?2、升级包是如何写入到system分区的?
2.2 OTA升级包update.zip结构
2.2.1、 update.zip包的目录结构
|----boot.img
|----system/
|----recovery/
`|----recovery-from-boot.p
`|----etc/
`|----install-recovery.sh
|---META-INF/
`|CERT.RSA
`|CERT.SF
`|MANIFEST.MF
`|----com/
`|----google/
`|----android/
`|----update-binary
`|----updater-script
`|----android/
`|----metadata
2.2.2、 update.zip包目录结构详解
以上是我们用命令makeotapackage 制作的update.zip包的标准目录结构。(和实际的略有不同)
1、boot.img是更新boot分区所需要的文件。这个boot.img主要包括kernel+ramdisk,包括应用会用到的一些库等等。可以将Android源码编译out/target/product/ xxxx /system/中的所有文件拷贝到这个目录来代替。
2、system/目录的内容在升级后会放在系统的system分区。主要用来更新系统的一些应用或则应用会用到的一些库等等。可以将Android源码编译out/target/product/xxxx/system/中的所有文件拷贝到这个目录来代替。
3、recovery/目录中的recovery-from-boot.p是boot.img和recovery.img的补丁(patch),主要用来更新recovery分区,其中etc/目录下的install-recovery.sh是执行更新的脚本。
4、update-binary是一个二进制文件,相当于一个脚本解释器,能够识别updater-script中描述的操作。它是Android源码编译后生成的out/target/product/xxxx/system bin/updater文件,可将updater重命名为update-binary得到。该文件在具体的更新包中的名字由源码中bootable/recovery/install.c中的宏ASSUMED_UPDATE_BINARY_NAME的值而定。
5、updater-script:此文件是一个脚本文件,具体描述了更新过程。我们可以根据具体情况编写该脚本来适应我们的具体需求。该文件的命名由源码中bootable/recovery/updater/updater.c文件中的宏SCRIPT_NAME的值而定。
6、 metadata文件是描述设备信息及环境变量的元数据。主要包括一些编译选项,签名公钥,时间戳以及设备型号等。
7、我们还可以在包中添加userdata目录,来更新系统中的用户数据部分。这部分内容在更新后会存放在系统的/data目录下。
8、update.zip包的签名:update.zip更新包在制作完成后需要对其签名,否则在升级时会出现认证失败的错误提示。而且签名要使用和目标板一致的加密公钥。加密公钥及加密需要的三个文件在Android源码编译后生成的具体路径为:
out/host/linux-x86/framework/signapk.jar
build/target/product/security/testkey.x509.pem
build/target/product/security/testkey.pk8。
我们用命令makeotapackage制作生成的update.zip包是已签过名的,如果自己做update.zip包时必须手动对其签名。具体的加密方法:
$ java –jar gingerbread/out/host/linux/framework/signapk.jar –wgingerbread/build/target/product/security/testkey.x509.pem gingerbread/build/target/product/security/testkey.pk8update.zip update_signed.zip
以上命令在update.zip包所在的路径下执行,其中signapk.jartestkey.x509.pem以及testkey.pk8文件的引用使用绝对路径。update.zip 是我们已经打好的包,update_signed.zip包是命令执行完生成的已经签过名的包。
9、MANIFEST.MF:这个manifest文件定义了与包的组成结构相关的数据。类似Android应用的mainfest.xml文件。
10、CERT.RSA:与签名文件相关联的签名程序块文件,它存储了用于签名JAR文件的公共签名。
11、CERT.SF:这是JAR文件的签名文件,其中前缀CERT代表签名者。
另外,在具体升级时,对update.zip包检查时大致会分三步:①检验SF文件与RSA文件是否匹配。②检验MANIFEST.MF与签名文件中的digest是否一致。③检验包中的文件与MANIFEST中所描述的是否一致。
12、在做的MTK平台的项目(如8670、9976),需要增加与项目强相关的适配文件(scatter.txt、SEC_VER.txt、type.txt),scatter.txt分散加载文件,将可执行映像文件分散加载到不同的内存段(文件内容:指定不同内存段的起始地址)。
type.txt是build升级包过程生成的,里面的值1代表FullOTA,0代表DiffOTA,android的上层的update流程中会check这个值。
scatter.txt也是build升级包过程生成的,里面的内容来自于/mediatek/misc/ota_scatter.txt。具体code可见脚本ota_from_target_files。而mediatek/misc/ota_scatter.txt是在build full ota时会产生。该文件主要用于在升级的时候check升级前后parition layout是否有改变。
SEC_VER.TXT是在编译时从alps\mediatek\custom\$PROJECT\security\recovery下copy过来的,用于在打开SUPPORT_SBOOT_UPDATE之后会使用,具体可以参考[FAQ05739] SD或者OTA升级secutiry device和non-security device的区别。
在./mk new时,会执行ptgen,执行ptgen会依赖OTA_SCATTER_FILE,见mediatek/build/libs/pregen.mk:218,然后再build/tools/makeMtk.mk中的142 以及 692会生成ota_scatter.txt。
2.3 OTA升级包制作工程分析
升级包有整包与差分包之分。顾名思义,所谓整包即包含整个system分区中的数据文件;而差分包则仅包含两个版本之间改动的部分。利用整包升级好比对电脑进行重作系统,格式化系统分区,并将新系统数据写入分区;而利用差分包升级不会格式化system分区,只是对其中部分存储段的内容进行重写。除升级包之外,制作过程中还会涉及到另一种zip包,代码中称之为8675-cota-target_files-xxx.zip,我称之为差分资源包。首先阐述下整包的制作过程。
2.3.1 整包的制作
系统经过整编后,执行makeotapackage命令,即可完成整包的制作,而此命令可分为两个阶段进行。首先执行./build/core/Makefile中的代码:
#-----------------------------------------------------------------
# OTA update package
name := $(TARGET_PRODUCT)
ifeq ($(TARGET_BUILD_TYPE),debug)
name :=$(name)_debug
endif
name := $(name)-ota-$(FILE_NAME_TAG)
INTERNAL_OTA_PACKAGE_TARGET:= $(PRODUCT_OUT)/$(name).zip
$(INTERNAL_OTA_PACKAGE_TARGET): KEY_CERT_PAIR :=$(DEFAULT_KEY_CERT_PAIR)
$(INTERNAL_OTA_PACKAGE_TARGET):$(BUILT_TARGET_FILES_PACKAGE) $(OTATOOLS)
@echo"Package OTA: $@"
$(hide) ./build/tools/releasetools/ota_from_target_files-v \
-n \
-p$(HOST_OUT) \
-k$(KEY_CERT_PAIR) \
$(ota_extra_flag) \
$(BUILT_TARGET_FILES_PACKAGE) $@
.PHONY: otapackage
otapackage: $(INTERNAL_OTA_PACKAGE_TARGET)
#-----------------------------------------------------------------
代码段1 make otapackage目标代码
如上代码是Makefile文件中目标otapackage的执行代码 。首先,make otapackage命令会执行Makefile(./build/core/Makefile)中otapackage的目标代码(如代码1所示)。由代码可知,otapackage目标的执行只依赖于$(INTERNAL_OTA_PACKAGE_TARGET),而不存在任何规则(根据Makefile语法,规则必须以TAB键开始,而目标otapackage的定义之后却是变量name的声明,因此不存在规则),因此只需要关注目标$(INTERNAL_OTA_PACKAGE_TARGET)的生成。显然,此目标的生成依赖于目标文件:$(BUILT_TARGET_FILES_PACKAGE)和$(OTATOOLS),且其执行的命令为./build/tools/releasetools/ota_from_target_files。也就是说,make otapackage所完成的功能全是通过这两个目标文件和执行的命令完成的,我们将分别对这三个关键点进行分析。
a) $(OTATOOLS)
目标文件OTATOOLS的编译规则如下所示
1. OTATOOLS := $(HOST_OUT_EXECUTABLES)/minigzip \
2. $(HOST_OUT_EXECUTABLES)/mkbootfs \
3. $(HOST_OUT_EXECUTABLES)/mkbootimg \
4. $(HOST_OUT_EXECUTABLES)/fs_config \
5. $(HOST_OUT_EXECUTABLES)/mkyaffs2image \
6. $(HOST_OUT_EXECUTABLES)/zipalign \
7. $(HOST_OUT_EXECUTABLES)/aapt \
8. $(HOST_OUT_EXECUTABLES)/bsdiff \
9. $(HOST_OUT_EXECUTABLES)/imgdiff \
10. $(HOST_OUT_JAVA_LIBRARIES)/dumpkey.jar \
11. $(HOST_OUT_JAVA_LIBRARIES)/signapk.jar \
12. $(HOST_OUT_EXECUTABLES)/mkuserimg.sh \
13. $(HOST_OUT_EXECUTABLES)/genext2fs \
14. $(HOST_OUT_EXECUTABLES)/tune2fs \
15. $(HOST_OUT_EXECUTABLES)/e2fsck \
16. $(HOST_OUT_EXECUTABLES)/make_ext4fs
17.
18. .PHONY: otatools
19. otatools: $(OTATOOLS)
可以看出变量OTATOOLS为系统中一系列文件的集合。那么这些文件又有什么用处呢? 事实上,这些文件用于压缩(minigzip:用于gzip文件;make_ext4fs:将文件转换为ext4类型;mkyaffs2image:用于yaffs文件系统;......)、解压缩、差分(bsdiff,imgdiff)、签名(singapk.jar)等功能,结合代码段1可得到如下结论:目标$(INTERNAL_OTA_PACKAGE_TARGET)的执行依赖于这一系列系统工具--仅此而已。也就是说,目标文件$(OTATOOLS)仅仅指定了命令执行所需要的工具,并未执行任何操作。
注:变量$(HOST_OUT_EXECUTABLES)指代的是out/host/linux-x86/bin目录,而变量$(HOST_OUT_JAVA_LIBRARIES)/表示的是out/host/linux-x86/framework目录,这意味着我们可以从此目录下找到上述工具,并为我们所用。
b) $(BUILT_TARGET_FILES_PACKAGE)
目标OTATOOLS指明了执行makeotapackage命令所需要的系统工具,而目标$(BUILT_TARGE_FILES_PACKAGE)的生成则完成了两件事:重新打包system.img文件和生成差分资源包。$(BUILT_TARGE_FILES_PACKAGE)的编译规则如下所示:
1. # -----------------------------------------------------------------
2. # A zip of the directories that map to the target filesystem.
3. # This zip can be used to create an OTA package or filesystem image
4. # as a post-build step.
5. #
6. name := $(TARGET_PRODUCT)
7. ifeq ($(TARGET_BUILD_TYPE),debug)
8. name := $(name)_debug
9. endif
10.name := $(name)-target_files-$(FILE_NAME_TAG)
11.
12.intermediates := $(call intermediates-dir-for,PACKAGING,target_files)
13.BUILT_TARGET_FILES_PACKAGE := $(intermediates)/$(name).zip
14.$(BUILT_TARGET_FILES_PACKAGE): intermediates := $(intermediates)
15.$(BUILT_TARGET_FILES_PACKAGE): \
16. zip_root := $(intermediates)/$(name)
17.
18.# $(1): Directory to copy
19.# $(2): Location to copy it to
20.# The "ls -A" is to prevent "acp s/* d" from failing if s is empty.
21.define package_files-copy-root
22. if [ -d "$(strip $(1))" -a "$$(ls -A $(1))" ]; then \
23. mkdir -p $(2) && \
24. $(ACP) -rd $(strip $(1))/* $(2); \
25. fi
26.endef
27.
28.built_ota_tools := \
29. $(call intermediates-dir-for,EXECUTABLES,applypatch)/applypatch \
30. $(call intermediates-dir-for,EXECUTABLES,applypatch_static)/applypatch_static \
31. $(call intermediates-dir-for,EXECUTABLES,check_prereq)/check_prereq \
32. $(call intermediates-dir-for,EXECUTABLES,sqlite3)/sqlite3 \
33. $(call intermediates-dir-for,EXECUTABLES,updater)/updater
34.$(BUILT_TARGET_FILES_PACKAGE): PRIVATE_OTA_TOOLS := $(built_ota_tools)
35.
36.$(BUILT_TARGET_FILES_PACKAGE): PRIVATE_RECOVERY_API_VERSION := $(RECOVERY_API_VERSION)
37.
38.ifeq ($(TARGET_RELEASETOOLS_EXTENSIONS),)
39.# default to common dir for device vendor
40.$(BUILT_TARGET_FILES_PACKAGE): tool_extensions := $(TARGET_DEVICE_DIR)/../common
41.else
42.$(BUILT_TARGET_FILES_PACKAGE): tool_extensions := $(TARGET_RELEASETOOLS_EXTENSIONS)
43.endif
44.
45.# Depending on the various images guarantees that the underlying
46.# directories are up-to-date.
47.
48.ifeq ($(TARGET_USERIMAGES_USE_EXT4),true)
49.$(BUILT_TARGET_FILES_PACKA