这几天在测试RK3288平台的recovery升级功能,测试的是打包生成的update.img升级镜像。经过多次测试发现以下问题,kernel部分的logo没被更新。一般情况下原厂recovery升级都是正常的,不过是为了更好地解决问题,也是趁着这个机会去了解下recovery下流程。
recovery相关部分的代码路径
${code_root}/bootable/recovery
${code_root}/bootable/recovery/recovery.cpp
${code_root}/bootable/recovery/rkimage.cpp
${code_root}/frameworks/base/core/java/android/os/RecoverySystem.java
根据串口跟踪升级流程
这里贴出我从串口上取下来的一些关键Log打印
I/ [File] : bootable/recovery/recovery.cpp; [Line] : 1408; [Func] : SetSdcardRootPath; InternalSD_ROOT: /mnt/internal_sd
I/ [File] : bootable/recovery/recovery.cpp; [Line] : 1410; [Func] : SetSdcardRootPath; ExternalSD_ROOT: /mnt/external_sd
failed to create /cache dir,err=File exists!
D/ [File] : bootable/recovery/recovery.cpp; [Line] : 2265; [Func] : main; to dump args befor get_args() :
1 argument(s) :
/sbin/recovery
D/ [File] : bootable/recovery/recovery.cpp; [Line] : 604; [Func] : get_args; to dump 'boot' :
command :
status :
recovery :
stage :
I/ [File] : bootable/recovery/recovery.cpp; [Line] : 655; [Func] : get_args; Got arguments from /cache/recovery/command
D/ [File] : bootable/recovery/recovery.cpp; [Line] : 2282; [Func] : main; to dump args after get_args() :
3 argument(s) :
/sbin/recovery
--update_rkimage=/mnt/usb_storage/USB_DISK2/udisk0/update.img
--locale=zh_CN
locale is [zh_CN]
stage is []
reason is [(null)]
Recovery system v5.0
I/ [File] : bootable/recovery/recovery.cpp; [Line] : 2379; [Func] : main; Recovery system v5.0, built at '15:49:43', on 'May 17 2016'.
failed to create /mnt/external_sd dir,err=File exists!
W/ [File] : bootable/recovery/roots.cpp; [Line] : 145; [Func] : ensure_path_mounted; trying mount /dev/block/mmcblk1p1 to ntfs
W/ [File] : bootable/recovery/roots.cpp; [Line] : 161; [Func] : ensure_path_mounted; trying mount /dev/block/mmcblk1 to ntfs
E:failed to mount /mnt/external_sd (No such device)
E/ [File] : bootable/recovery/roots.cpp; [Line] : 167; [Func] : ensure_path_mounted; failed to mount /mnt/external_sd (No such device)
delay 2sec
failed to create /mnt/external_sd dir,err=File exists!
W/ [File] : bootable/recovery/roots.cpp; [Line] : 145; [Func] : ensure_path_mounted; trying mount /dev/block/mmcblk1p1 to ntfs
W/ [File] : bootable/recovery/roots.cpp; [Line] : 161; [Func] : ensure_path_mounted; trying mount /dev/block/mmcblk1 to ntfs
E:failed to mount /mnt/external_sd (No such device)
E/ [File] : bootable/recovery/roots.cpp; [Line] : 167; [Func] : ensure_path_mounted; failed to mount /mnt/external_sd (No such device)
delay 2sec
read cmdline
Not enter sdboot!
failed to create /mnt/external_sd dir,err=File exists!
W/ [File] : bootable/recovery/roots.cpp; [Line] : 145; [Func] : ensure_path_mounted; trying mount /dev/block/mmcblk1p1 to ntfs
W/ [File] : bootable/recovery/roots.cpp; [Line] : 161; [Func] : ensure_path_mounted; trying mount /dev/block/mmcblk1 to ntfs
E:failed to mount /mnt/external_sd (No such device)
E/ [File] : bootable/recovery/roots.cpp; [Line] : 167; [Func] : ensure_path_mounted; failed to mount /mnt/external_sd (No such device)
failed to create /metadata dir,err=File exists!
[ 10.900450] EXT4-fs (mmcblk0p12): mounted filesbotem with ordc ed dmta mo e. Opts:
very" "--update_rkimage=/mnt/usb_storage/USB_DISK2/udisk0/update.img" "--locale=zh_CN"
findPackageAndMountUsbDevice : searchFile = /mnt/usb_storage/update.img
/dev/block/.
/dev/block/..
/dev/block/sda1
try to mount usb device at /dev/block/sda1 by vfat[ 10.934452] FAT-fs (sda1): Volume was not properly unmounted. Some uab updateepackage..
I/ [File] : bootable/recovery/recovery.cpp; [Line] : 2517; [Func] : main; to install rk_img : /mnt/usb_storage/update.img.
Finding update package...
=== UPDATE RKIMAGE===
Find and check firmware...
I/ [File] : bootable/recovery/rkimage.cpp; [Line] : 1286; [Func] : find_update_img; Update location: /mnt/usb_storage/update.img
the path is already mounted!
I/ [File] : bootable/recovery/rkimage.cpp; [Line] : 1293; [Func] : find_update_img; Update file path: /mnt/usb_storage/update.img
I/ [File] : bootable/recovery/rkimage.cpp; [Line] : 514; [Func] : CheckImageFile; Local model: rk3288_box
Update model: rk3288_box
I/ [File] : bootable/recovery/rkimage.cpp; [Line] : 521; [Func] : CheckImageFile; Checking...
I/ [File] : bootable/recovery/rkimage.cpp; [Line] : 361; [Func] : check_image_crc; Check crc okay.
I/ [File] : bootable/recovery/rkimage.cpp; [Line] : 1924; [Func] : install_rkimage; g_package_target=/mnt/usb_storage/update.img
!!! Please KEEP your USB cable or DC-in connected !!!
E:unknown volume for path [RU_PARTITION_MOUNT_PATH]
E/ [File] : bootable/recovery/roots.cpp; [Line] : 93; [Func] : ensure_path_mounted; unknown volume for path [RU_PARTITION_MOUNT_PATH]
E:unknown volume for path [SYSTEM_PARTITION_MOUNT_PATH]
E/ [File] : bootable/recovery/roots.cpp; [Line] : 93; [Func] : ensure_path_mounted; unknown volume for path [SYSTEM_PARTITION_MOUNT_PATH]
Update boot.img...
I/ [File] : bootable/recovery/rkimage.cpp; [Line] : 812; [Func] : write_image; src=boot dest=/boot offset=0
I/ [File] : bootable/recovery/rkimage.cpp; [Line] : 839; [Func] : write_image; dest isFile: 0
Check boot.img...
I/ [File] : bootable/recovery/rkimage.cpp; [Line] : 1086; [Func] : image_compare; src=boot dest=/boot offset=0
Update resource.img...
I/ [File] : bootable/recovery/rkimage.cpp; [Line] : 812; [Func] : write_image; src=resource dest=/resource offset=0
I/ [File] : bootable/recovery/rkimage.cpp; [Line] : 839; [Func] : write_image; dest isFile: 0
Check resource.img...
I/ [File] : bootable/recovery/rkimage.cpp; [Line] : 1086; [Func] : image_compare; src=resource dest=/resource offset=0
Update uboot.img...
I/ [File] : bootable/recovery/rkimage.cpp; [Line] : 812; [Func] : write_image; src=uboot dest=/uboot offset=0
E:Can't find uboot
E/ [File] : bootable/recovery/rkimage.cpp; [Line] : 819; [Func] : write_image; Can't find uboot
no uboot.img so ignore
Update trust.img...
I/ [File] : bootable/recovery/rkimage.cpp; [Line] : 812; [Func] : write_image; src=trust dest=/trust offset=0
E:Can't find trust
E/ [File] : bootable/recovery/rkimage.cpp; [Line] : 819; [Func] : write_image; Can't find trust
no trust.img so ignore
Update system...
I/ [File] : bootable/recovery/rkimage.cpp; [Line] : 812; [Func] : write_image; src=system dest=/system offset=0
E:Can't find system
E/ [File] : bootable/recovery/rkimage.cpp; [Line] : 819; [Func] : write_image; Can't find system
no boot.img so ignore
Update backup...
I/ [File] : bootable/recovery/rkimage.cpp; [Line] : 812; [Func] : write_image; src=backup dest=/backup offset=0
I/ [File] : bootable/recovery/rkimage.cpp; [Line] : 839; [Func] : write_image; dest isFile: 0
Check backup...
I/ [File] : bootable/recovery/rkimage.cpp; [Line] : 1086; [Func] : image_compare; src=backup dest=/backup offset=0
Update recovery.img...
I/ [File] : bootable/recovery/rkimage.cpp; [Line] : 812; [Func] : write_image; src=recovery dest=/recovery offset=0
I/ [File] : bootable/recovery/rkimage.cpp; [Line] : 839; [Func] : write_image; dest isFile: 0
Check recovery...
I/ [File] : bootable/recovery/rkimage.cpp; [Line] : 1086; [Func] : image_compare; src=recovery dest=/recovery offset=0
I/ [File] : bootable/recovery/rkimage.cpp; [Line] : 1496; [Func] : handle_update_script; Read script
I/ [File] : bootable/recovery/rkimage.cpp; [Line] : 1512; [Func] : handle_update_script; Parse the script
line 3 col 58: syntax error, unexpected STRING, expecting $end
E:1 parse errors
E/ [File] : bootable/recovery/rkimage.cpp; [Line] : 1519; [Func] : handle_update_script; 1 parse errors
handle script error! ignore...
copy Bootloader...
I/ [File] : bootable/recovery/rkimage.cpp; [Line] : 612; [Func] : write_loader; src=bootloader dest=/misc offset=49152
I/ [File] : bootable/recovery/rkimage.cpp; [Line] : 662; [Func] : write_loader; dest isFile: 0
Installation complete.
I/ [File] : bootable/recovery/recovery.cpp; [Line] : 2522; [Func] : main; to wipe /data.
Formatting /data...
Creating filesystem with parameters:
Size: 1073741824
Block size: 4096
Blocks per group: 32768
Inodes per group: 8192
Inode size: 256
Journal blocks: 4096
Label:
Blocks: 262144
Block groups: 8
Reserved block group size: 63
Created filesystem with 11/65536 inodes and 8536/262144 blocks
I/ [File] : bootable/recovery/recovery.cpp; [Line] : 821; [Func] : finish_recovery; Saving locale "zh_CN"
Rebooting...
[ 16.647164] SysRq : Emergency Remount R/O
[ 16.649590] EXT4-fs (mmcblk0p12): re-mounted. Opts: (null)
[ 16.651388] Emergency Remount complete
[ 16.747856] cpufreq: cpufreq: reboot set core rate=1200000000, volt=1100000
[ 16.748050] mmcblk mmc0:0001: Unbalanced pm_runtime_enable!
[ 17.358818] dwc_otg_driver_shutdown: disconnect USB device mode
[ 17.366720] Restarting system with command ''.
DDR Version 1.00 20150318
根据Log输出你可以对Recovery的升级过程有大体的了解,针对update.img的升级这里主要涉及recovery.cpp和rkimage.cpp,recovery.cpp是进入recovery升级调用的入口,rkimage.cpp是对update.img进行拆包升级的。这里想说明的是Log是很好帮助你分析流程和问题的工具,多对Log进行分析对你解决问题。
简单分析应用上层如何进入recovery升级
要想recovery工作,需要往”/cache/recovery/command”这个节点写命令,在Log我们可以发现如下参数,包括升级包的路径和本地语言。
I/ [File] : bootable/recovery/recovery.cpp; [Line] : 655; [Func] : get_args; Got arguments from /cache/recovery/command
D/ [File] : bootable/recovery/recovery.cpp; [Line] : 2282; [Func] : main; to dump args after get_args() :
3 argument(s) :
/sbin/recovery
--update_rkimage=/mnt/usb_storage/USB_DISK2/udisk0/update.img
--locale=zh_CN
locale is [zh_CN]
stage is []
reason is [(null)]
这些参数如何通过上层应用写给/cache/recovery/command节点的,这里可以参考android.os.RecoverySystem这个类里面的相关方法。
那recovery里面有哪些可以操作的参数呢,相关的命令可以在recovery.cpp中找到声明。
static const struct option OPTIONS[] = {
{ "factory_mode", required_argument, NULL, 'f' },
{ "send_intent", required_argument, NULL, 's' },
{ "update_package", required_argument, NULL, 'u' },
{ "update_rkimage", required_argument, NULL, 'k' }, // support rkimage to update
{ "radical_update_package", required_argument, NULL, 'z' }, // to support ru_pkg to update
{ "wipe_data", no_argument, NULL, 'w' },
{ "wipe_cache", no_argument, NULL, 'c' },
{ "show_text", no_argument, NULL, 't' },
{ "wipe_all", no_argument, NULL, 'w'+'a' },
{ "just_exit", no_argument, NULL, 'x' },
{ "locale", required_argument, NULL, 'l' },
{ "stages", required_argument, NULL, 'g' },
{ "shutdown_after", no_argument, NULL, 'p' },
{ "fw_update", required_argument, NULL, 'f'+'w' },
{ "demo_copy", required_argument, NULL, 'd' },
{ "reason", required_argument, NULL, 'r' },
{ NULL, 0, NULL, 0 },
};
转换的过程读者可以看下recovery.cpp的main方法,这里就不贴代码了,通过传入参数,recovery会作出选择,本次是升级还是还原操作,是否擦除分区等等。至此上层应用到recovery的过程基本理清。
无法升级logo的问题的解决
RK3288平台的开机Logo是打包在resource.img中的,在生成镜像时会把resource.img打包到boot.img中,代码中是确实对boot.img中进行升级了。那么问题出在哪里呢?明明升级了但是却没有效果。
此时我注意到一个打印数据如下
bootmode = emmc
recovery filesystem table
=========================
0 /mnt/internal_sd vfat /dev/block/platform/ff0f0000.rksdmmc/by-name/user 0
1 /mnt/external_sd vfat /dev/block/mmcblk1p1 0
2 /system ext4 /dev/block/platform/ff0f0000.rksdmmc/by-name/system 0
3 /cache ext4 /dev/block/platform/ff0f0000.rksdmmc/by-name/cache 0
4 /metadata ext4 /dev/block/platform/ff0f0000.rksdmmc/by-name/metadata 0
5 /data ext4 /dev/block/platform/ff0f0000.rksdmmc/by-name/userdata 0
6 /cust ext4 /dev/block/platform/ff0f0000.rksdmmc/by-name/cust 0
7 /custom ext4 /dev/block/platform/ff0f0000.rksdmmc/by-name/custom 0
8 /radical_update ext4 /dev/block/platform/ff0f0000.rksdmmc/by-name/radical_update 0
9 /misc emmc /dev/block/platform/ff0f0000.rksdmmc/by-name/misc 0
10 /uboot emmc /dev/block/platform/ff0f0000.rksdmmc/by-name/uboot 0
11 /charge emmc /dev/block/platform/ff0f0000.rksdmmc/by-name/charge 0
12 /resource emmc /dev/block/platform/ff0f0000.rksdmmc/by-name/resource 0
13 /parameter emmc /dev/block/platform/ff0f0000.rksdmmc/by-name/parameter 0
14 /boot emmc /dev/block/platform/ff0f0000.rksdmmc/by-name/boot 0
15 /recovery emmc /dev/block/platform/ff0f0000.rksdmmc/by-name/recovery 0
16 /backup emmc /dev/block/platform/ff0f0000.rksdmmc/by-name/backup 0
17 /tmp ramdisk ramdisk 0
resource也是有分区,是不是resource.img也需要单独升级呢?带着这样的的疑问,我做了下实验,在rkimage.cpp的install_rkimage方法添加升级resource.img的处理(如下),实验结论就是开机logo可以被更新了。
ui->Print("Update resource.img...\n");
result = write_image("resource", "/resource", 0);
if(result == -4) {
//some times, we not want to boot every time;
ui->Print("no resource.img so ignore\n");
}else if(result == 0) {
ui->Print("Check resource.img...\n");
result = image_compare("resource", "/resource", 0);
if(result) {
ui->Print("Failed(%d)\n", result);
goto update_error;
}
}else {
ui->Print("Failed(%d)\n", result);
goto update_error;
}
问题原因及结论:在工厂升级的时候把resource.img作为一个分区升级到板卡上了,后续如果想更新开机logo必须要把该分区更新。另外的解决办法就是resource.img分区不作为一个分区更新到板卡,和boot.img分区打包在一起即可。
欢迎关注我的个人主页,谢谢大家!