刷机攻略,回归一下。
主要刷机方式,EDL(紧急下载,USB端口9008),fastboot工具线刷,OTA升级(全包/差分升级,nonAB系统与AB系统升级)。这个玩android系统的基本都知道,还是列个表:
环境 |
进入方式 |
工具 |
|
EDL模式 |
* |
音量上+音量下 |
厂商工具(QFIL) |
fastboot模式 |
Bootloader |
音量下 |
Fastboot |
recovery模式 |
Kernel+RecoveryFS(nonAB) |
音量上 |
Adb |
update_engine |
Android system(AB) |
update_engine |
表中进入方式不要认为是电源键+音量上/下,模式选择在开机时判断,长按电源键是为了重启。
下面分节,并带GPT修改和NV保留问题去看这几个刷机方式。
目录
1、EDL模式
2、fastboot模式
3、OTA升级
3.1、nonAB系统升级
3.2、AB系统的OTA升级
4、userdebug版本adb push 到/dev/block/by-name/对应的块设备节点
详细见下面blog
高通 MSM8K bootloader 之二: SBL1_Fybon的博客-CSDN博客
1.1、分析xml文件
Program 可以改为read 来dump设备,
SECTOR_SIZE_IN_BYTES 扇区大小
file_sector_offset 偏移
filename 文件名
label 分区名
num_partition_sectors 分区扇区数
sparse 是否是sparse镜像格式,非sparse格式就是直接写。
start_byte_hex 起始位置
start_sector 起始扇区号
1.2、 MODEL参数(NV分区)保留
方法1,有tool->QCN backup按键。
方法2,有partition Manager->read.
方法3,configuration->FireHose configuration->Auto backup Restore QCN (读取后重写入)/Auto preserve(不动这几个分区)
1.3、分区下载
使用partition manage读出的分区文件都是bin格式,load进去也必须是bin格式。
把其它设备的userdata数据刷入到其它同样设备,数据完全保留,可用。(userdebug调试user的数据,手机还是需要设置开机密码的)
使用fastboot命令刷机流程详解_Android小码农的博客-CSDN博客_fastboot
2.1、文件分析
android镜像分析已经提到。
2.2、fastboot命令
fastboot flash比较常用,刷指定分区命令类似于fastboot flash boot boot.img,下面几个命令可以了解下:
cmdline 有点长
core_ctl_disable_cpumask=0-7 kpti=0 console=ttyMSM0,115200,n8 androidboot.console=ttyMSM0 androidboot.hardware=qcom msm_rtb.filter=0x237 ehci-hcd.park=3 lpm_levels.sleep_disabled=1 androidboot.bootdevice=7824900.sdhci earlycon=msm_serial_dm,0x78af000 firmware_class.path=/vendor/firmware_mnt/image androidboot.usbconfigfs=true loop.max_part=7 buildvariant=userdebug androidboot.emmc=true androidboot.verifiedbootstate=orange androidboot.keymaster=1 dm="1 vroot none ro 1,0 4918112 verity 1 PARTUUID=1301d1c2-456f-1c8f-e1c1-1b435756052c PARTUUID=1301d1c2-456f-1c8f-e1c1-1b435756052c 4096 4096 614764 614764 sha1 2d97a9989b5bf9c8ae5263f2d88c40e34254210d 7e61282c660bf96ef462600a73a88471b5edab47 10 restart_on_corruption ignore_zero_blocks use_fec_from_device PARTUUID=1301d1c2-456f-1c8f-e1c1-1b435756052c fec_roots 2 fec_blocks 619606 fec_start 619606" root=/dev/dm-0 androidboot.vbmeta.device=PARTUUID=88b216e2-034a-fcbc-d3a5-6e06f26402da androidboot.vbmeta.avb_version=1.0 androidboot.vbmeta.device_state=unlocked androidboot.vbmeta.hash_alg=sha256 androidboot.vbmeta.size=4992 androidboot.vbmeta.digest=d434fe934f80dc3434a804980a8c13139b3a381a953778e7dd69c3190c7fcfa6 androidboot.veritymode=enforcing androidboot.serialno=0000000000 androidboot.baseband=msm mdss_mdp.panel=1:dsi:0:qcom,mdss_dsi_st7701s_tn_400p_video:1:none:cfg:single_dsi androidboot.slot_suffix=_a skip_initramfs root wait ro init=/init androidboot.dtbo_idx=0
这里再说几点:
fastboot oem *** 可以aboot中自定义命令而不用修改fastboot工具。
fastboot -w 是fastboot getvar获取容量后,生成userdata.img镜像,再write,这就与flash userdata其实差不多了。
fastboot -w有文件系统,fastboot erase userdata清空分区,后面这种进入system后识别userdata被擦,自动重启到recovery格式化userdata。
fastboot不支持读。
如果设备直接连到你的编译服务器,可以设置刷机路径,使用fastboot flashall命令(我们都是windows批处理来刷机)。
OTA升级制作主要两种包,全包和差分包(现在翻译为增量包)。android 6开始OTA按块升级,差分包也是按块对比。
通过target-file包制作OTA全包命令:
./build/tools/releasetools/ota_from_target_files ${source_zip} ${output_zip}
通过target-file包制作OTA差分包命令:
./build/tools/releasetools/ota_from_target_files -i ${source_zip} ${target_zip} ${output_zip}
ota_from_target_files更多参数可查看帮助。
如果target-file包含所有fastboot升级包的所有内容还可以制作fastboot升级包
unzip -q -o ${target_files_zip_name} IMAGES/vendor.img -d ${fastboot_out_tmp}/AP
***
***
***
unzip -q -o ${target_files_zip_name} IMAGES/system.img -d ${fastboot_out_tmp}/AP
unzip -q -o ${target_files_zip_name} IMAGES/modem.img -d ${fastboot_out_tmp}/MP
现在区分nonAB和AB的android系统,虽然制作命令相同,但它们OTA包里面文件的格式,升级流程有很大差异。
nonAB升级流程是recovery调用OTA包中的update-binary二进制执行程序,解析updater-script脚本,按该脚本流程升级。
官网https://source.android.com/devices/tech/ota/nonab详细了解nonAB的OTA升级流程的看下面这系列的blog比较好
Android OTA升级包制作脚本详解(一,参数解析)_高桐@BILL的博客-CSDN博客
system模式和recovery模式的文件系统不同,nonAB系统的recovery文件系统在recovery.img中,AB系统的recovery文件系统在boot.img中。执行程序在文件系统的sbin/recovery。
提示,如果是userdebug版本的recovery,可以挂载system使用adb。
3.1.1 nonAB系统的OTA文件分析
Android 4.4还是以文件方式升级,所以OTA包直接解压可以看到所有的文件。
Android 6.0以块方式升级,要刷的system内容在system.new.dat中,这里sdat2img.py先转换下,然后挂载即可。OTA包解压,如下
File *
boot.img: Android bootimg, kernel, ramdisk, page size: 2048, cmdline (console=ttyHSL0,115200,n8 androidboot.console=ttyHSL0 androidbo)
file_contexts.bin: data
firmware-update: directory
META-INF: directory
system.new.dat.br: data
system.patch.dat: empty
system.transfer.list: ASCII text
vendor.new.dat.br: data
vendor.patch.dat: empty
vendor.transfer.list: ASCII text
sdat2img.py system.transfer.list system.new.dat system.img
sdat2img binary - version: 1.0
Android Nougat 7.x / Oreo 8.x detected!
Skipping command erase...
Copying 1024 blocks into position 0...
Copying 1024 blocks into position 1024...
Copying 1024 blocks into position 2048...
Copying 1024 blocks into position 3072...
***
***
***
Copying 1 blocks into position 345084...
Copying 1 blocks into position 345086...
Skipping command zero...
***
Skipping command zero...
Done! Output image: /***/system.img
sudo mount system.img systemtest挂载查看
其中system.patch.dat这个是补丁文件,差分包才会使用。OTA包里面升级脚本执行程序在/META-INF/com/google/android/update-binary,升级脚本在/META-INF/com/google/android/updater-script。Android OTA升级原理和流程分析(一) --update.zip包的制作_发飙的IT宅男的博客-CSDN博客
3.1.2 recovery模式OTA包升级操作
方法1、adb sideload updater.zip通过USB线升级。
方法2、OTA包放入SD卡中升级
recovery是无法读取userdata里面数据去升级的,当然你可以把一个分区当作sdcardfs文件类型来使用,达到使用内部数据升级的目的(sdcardfs文件类型区别于system,media等类型,https://www.anquanke.com/vul/id/1344320有描述sdcardfs的权限提升漏洞)。
方法3、使用MISC分区传送指令升级
通过misc传送指令可以实现system上层的升级
下面是misc内数据分析
擦除数据 recovery\n--wipe_data
升级 recovery\n --update_package=/cache/some-filename.zip
工厂测试 FFBM-00(01/02)
3.1.3 升级工具update-binary分析
该工具update-binary由updater复制而来。updater源码在bootable\recovery\updater,编译出obj\EXECUTABLES\updater_intermediates\LINKED\updater后,再去掉一些信息转换成updater(LINKED下的updater可以通过nm -n 获取main函数起始位置,而最后得到的updater无法获取,android的可执行程序基本都如此)。下面是通过读取section(.text)去猜测main函数起始位置。(如果能直接得到,请赐教)下面开始反汇编:
file update-binary
update-binary: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), statically linked, BuildID[md5/uuid]=55f330750d82ac7c1d716cd1ce1968e5, stripped
aarch64-linux-androidkernel-readelf -a update-binary
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .note.android.ide NOTE 0000000000400158 00000158
0000000000000018 0000000000000000 A 0 0 4
[ 2] .note.gnu.build-i NOTE 0000000000400170 00000170
0000000000000020 0000000000000000 A 0 0 4
[ 3] .text PROGBITS 00000000004001c0 000001c0
00000000001332bc 0000000000000000 AX 0 0 64
[ 4] .rodata PROGBITS 0000000000533480 00133480
000000000004b200 0000000000000000 A 0 0 64
[ 5] .gcc_except_table PROGBITS 000000000057e680 0017e680
000000000000d404 0000000000000000 A 0 0 4
aarch64-linux-androidkernel-objdump -d update-binary –start-address=(.text)起始地址
00000000004001c0 <.text>:
4001c0: f81e0ff3 str x19, [sp,#-32]!
4001c4: a9017bfd stp x29, x30, [sp,#16]
4001c8: 910043fd add x29, sp, #0x10
4001cc: 2a0003f3 mov w19, w0
4001d0: 9404023c bl 0x500ac0
4001d4: aa1f03e0 mov x0, xzr
4001d8: 94040165 bl 0x50076c
***
***
***
400894: d65f03c0 ret
400898: d10743ff sub sp, sp, #0x1d0
40089c: a9176ffc stp x28, x27, [sp,#368]
4008a0: a91867fa stp x26, x25, [sp,#384]
4008a4: a9195ff8 stp x24, x23, [sp,#400]
4008a8: a91a57f6 stp x22, x21, [sp,#416]
4008ac: a91b4ff4 stp x20, x19, [sp,#432]
update_engine是AB系统升级工具。源码位置system/update_engine,其中 payload_consumer/delta_performer.cc中有限制升级的规则,包括检查时间戳,版本补丁等级等信息。
目前AB系统做法是不再使用recovery的UI界面,在恢复出厂时还是用到该模式。由于该模式系统不挂载system,vendor,userdata分区,可以进行格式化操作。(当然你可以再开recovery的UI,也可以update_engine_sideload中添加boot_ctrl的静态库来支持recovery的OTA升级)
3.2.1、AB系统的OTA文件分析
file *
care_map.txt: ASCII text
compatibility.zip: Zip archive data, at least v2.0 to extract
META-INF: directory
payload.bin: data
payload_properties.txt: ASCII text
payload_dumper和extract_android_ota_payload 可以解包其中的payload.bin文件
python3 payload_dumper.py payload.bin
file *
aboot.img: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, stripped
boot.img: Android bootimg, kernel, ramdisk, page size: 2048, cmdline (console=ttyMSM0,115200,n8 androidboot.console=ttyMSM0 androidbo)
cmnlib64.img: ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV), statically linked, stripped
cmnlib.img: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), statically linked, stripped
devcfg.img: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), statically linked, stripped
dsp.img: Linux rev 1.0 ext4 filesystem data, UUID=af32c008-2a39-7e5b-a5dc-201456d93103, volume name "dsp" (extents) (large files)
dtbo.img: data
keymaster.img: ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV), statically linked, stripped
lksecapp.img: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), statically linked, stripped
mdtp.img: data
modem.img: DOS/MBR boot sector, code offset 0x3c+2, OEM-ID "MSDOS5.0", sectors/cluster 32, root entries 512, Media descriptor 0xf8, sectors/FAT 22, sectors/track 63, heads 255, sectors 180224 (volumes > 32 MB) , serial number 0xbc614e, unlabeled, FAT (16 bit)
rpm.img: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, stripped
sbl1.img: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, stripped
system.img: Linux rev 1.0 ext2 filesystem data, UUID=4788ae58-ad4a-5bea-ae45-5b2f9b4368be (extents) (large files) (huge files)
tz.img: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), statically linked, stripped
vbmeta.img: data
vendor.img: Linux rev 1.0 ext2 filesystem data, UUID=5204afa9-c67d-5902-83ce-5a06b5cc26f1, volume name "vendor" (extents) (large files) (huge files)
xbl.img: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), statically linked, corrupted section header size
变成镜像后可以根据前面镜像分析去解析,这里几个sparse格式镜像都变成文件系统格式(Linux rev 1.0 ext2 filesystem data),因为制作的OTA包是按块刷写,不能使用sparse压缩格式,制作差分包也不能用sparse格式。
3.2.2、update_engine的使用
Android9.0系统OTA升级update_engine_-Ryan的博客-CSDN博客_applypayload请求升级
这种也相当于刷机,所有分区不要push压缩格式(system/vendor/userdata/persist分区不要push sparse格式)