recovery升级遇到的问题及其流程简单分析

这几天在测试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分区打包在一起即可。
欢迎关注我的个人主页,谢谢大家!

    原文作者:J_Coder
    原文地址: https://www.jianshu.com/p/1ebbdcb24d2f
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞