type
status
date
slug
summary
tags
category
icon
password
URL
一、问题现象
C3U升V项目自己编译的柯基版本正常,正式daliy的柯基包开不了机。
二、日志分析
2.1 cgroups.json找不到
cgroup创建失败,apex-bootstrap 启动失败造成的重启
分析原因:由于自己打包的版本正常,而正式签名版本异常。两者有区别的部分在于正式签名,自己打包的版本是没有签名的步骤的,故问题肯定出现再签名部分。
2.2 正式版本+testkey

把 sign_target_file_apks.py中 apk/apex 签名步骤全部跳过了,这些内容编译号target file后自带测试签名
此测试包验证结果:没有解决,报错一样
2.3 怀疑system.img
通过解包后的system.img,进入fastbootd模式单刷system.img,发现报错没有了(有其他的问题)。
我们来描述一下两者system.img的编译区别
自己打包的版本:
system.img从源码编译到out/target/product/missi/system.img
→ merge_target_file 将system.img压入到 nosigned_target_file.zip中
→ 从nosigned_target_file.zip中取出super
正式版本:
system.img从源码编译到out/target/product/missi/system.img
→ merge_target_file 将system.img压入到 nosigned_target_file.zip中
→ sign_target_files_apks 对 nosigned_tagret_file.zip进行签名
→ 在目标文件signed_target_files.zip中不存在system.img,故重新rebuild system.img放到signed_target_file.zip
→ 从signed_target_file.zip中取出super
对于system.img两者的区别在于正式版本多了一次rebuild的过程。
故为了验证是否是system rebuild 导致的问题,写了如下的debug change做验证。
原理是: 从nosigned_target_file.zip中解压出system.img,先压入到signed_tagret_file.zip中,再签名时发现IMAGE/system.img存在就不会再次rebuild,后续继续进行签名流程
此版本验证之前的cgroups.json的报错没有了,确实验证了问题出现在 system rebuild上。
2.4 system rebuild的流程检查
通过对比Android U版本以及Android V版本关于 system rebuild的编译log,发现如下的异常点
Android U:
Android V:
发现V版本在system rebuild 没有编成sparse格式的img
查看代码

进行img2simg受manual_sparse变量控制,而manual_sparse变量受
disable_sparse
控制。而disable_sparse经查询就是misc_info中的 {partition}_disable_sparse参数
Android V rom target-file misc_info.txt:
Android U rom target-file misc_info.txt:
而此参数的生成由如下的代码在编译时生成
这段代码的含义为 检查这三个变量的值:
$(BOARD_$(_var)IMAGE_PARTITION_SIZE)
$(BOARD_$(_var)IMAGE_PARTITION_RESERVED_SIZE)
$(PRODUCT_$(_var)_HEADROOM)
只要这三个变量只要有一个不为空,则不进行任何操作,否则写入${partition}_disable_sparse=true 到文件里。
目前Android V $(partition)_disable_sparse 为true, 所以说明这三个参数肯定都为空
检查到有一笔修改partition_size.mk中把这个参数删除了,加上后测试结果:

增加上BOARD_SYSTEMIMAGE_PARTITION_SIZE后 还是有相同的报错。

此方案编译出的target file中的system.img已经改为了sparse格式的

此怀疑验证fail,编译格式的差异,可能只是android版本的编译差异,不是影响开机的原因。
2.5 本地模拟签名
没什么灵感了,所以尝试本地复现,加一些log 方便debug
准备文件:来源为柯基,miext.target.file.zip 和 userdata.target.file.zip来自小米编译而出(这两个是小米自己加的target-file)
- 创建好文件夹sys_dir/vnd_dir/miext_dir/userdata_dir/out_dir,并将所需要的文件拷贝到对应的文件夹内(如下图)

- 创建apex_keys
使用如下的脚本创建apex_keys
./gen_apex_key.sh ~/Documents/sign_dir/apex_keys
- 创建apk_keys
拷贝 build/make/target/product/security/下的key到apk_keys
- 解压otatools.zip
- 找到vendor_otatools.zip的路径,签名时会用到
- 签名target-file
注意指令的路径要替换成自己的路径,其次使用绝对路径,不要使用相对路径,也不要使用家目录~符号的路径
2.6 异常定位


通过解压缩正常版本与异常版本的target_files.zip发现未签名的targetfile就已经有问题了,ROOT下的软链接都失效了
再次解压异常版本的sys.target_files.zip,ROOT下是正常的

再次check merge阶段 vnd target file与sys target file 解压缩到merge_target_files_xxx的临时目录,ROOT下是正常的

merge完之后的 target_file.zip,ROOT是异常的

那问题点就只会出现在merge target file的阶段

查看代码create merged_target_files.zip的函数

调用soong_zip工具对source_dir进行打包
而output_target_files_temp_dir的由来如下
通过查看log,确定走的下面的这个else代码

output_target_files_temp_dir 就是 temp_dir/output目录
通过在编译时编译log检查temp_dir/output目录

merge之后还会会在temp目录生成临时的target_file.zip解压后发现是正常的

而这个和之前验证的merge完的target_file是异常的是相悖的,那就说明targetfile再次且肯定变动了,此target_files.zip已经是正常merge的流程结束的最后产物

检查这两个步骤之间的编译log,发现如下的异常log

这部分是新增了,也调用了soong_zip函数
检查后发现如下的代码

google正常targetfile的流程生成的一次targetfile.zip
被走了这个流程,解压了一次 又重新生成了一次
而extractall函数的缺陷 不能保留软链接
2.7 修正extractall的代码验证
本地解压出sys.otatools.zip,将merge_vendor_boot_to_modem.py并覆盖到sys.otatools.zip中的源文件,再次重新压缩成新的sys.otatools.zip
本地模拟使用split_build.py merge target file的指令,并再次使用本地sign_target_files_apks指令签targetfile,验证结果均pass
三、根本原因
MTK给的pack vendor_boot 镜像到 modem镜像的patch存在问题,其中会先对target_file.zip解压缩取出vendor_boot.img和modem image,完成pack vendor_boot.img到modem镜像后,会把新的modem镜像再次压缩到target_file.zip中,其中的解压缩操作使用了python的库函数extractall,此函数不会保留target_file.zip中的软链接,从而导致最后开机时候的系统软链接全部失效