程序项目代做,有需求私信(小程序、网站、爬虫、电路板设计、驱动、应用程序开发、毕设疑难问题处理等)

Rockchip RK3588 - Rockchip Linux Recovery updateEngine测试

----------------------------------------------------------------------------------------------------------------------------

开发板 :ArmSoM-Sige7开发板
eMMC64GB
LPDDR48GB
显示屏 :15.6英寸HDMI接口显示屏
u-boot2017.09
linux5.10
----------------------------------------------------------------------------------------------------------------------------

在《Rockchip RK3588 - Rockchip Linux Recovery updateEngine源码分析》中我们已经对updateEngine源码的来龙去脉做了详细的介绍,本节将会介绍如何使用updateEngine进行固件的升级。

一、制作系统镜像

首先我们需要将我们制作的统一固件update.img(这里以buildroot系统为例)烧录到开发板eMMC中,具体烧录步骤可以参考《Rockchip RK3588 - Rockchip Linux SDK编译》。

制作统一固件update.img有多种方式:

  • 采用 ./build.sh all进行一键全自动编译(包含了ubootkernel等):
  • 按模块进行编译;

由于《Rockchip RK3588 - Rockchip Linux SDK编译》中我们已经编译了ubootkernelrootfs等模块,因此在这里我们采用按模块编译的方式重新编译rootfsrecovery,具体步骤如下文所述。

1.1 buildroot编译

这里我们使用buildroot系统,在SDK根目录下执行如下命令重新编译生成rootfs.ext2

root@ubuntu:/work/sambashare/rk3588/armsom/armsom-rk3588-bsp# sudo ./build.sh buildroot

编译使用的配置项是rockchip_rk3588_defconfig的配置,其配置项远远多余rockchip_rk3588_recovery_defconfig的配置;

#include "base/base.config"
#include "chips/rk3588_aarch64.config"
#include "font/chinese.config"
#include "fs/exfat.config"
#include "fs/ntfs.config"
#include "fs/vfat.config"
#include "gpu/gpu.config"
#include "multimedia/audio.config"
#include "multimedia/camera.config"
#include "multimedia/gst/audio.config"
#include "multimedia/gst/camera.config"
#include "multimedia/gst/rtsp.config"
#include "multimedia/gst/video.config"
#include "multimedia/mpp.config"
#include "wifibt/bt.config"
#include "wifibt/wireless.config"
#include "benchmark.config"
#include "chromium.config"
#include "debug.config"
#include "npu2.config"
#include "powermanager.config"
#include "test.config"
#include "weston.config"

编译后在buildroot/output/rockchip_rk3588/images下生成不同格式的镜像, 默认使用rootfs.ext2文件;

root@ubuntu:/work/sambashare/rk3588/armsom/armsom-rk3588-bsp/buildroot$ ll  output/rockchip_rk3588/images/
-rw-r--r-- 1 root root 615688192  6月 25 00:51 rootfs.cpio
-rw-r--r-- 1 root root 273879343  6月 25 00:52 rootfs.cpio.gz
-rw-r--r-- 1 root root 761266176  6月 25 00:52 rootfs.ext2
lrwxrwxrwx 1 root root        11  6月 25 00:52 rootfs.ext4 -> rootfs.ext2
-rw-r--r-- 1 root root 275013632  6月 25 00:52 rootfs.squashfs
-rw-r--r-- 1 root root 624496640  6月 25 00:52 rootfs.tar

可以看到编译出来的rootfs.ext2700M+

编译出来的rootfs.ext2仅仅包含updateEngine可执行文件。

1.2 recovery编译

SDK根目录下执行如下命令重新编译生成recovery.img

root@ubuntu:/work/sambashare/rk3588/armsom/armsom-rk3588-bsp# sudo ./build.sh recovery

编译后在buildroot/output/rockchip_rk3588_recovery/images/目录下生成recovery.img

root@ubuntu:/work/sambashare/rk3588/armsom/armsom-rk3588-bsp/buildroot$ ll  output/rockchip_rk3588_recovery/images/
-rw-r--r-- 1 root root 44336128  6月 18 01:48 recovery.img
-rw-r--r-- 1 root root 15856640  6月 18 01:48 rootfs.cpio
-rw-r--r-- 1 root root  6713449  6月 18 01:48 rootfs.cpio.gz
-rw-r--r-- 1 root root 43342848  6月 18 01:48 rootfs.ext2
lrwxrwxrwx 1 root root       11  6月 18 01:48 rootfs.ext4 -> rootfs.ext2
-rw-r--r-- 1 root root  6676480  6月 18 01:48 rootfs.squashfs
-rw-r--r-- 1 root root 16947200  6月 18 01:48 rootfs.tar

可以看到编译出来的recovery.img40M+

编译出来的recovery.img包含用于升级的updateEnginerkupdate可执行文件;

1.3 打包

1.3.1 打包分区镜像

执行以下命令更新output/firmware/下各个分区镜像;

root@ubuntu:/work/sambashare/rk3588/armsom/armsom-rk3588-bsp$ sudo ./build.sh firmware

如果recovery.img文件不存在,创建recovery.img链接文件指向buildroot/output/rockchip_rk3588_recovery/images/recovery.img

如果rootfs.img文件不存在,创建recovery.img链接文件指向buildroot/output/rockchip_rk3588_recovery/images/rootfs.ext2

1.3.2 打包统一固件

执行如下命令重新生成统一固件;

root@ubuntu:/work/sambashare/rk3588/armsom/armsom-rk3588-bsp$ sudo ./build.sh updateimg

编译会生成统一镜像update.img,位于output/update/update目录.

如果output/firmware/update.img文件不存在,创建output/firmware/update.img链接文件指向output/update/Image/update.img

1.4 烧录测试

将统一固件update.img烧录到开发板中,系统启动后,我们查看文件系统中的updateEngine

root@rk3588-buildroot:~# ls /usr/bin/updateEngine -l
-rwxr-xr-x 1 root root 3100260  6月  9 12:58 buildroot/output/rockchip_rk3588/target/usr/bin/updateEngine

如果你研究过rockchip_rk3588_defconfig,你会发现builroot编译的板载配置rockchip_rk3588_defconfig并没有配置updateEngine/rkupdate升级方式,那这些文件是哪里来的呢?

这个是由./build.sh buildroot脚本实现的,其从device/rockchip/common/tools/armhf/位置将updateEngine拷贝到buildroot/output/rockchip_rk3588/target/usr/bin目录下,该文件采用的是静态链接方式(其原因是buildroot系统并没有安装该程序运行所依赖的动态库)。

这里我们可以使用官方提供的updateEngine(需要注意的是官方提供的并不会输出日志信息),当然在一些场景下我们可能需要自己编译updateEngine

1.4.1 使用recovery.img中的updateEngine

我们将recovery编译得到的updateEngine复制到/work/tftpwork目录下:

root@ubuntu:/work/sambashare/rk3588/armsom/armsom-rk3588-bsp$ cp buildroot/output/rockchip_rk3588_recovery/target/usr/bin/updateEngine /work/tftpboot/

系统运行后, 这里我们将updateEngine替换成我们编译的updateEngine

root@rk3588-buildroot:/userdata# tftp -g -l updateEngine 192.168.0.200
root@rk3588-buildroot:/userdata# chmod +x updateEngine
root@rk3588-buildroot:/userdata# mv updateEngine /usr/bin
root@rk3588-buildroot:/userdata# updateEngine --h
./updateEngine: error while loading shared libraries: libcurl.so.4: cannot open shared object file: No such file or directory

可以看到该程序是无法直接运行了,因为其依赖了curl等库,在buildroot编译并没有安装安装相关依赖。

1.4.2 重新编译updateEngine

我们直接进入updateEngine源码所在路径,复制一份源码命名为recovery_bak

root@ubuntu:/work/sambashare/rk3588/armsom/armsom-rk3588-bsp/external$ sudo cp -r recovery recovery_bak

创建文件recovery_autogenerate.h

#define GIT_COMMIT_INFO -g28f720bc5-240524-dirty

修改Makefile

%.o: %.c  recovery_version
        $(CC) -c $< -o $@ $(CFLAGS)
# 修改为
%.o: %.c   # recovery_version
        $(CC) -c $< -o $@ $(CFLAGS)

执行如下代码;

root@ubuntu:/work/sambashare/rk3588/armsom/armsom-rk3588-bsp/external/recovery_bak$ sudo make updateEngine CC="/work/sambashare/rk3588/armsom/armsom-rk3588-bsp/buildroot/output/rockchip_rk3588_recovery/host/bin/aarch64-buildroot-linux-gnu-gcc"  CFLAGS="-D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64  -Os -g0 -D_FORTIFY_SOURCE=1 -I. -fPIC -lpthread -lcurl -lssl -lcrypto -lbz2 -DUSE_UPDATEENGINE=ON -DSUCCESSFUL_BOOT=ON"

注意:这里关闭了RecoveryNoUi配置,为了减少一下依赖的库(pngdrmbm等)。此处编译我们采用的是动态链接,当然我们也可以制作libcurl.alibbz2.a静态库,采用静态链接编译updateEngine程序。

编译完成会在当前路径生成updateEngine

root@ubuntu:/work/sambashare/rk3588/armsom/armsom-rk3588-bsp/external/recovery_bak$ file updateEngine
updateEngine: ELF 64-bit LSB pie executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, for GNU/Linux 3.7.0, not stripped

使用objdump命令查看库依赖:

zhengyang@ubuntu:/work/sambashare/rk3588/armsom/armsom-rk3588-bsp/external/recovery_bak$ objdump -p updateEngine | grep NEEDED
  NEEDED               libcurl.so.4                  # buildroot系统未安装
  NEEDED               libssl.so.1.1                 # buildroot系统已有
  NEEDED               libcrypto.so.1.1              # buildroot系统已有
  NEEDED               libbz2.so.1.0                 # buildroot系统未安装 
  NEEDED               libc.so.6                     # buildroot系统已有
  NEEDED               ld-linux-aarch64.so.1         # buildroot系统已有  

接下来我们依次安装这些依赖(这些库我们直接从recovery文件系统查找就好),这里在宿主机开启一个http服务:

root@ubuntu:/work/sambashare/rk3588/armsom/armsom-rk3588-bsp/buildroot/output/rockchip_rk3588_recovery/target$ python -m http.server 8080

下载动态库到开发板buildroot系统:

root@rk3588-buildroot:/usr/lib64# cd /usr/lib64
# 安装libcurl.so.4.7.0
root@rk3588-buildroot:/usr/lib64# wget http://192.168.0.200:8080/usr/lib64/libcurl.so.4.7.0
root@rk3588-buildroot:/usr/lib64# ln -s libcurl.so.4.7.0 libcurl.so
root@rk3588-buildroot:/usr/lib64# ln -s libcurl.so.4.7.0 libcurl.so.4
# 安装libbz2.so
root@rk3588-buildroot:/usr/lib64# wget http://192.168.0.200:8080/usr/lib64/libbz2.so.1.0.8
root@rk3588-buildroot:/usr/lib64# ln -s libbz2.so.1.0.8 libbz2.so
root@rk3588-buildroot:/usr/lib64# ln -s libbz2.so.1.0.8 libbz2.so.1.0
# 安装libssl.so
root@rk3588-buildroot:/usr/lib64# wget http://192.168.0.200:8080/usr/lib64/libbz2.so.1.0.8
root@rk3588-buildroot:/usr/lib64# ln -s libbz2.so.1.0.8 libbz2.so
root@rk3588-buildroot:/usr/lib64# ln -s libbz2.so.1.0.8 libbz2.so.1.0
1.4.3 查看帮助命令

我们将重新编译得到的updateEngine拷贝到userdata,再次执行updateEngine程序:

root@rk3588-buildroot:/userdata# updateEngine --h
LOG_INFO: *** update_engine: V1.0.1-g28f720bc5-240524-dirty ***.
LOG_INFO: --misc=now             Linux A/B mode: Setting the current partition to bootable.
LOG_INFO: --misc=other           Linux A/B mode: Setting another partition to bootable.
LOG_INFO: --misc=update          Recovery mode: Setting the partition to be upgraded.
LOG_INFO: --misc=display         Display misc info.
LOG_INFO: --misc=wipe_userdata   Format data partition.
LOG_INFO: --misc_custom= < op >  Operation on misc for custom cmdlineLOG_INFO:         op:     read   Read custom cmdline to /tmp/custom_cmdlineLOG_INFO:                 write  Write /tmp/custom_cmdline to custom areaLOG_INFO:                 clean  clean custom areaLOG_INFO: --update               Upgrade mode.
LOG_INFO: --partition=0x3FFC00   Set the partition to be upgraded.(NOTICE: OTA not support upgrade loader and parameter)
LOG_INFO:                        0x3FFC00: 0011 1111 1111 1100 0000 0000.
LOG_INFO:                                  uboot trust boot recovery rootfs oem
LOG_INFO:                                  uboot_a uboot_b boot_a boot_b system_a system_b.
LOG_INFO:                        100000000000000000000000: Upgrade loader
LOG_INFO:                        010000000000000000000000: Upgrade parameter
LOG_INFO:                        001000000000000000000000: Upgrade uboot
LOG_INFO:                        000100000000000000000000: Upgrade trust
LOG_INFO:                        000010000000000000000000: Upgrade boot
LOG_INFO:                        000001000000000000000000: Upgrade recovery
LOG_INFO:                        000000100000000000000000: Upgrade rootfs
LOG_INFO:                        000000010000000000000000: Upgrade oem
LOG_INFO:                        000000001000000000000000: Upgrade uboot_a
LOG_INFO:                        000000000100000000000000: Upgrade uboot_b
LOG_INFO:                        000000000010000000000000: Upgrade boot_a
LOG_INFO:                        000000000001000000000000: Upgrade boot_b
LOG_INFO:                        000000000000100000000000: Upgrade system_a
LOG_INFO:                        000000000000010000000000: Upgrade system_b
LOG_INFO:                        000000000000001000000000: Upgrade misc
LOG_INFO:                        000000000000000100000000: Upgrade userdata
LOG_INFO: --reboot               Restart the machine at the end of the program.
LOG_INFO: --version_url=url      The path to the file of version.
LOG_INFO: --image_url=url        Path to upgrade firmware.
LOG_INFO: --savepath=url         save the update.img to url.
LOG_INFO: --version              the version of updateEngine
LOG_INFO: --rkdebug              Log output to serial port
LOG_INFO: --ui_rotation          UI rotation,has 4 angles(0-3).

可以看到updateEngine支持的命令参数。

二、 制作升级镜像

按照正常的固件编译流程,制作用于升级的update.img固件,可以参考《Rockchip RK3588 - Rockchip Linux SDK编译》。

升级固件不一定要全分区升级,可修改 package-file 文件,将不要升级的分区去掉,这样可以减少升级包的大小。

例如,执行如下命令(可参考文件tools/linux/Linux_Pack_Firmware/rockdev/rk3588-package-file):

root@ubuntu:/work/sambashare/rk3588/armsom/armsom-rk3588-bsp$ sudo ./build.sh edit-package-file

backup的相对路径改为 RESERVED,这样就不会backup.img,即不升级backup分区。

# NAME  PATH
package-file    package-file
parameter       parameter.txt
bootloader      MiniLoaderAll.bin
uboot   uboot.img
misc    misc.img
boot    boot.img
recovery        recovery.img
backup  RESERVED
rootfs  rootfs.img
oem     oem.img
userdata  userdata.img

注意: 若将升级固件放至设备的/userdata/目录,则不要升级userdata分区;我们可以不对userdata.img进行打包,将userdata.img改为RESERVED即可。

执行如下命令生成统一固件;

root@ubuntu:/work/sambashare/rk3588/armsom/armsom-rk3588-bsp$ sudo ./build.sh updateimg

将制作好的升级固件拷贝到U盘、TF卡或者开发版的/userdata/目录下。

我们可以将统一镜像复制到/work/tftpwork目录下:

root@ubuntu:/work/sambashare/rk3588/armsom/armsom-rk3588-bsp$ cp ./rockdev/update.img /work/tftpboot/

三、buildroot系统升级

OTAOver-the-Air)即空间下载技术。 OTA升级是Android系统提供的标准软件升级方式。它功能强大,可以无损失升级系统,主要通过网络,例如WIFI3G/4G/5G自动下载OTA升级包、自动升级,也支持通过下载OTA升级包到SD卡/U盘升级,OTA的升级包非常的小,一般几MB到十几MB

本节主要介绍了使用OTA技术升级时,本地升级程序updateEngine/rkupdate执行升级的流程及技术细节,以便用户在开发过程中了解升级的过程及注意事项。

3.1 updateEngine升级命令

3.1.1 升级流程

updateEngine升级流程如下:

  • 固件版本比较(--version_url);
  • 下载固件(--image_url),并保存到本地(--savepath);
  • normal系统下升级recovery分区;
  • 重启,进入recovery系统,升级其它分区(--partition);
  • 升级成功,重启进入normal系统。

这里有一点需要补充,如果我们指定了需要升级的分区,并且需要升级的分区中没有recovery分区,那么会在normal系统下升级所有分区;换句话说只有需要升级的分区中包含了recovery分区,那么升级过程才会包含上述步骤的第三部、第四步。

因此在升级指定升级分区时一定要指定recovery分区,这样才会进入recovery系统烧录除了recovery之外的分区;

  • 如果没有指定recovery分区,那么将会在normal系统进行烧录,存在诸多风险,比如:升级中断导致normal系统无法正常启动;
  • 而在recovery系统进行升级能保证升级的完整性,即升级过程被中断,如异常掉电,升级仍然能继续执行;

注意:除此之外,我们还需要注意一点,不可以升级升级固件update.img存放的分区,因为这样存在覆盖的问题。比如我们如果将升级固件放在/userdata目录,就不要升级userdata分区。

3.1.2 升级命令

升级支持网络下载和本地升级,且可指定要升级的分区,在normal系统运行如下命令:

网络升级:

updateEngine --image_url=http://192.168.0.200:8080/recovery/update.img --misc=update --savepath=/userdata/update.img --reboot

本地升级:

updateEngine --image_url=/userdata/update.img --misc=update --savepath=/userdata/update.img --reboot

可缺省参数:

  • --version_url:如果有传入路径,升级之前会与/etc/version文件中的RK_VERSION= 版本值进行比较;
    • 本地路径:从固件中读取版本号;
    • 远程路径:从远程下载版本文件,远程版本文件格式必须跟/etc/version一致;
  • --image_url:设置升级固件的路径,可为远程或本地路径;
  • --savepath:固件保存地址,如果没有传入且升级的固件路径为远程地址则默认值为/tmp/update.img,建议传入/userdata/update.img
  • --misc
    • nowLinux A/B mode: Setting the current partition to bootable,即Linux A/B模式,将当前分区设置为可引导分区;
    • otherLinux A/B mode: Setting another partition to bootable,即Linux A/B模式,将另外一个分区设置为升级完成分区,重启之后会尝试从另外一个分区引导;
    • updateRecovery mode: Setting the partition to be upgraded,供recovery模式使用,在normal系统升级recovery分区,在recovery 系统升级其余分区;
    • displayDisplay misc info,输出misc信息;
    • wipe_userdataFormat data partition
  • --partition:设置将要升级的分区,比如uboottrustbootrecoveryrootfsoem等;
    • 如果没有传入要升级的分区,在recovery模式默认升级uboot/trust/boot/recovery/rootfs/oempartition=0x3F0000
    • 如果指定了parametermiscparametermisc分区会自动忽略;
    • 如果升级uboot分区,指定partition=0x200000
    • 如果升级trust分区,指定partition=0x100000
    • 如果升级boot分区,指定partition=0x80000
    • 如果升级recovery分区,指定partition=0x40000
    • 如果升级rootfs分区,指定partition=0x20000
    • 如果升级oem分区,指定partition=0x10000
    • 如果升级misc分区,指定partition=0x200
    • 如果升级userdata分区,指定partition=0x100
  • --updateUpgrade mode
  • --reboot:升级完成后重启。

更多参数可以通过updateEngine --h查看。

3.2 updateEngine升级测试

3.2.1 网络升级测试

我们可以在ubunut开启http服务,搭建一个web服务;

root@ubuntu:/work/sambashare/rk3588/armsom/armsom-rk3588-bsp# python -m http.server 8080

然后执行updateEngine网络升级命令;

root@rk3588-buildroot:/# updateEngine --image_url=http://192.168.0.200:8080/output/update/Image/update.img --misc=update --savepath=/userdata/update.img --reboot

由于没有传入要升级的分区,在recovery模式会升级uboot、boot、recovery、rootfs、oem这5个分区。;

3.2.2 normal系统下升级日志

首先在normal系统下升级recovery分区,输出日志如下;

点击查看代码
LOG_INFO: *** update_engine: V1.0.1-g28f720bc5-240524-dirty ***.
LOG_INFO: Current Mode is recovery.
# 1 MiscUpdate->RK_ota_set_url
LOG_INFO: start RK_ota_url url [http://192.168.0.200:8080/output/update/Image/update.img] save path [/userdata/update.img].
LOG_INFO: save image to /userdata/update.img.
LOG_INFO: url = http://192.168.0.200:8080/output/update/Image/update.img.
LOG_INFO: [MiscUpdate:90] save path: /userdata/update.img
# 在normal系统,升级recovery分区
LOG_INFO: update recovery in normal system.
# 2. MiscUpdate -> RK_ota_set_partition(0x040000): 遍历升级命令数组,对需要执行的升级命令打标记(parameter、recovery)
LOG_INFO: [RK_ota_set_partition:106] num [16]
LOG_INFO: need update parameter.
LOG_INFO: need update recovery.
LOG_INFO: Current device is not MTD
# 3. MiscUpdate -> RK_ota_start: 对命令数组update_cmd中打了标记的命令所指向的分区进行升级
LOG_INFO: start RK_ota_start.
# 3.1 RK_ota_start -> download_file(_url, _save_path): 函数从_url下载升级固件,文件下载成功设置_url=_save_path;
LOG_INFO: rk m_status = 1.
LOG_INFO: down_processvalue is 0%
LOG_INFO: down_processvalue is 1%
LOG_INFO: down_processvalue is 2%
LOG_INFO: down_processvalue is 3%
LOG_INFO: down_processvalue is 4%
LOG_INFO: down_processvalue is 5%
LOG_INFO: down_processvalue is 6%
......
LOG_INFO: down_processvalue is 96%
LOG_INFO: down_processvalue is 97%
LOG_INFO: down_processvalue is 98%
LOG_INFO: down_processvalue is 99%
LOG_INFO: down_processvalue is 100%
# 3.2 RK_ota_start -> RK_ota_set_partition(-1): 获取升级固件的信息,输出固件update.img头信息、原始固件update.raw.img头信息
LOG_INFO: [RK_ota_set_partition:106] num [16]
LOG_DEBUG: uiTag = 57464b52.                      # 固件update.img头信息 标志  16进制输出     
LOG_DEBUG: usSize = 66.
LOG_DEBUG: dwVersion = 1000000.
LOG_DEBUG: btMajor = 1, btMinor = 0, usSmall = 00.
LOG_DEBUG: dwBootOffset = 66.
LOG_DEBUG: dwBootSize = 731c0.
LOG_DEBUG: dwFWOffset = 73226.
LOG_DEBUG: dwFWSize = 33d95004.
LOG_DEBUG: tag = 1178684242                      # 固件update.img头信息 标志  16进制输出     
LOG_DEBUG: size = 869879808
LOG_DEBUG: machine_model =  RK3588
LOG_DEBUG: manufacturer =  RK3588
LOG_DEBUG: version = 16777216
LOG_DEBUG: item = 10.
LOG_INFO: ================================================
LOG_DEBUG: name = package-file
LOG_DEBUG: file = package-file
LOG_DEBUG: offset = 473638
LOG_DEBUG: flash_offset = -1
LOG_DEBUG: usespace = 1
LOG_DEBUG: size = 226
LOG_INFO: ================================================
LOG_DEBUG: name = parameter
LOG_DEBUG: file = parameter.txt
LOG_DEBUG: offset = 475686
LOG_DEBUG: flash_offset = 0
LOG_DEBUG: usespace = 1
LOG_DEBUG: size = 551
LOG_INFO: ================================================
LOG_DEBUG: name = bootloader
LOG_DEBUG: file = MiniLoaderAll.bin
LOG_DEBUG: offset = 102
LOG_DEBUG: flash_offset = -1
LOG_DEBUG: usespace = 231
LOG_DEBUG: size = 471488
LOG_INFO: ================================================
LOG_DEBUG: name = uboot
LOG_DEBUG: file = uboot.img
LOG_DEBUG: offset = 950822
LOG_DEBUG: flash_offset = 16384
LOG_DEBUG: usespace = 2048
LOG_DEBUG: size = 4194304
LOG_INFO: ================================================
LOG_DEBUG: name = misc
LOG_DEBUG: file = misc.img
LOG_DEBUG: offset = 5145126
LOG_DEBUG: flash_offset = 24576
LOG_DEBUG: usespace = 24
LOG_DEBUG: size = 49152
LOG_INFO: ================================================
LOG_DEBUG: name = boot
LOG_DEBUG: file = boot.img
LOG_DEBUG: offset = 5194278
LOG_DEBUG: flash_offset = 32768
LOG_DEBUG: usespace = 18371
LOG_DEBUG: size = 37622272
LOG_INFO: ================================================
LOG_DEBUG: name = recovery
LOG_DEBUG: file = recovery.img
LOG_DEBUG: offset = 42818086
LOG_DEBUG: flash_offset = 163840
LOG_DEBUG: usespace = 21649
LOG_DEBUG: size = 44336128
LOG_INFO: ================================================
LOG_DEBUG: name = rootfs
LOG_DEBUG: file = rootfs.img
LOG_DEBUG: offset = 87155238
LOG_DEBUG: flash_offset = 491520
LOG_DEBUG: usespace = 371712
LOG_DEBUG: size = 761266176
LOG_INFO: ================================================
LOG_DEBUG: name = oem
LOG_DEBUG: file = oem.img
LOG_DEBUG: offset = 848421414
LOG_DEBUG: flash_offset = 29851648
LOG_DEBUG: usespace = 8524
LOG_DEBUG: size = 17457152
LOG_INFO: ================================================
LOG_DEBUG: name = userdata
LOG_DEBUG: file = userdata.img
LOG_DEBUG: offset = 865878566
LOG_DEBUG: flash_offset = 30113792
LOG_DEBUG: usespace = 2184
LOG_DEBUG: size = 4472832
LOG_INFO: new md5:ea8bb25ed69ed738de469f8577bbb34e
LOG_INFO: MD5Check is ok of /userdata/update.img
LOG_INFO: analyticImage ok.
LOG_INFO: found rkimage_hdr.item[1].name = parameter.
LOG_INFO: found rkimage_hdr.item[6].name = recovery.
LOG_INFO: Current device is not MTD
# 3.3 RK_ota_start函数最后遍历每一个升级命令,对于打了标记需要执行的升级命令,执行升级命令的升级函数cmd
LOG_INFO: now write parameter to /dev/block/by-name/gpt.      # 跳过parameter、misc分区烧录
LOG_INFO: ingore misc. 
LOG_INFO: now write recovery to /dev/block/by-name/recovery.  # 烧录recovery分区
LOG_INFO: update_cmd.flash_offset = 0.
LOG_INFO: flash_normal:205 start.
LOG_INFO: Current device is not MTD
LOG_INFO: flash_normal:227, diff check for recovery
LOG_WARN: Not a diff image, ret = 80
LOG_INFO: block_write src /userdata/update.img dest /dev/block/by-name/recovery.
LOG_INFO: Current device is not MTD
LOG_INFO: new md5:46a1507531c328bd6cd710c5f7391fe8    # 校验分区 即烧录到eMMC分区的镜像和原镜像分区MD5校验值是否一致
LOG_INFO: MD5Check is ok of /dev/block/by-name/recovery
LOG_INFO: new md5:46a1507531c328bd6cd710c5f7391fe8
LOG_INFO: MD5Check is ok of /userdata/update.img
LOG_INFO: check /dev/block/by-name/recovery ok.      # 校验通过 
LOG_INFO: RK_ota_start is ok!
LOG_INFO: rk ota success.
LOG_INFO: Current Mode is recovery.
LOG_INFO: rk m_status = 0.                          # # RK_ota_start函数执行完毕
LOG_INFO: Current device is not MTD

通过查看日志信息,我们就可以了解到在normal系统下的升级流程,即仅仅升级recovery分区,这和和文章《Rockchip RK3588 - Rockchip Linux Recovery updateEngine源码分析》分析的一致。

3.2.3 recovery系统下的升级日志

接着重启进入recovery系统,执行/usr/bin/recovery升级其它分区。

因此我们可以在串口日志中定位到;

starting recovery...
LOG_INFO: devices is not MTD.
LOG_INFO: Boot command: boot-recovery                
LOG_INFO: Got arguments from boot message
LOG_INFO: devices is not MTD.

烧录日志会记录在/userdata/recovery/Log文件,从日志中可以看出recovery命令升级了ubootbootrootfsoem 4个分区;

点击查看代码
*********************************************************
            ROCKCHIP recovery system
*********************************************************
**** version : V1.0.1-g28f720bc5-240524-dirty ****
LOG_INFO: Starting recovery on Sun Jun 30 15:08:22 2024

LOG_INFO: Recovery System have UI defined.
LOG_INFO: failed to read font: res=-1, fall back to the compiled-in font
LOG_INFO: rotate degree: 0 - none, 1 - right, 2 - down, 3 - left.
LOG_INFO: current rotate degree is : 0
recovery filesystem table
=========================
  0 (null) /tmp ramdisk (null) (null) (null)
  1 /dev/root / ext4 rw,noauto 0 1
  2 tmpfs /tmp tmpfs mode=1777 0 0
  3 tmpfs /run tmpfs mode=0755,nosuid,nodev 0 0
  4 tmpfs /var/log tmpfs mode=0755,nosuid,nodev 0 0
  5 proc /proc proc defaults 0 0
  6 devtmpfs /dev devtmpfs defaults 0 0
  7 devpts /dev/pts devpts mode=0620,ptmxmode=0000,gid=5 0 0
  8 tmpfs /dev/shm tmpfs nosuid,nodev,noexec 0 0
  9 sysfs /sys sysfs nosuid,nodev,noexec 0 0
  10 configfs /sys/kernel/config configfs defaults 0 0
  11 debugfs /sys/kernel/debug debugfs defaults 0 0
  12 pstore /sys/fs/pstore pstore nosuid,nodev,noexec 0 0
  13 /dev/sda1 /mnt/udisk auto defaults 0 2
  14 /dev/mmcblk1p1 /mnt/sdcard auto defaults 0 2
  15 /dev/block/by-name/oem /oem ext4 defaults 0 2
  16 /dev/block/by-name/userdata /userdata ext4 defaults 0 2

LOG_INFO: devices is not MTD.
LOG_INFO: emmc_point is /dev/mmcblk0
LOG_INFO: sd_point is (null)
LOG_INFO: sd_point_2 is (null)
LOG_INFO: read cmdline
LOG_INFO: >>> Boot from non-SDcard
LOG_INFO: read cmdline
LOG_INFO: >>> Boot from non-U-Disk
LOG_INFO: Command: "recovery" "--update_package=/userdata/update.img"

LOG_INFO: check userdata/oem partition success ...
LOG_INFO: mounted /userdata/update.img Success.
LOG_INFO: >>>rkflash will update from /userdata/update.img
LOG_INFO: [do_rk_updateEngine] start with main.              
LOG_INFO: SDcard update data: [--image_url=/userdata/update.img]
LOG_INFO: devices is not MTD.
LOG_INFO:  >>>>>> [parameter] upgrade start... <<<<<<               
# 2 开始执行updateEngine升级源码的main函数
LOG_INFO: *** update_engine: V1.0.1-g28f720bc5-240524-dirty ***.
# 2.1 执行main函数中is_update逻辑
LOG_INFO: main-274: is ota update         
# 2.1.1 main -> MiscUpdate
LOG_INFO: Current Mode is recovery.
# 2.1.1.1 MiscUpdate->RK_ota_set_url
LOG_INFO: start RK_ota_url url [/userdata/update.img] save path [/userdata/update.img].  
LOG_INFO: save image to /userdata/update.img.
LOG_INFO: url = /userdata/update.img.                               
LOG_INFO: [MiscUpdate:90] save path: /userdata/update.img
# 2.1.1.2 MiscUpdate -> RK_ota_set_partition(partition): 遍历升级命令数组,对需要执行的升级命令打标记
LOG_INFO: [RK_ota_set_partition:106] num [16]      
LOG_INFO: need update parameter.                
LOG_INFO: need update uboot.
LOG_INFO: Current device is not MTD
LOG_INFO: need update trust.
LOG_INFO: Current device is not MTD
LOG_INFO: need update boot.
LOG_INFO: Current device is not MTD
LOG_INFO: need update rootfs.
LOG_INFO: Current device is not MTD
LOG_INFO: need update oem.
LOG_INFO: Current device is not MTD
#  2.1.1.3 MiscUpdate -> RK_ota_start: 对命令数组update_cmd中打了标记的命令所指向的分区进行升级
LOG_INFO: start RK_ota_start.      
# 2.1.1.3.1 RK_ota_start -> download_file(_url, _save_path):函数从_url下载升级固件,文件下载成功设置_url=_save_path;
LOG_INFO: rk m_status = 1.
LOG_INFO: where the file is local.
# 2.1.1.3.2 RK_ota_start -> RK_ota_set_partition(-1): 获取升级固件的信息,输出固件update.img头信息、原始固件update.raw.img头信息
LOG_INFO: [RK_ota_set_partition:106] num [16]      
LOG_DEBUG: uiTag = 57464b52.            # 固件update.img头信息 标志  16进制输出         
LOG_DEBUG: usSize = 66.                    # 结构体大小  
LOG_DEBUG: dwVersion = 1000000.            # Image 文件版本
LOG_DEBUG: btMajor = 1, btMinor = 0, usSmall = 00.
LOG_DEBUG: dwBootOffset = 66.              # bootloade分区镜像偏移    
LOG_DEBUG: dwBootSize = 731c0.             # bootloade分区镜像大小 
LOG_DEBUG: dwFWOffset = 73226.             # 原始固件update.raw.img偏移 
LOG_DEBUG: dwFWSize = 33d95004.            # 原始固件update.raw.img大小
LOG_DEBUG: tag = 1178684242             # 原始固件update.raw.img头信息  标志 10进制 输出
LOG_DEBUG: size = 869879808
LOG_DEBUG: machine_model =  RK3588     
LOG_DEBUG: manufacturer =  RK3588
LOG_DEBUG: version = 16777216
LOG_DEBUG: item = 10.                      # 需要升级的分区镜像个数
LOG_INFO: ================================================
LOG_DEBUG: name = package-file             # package-file分区镜像信息
LOG_DEBUG: file = package-file
LOG_DEBUG: offset = 473638
LOG_DEBUG: flash_offset = -1
LOG_DEBUG: usespace = 1
LOG_DEBUG: size = 226
LOG_INFO: ================================================
LOG_INFO: ================================================
LOG_DEBUG: name = parameter                # parameter分区镜像信息
LOG_DEBUG: file = parameter.txt
LOG_DEBUG: offset = 475686
LOG_DEBUG: flash_offset = 0
LOG_DEBUG: usespace = 1
LOG_DEBUG: size = 551
LOG_INFO: ================================================
LOG_DEBUG: name = bootloader                # bootloader分区镜像信息
LOG_DEBUG: file = MiniLoaderAll.bin
LOG_DEBUG: offset = 102
LOG_DEBUG: flash_offset = -1
LOG_DEBUG: usespace = 231
LOG_DEBUG: size = 471488
LOG_INFO: ================================================
LOG_DEBUG: name = uboot
LOG_DEBUG: file = uboot.img
LOG_DEBUG: offset = 950822
LOG_DEBUG: flash_offset = 16384
LOG_DEBUG: usespace = 2048
LOG_DEBUG: size = 4194304
LOG_INFO: ================================================
LOG_DEBUG: name = misc
LOG_DEBUG: file = misc.img
LOG_DEBUG: offset = 5145126
LOG_DEBUG: flash_offset = 24576
LOG_DEBUG: usespace = 24
LOG_DEBUG: size = 49152
LOG_INFO: ================================================
LOG_DEBUG: name = boot
LOG_DEBUG: file = boot.img
LOG_DEBUG: offset = 5194278
LOG_DEBUG: flash_offset = 32768
LOG_DEBUG: usespace = 18371
LOG_DEBUG: size = 37622272
LOG_INFO: ================================================
LOG_DEBUG: name = recovery
LOG_DEBUG: file = recovery.img
LOG_DEBUG: offset = 42818086
LOG_DEBUG: flash_offset = 163840
LOG_DEBUG: usespace = 21649
LOG_DEBUG: size = 44336128
LOG_INFO: ================================================
LOG_DEBUG: name = rootfs
LOG_DEBUG: file = rootfs.img
LOG_DEBUG: offset = 87155238
LOG_DEBUG: flash_offset = 491520
LOG_DEBUG: usespace = 371712
LOG_DEBUG: size = 761266176
LOG_INFO: ================================================
LOG_DEBUG: name = oem
LOG_DEBUG: file = oem.img
LOG_DEBUG: offset = 848421414
LOG_DEBUG: flash_offset = 29851648
LOG_DEBUG: usespace = 8524
LOG_DEBUG: size = 17457152
LOG_INFO: ================================================
LOG_DEBUG: name = userdata
LOG_DEBUG: file = userdata.img
LOG_DEBUG: offset = 865878566
LOG_DEBUG: flash_offset = 30113792
LOG_DEBUG: usespace = 2184
LOG_DEBUG: size = 4472832
LOG_INFO: new md5:ea8bb25ed69ed738de469f8577bbb34e
LOG_INFO: MD5Check is ok of /userdata/update.img
LOG_INFO: analyticImage ok.
LOG_INFO: found rkimage_hdr.item[1].name = parameter.
LOG_INFO: found rkimage_hdr.item[3].name = uboot.
LOG_INFO: found rkimage_hdr.item[5].name = boot.
LOG_INFO: found rkimage_hdr.item[7].name = rootfs.
LOG_INFO: found rkimage_hdr.item[8].name = oem.
LOG_INFO: Current device is not MTD
# 2.1.1.3.3 RK_ota_start 遍历每一个升级命令,对于打了标记需要执行的升级命令,执行升级命令的升级函数cmd
LOG_INFO: now write parameter to /dev/block/by-name/gpt.      # 跳过parameter、misc分区烧录
LOG_INFO:  >>>>>> [parameter] upgrade start... <<<<<<
LOG_INFO: ingore misc.
LOG_INFO: now write uboot to /dev/block/by-name/uboot.        # 1. 烧录uboot分区
LOG_INFO:  >>>>>> [uboot] upgrade start... <<<<<<
LOG_INFO: update_cmd.flash_offset = 0.
LOG_INFO: flash_normal:205 start.
LOG_INFO: Current device is not MTD
LOG_INFO: flash_normal:227, diff check for uboot
LOG_WARN: Not a diff image, ret = 80
LOG_INFO: block_write src /userdata/update.img dest /dev/block/by-name/uboot.  
LOG_INFO: Current device is not MTD
LOG_INFO: new md5:3a58dc09d6c8c605c05232223dd9284e
LOG_INFO: MD5Check is ok of /dev/block/by-name/uboot
LOG_INFO: new md5:3a58dc09d6c8c605c05232223dd9284e
LOG_INFO: MD5Check is ok of /userdata/update.img
LOG_INFO: check /dev/block/by-name/uboot ok.
LOG_INFO:  >>>>>> [uboot] upgraede success! <<<<<<
LOG_INFO: now write boot to /dev/block/by-name/boot.            # 2. 烧录boot分区
LOG_INFO:  >>>>>> [boot] upgrade start... <<<<<<
LOG_INFO: update_cmd.flash_offset = 0.
LOG_INFO: flash_normal:205 start.
LOG_INFO: Current device is not MTD
LOG_INFO: flash_normal:227, diff check for boot
LOG_WARN: Not a diff image, ret = 80
LOG_INFO: block_write src /userdata/update.img dest /dev/block/by-name/boot.
LOG_INFO: Current device is not MTD
LOG_INFO: new md5:2df264d6492237a4df9c24179d773bc4
LOG_INFO: MD5Check is ok of /dev/block/by-name/boot
LOG_INFO: new md5:2df264d6492237a4df9c24179d773bc4
LOG_INFO: MD5Check is ok of /userdata/update.img
LOG_INFO: check /dev/block/by-name/boot ok.
LOG_INFO:  >>>>>> [boot] upgraede success! <<<<<<
LOG_INFO: now write rootfs to /dev/block/by-name/rootfs.       # 3. 烧录rootfs分区
LOG_INFO:  >>>>>> [rootfs] upgrade start... <<<<<<
LOG_INFO: update_cmd.flash_offset = 0.
LOG_INFO: flash_normal:205 start.
LOG_INFO: Current device is not MTD
LOG_INFO: flash_normal:227, diff check for rootfs
LOG_WARN: Not a diff image, ret = 80
LOG_INFO: block_write src /userdata/update.img dest /dev/block/by-name/rootfs.
LOG_INFO: Current device is not MTD
LOG_INFO: new md5:8fbb598c27b8f050f5910e57b43ea9bd
LOG_INFO: MD5Check is ok of /dev/block/by-name/rootfs
LOG_INFO: new md5:8fbb598c27b8f050f5910e57b43ea9bd
LOG_INFO: MD5Check is ok of /userdata/update.img
LOG_INFO: check /dev/block/by-name/rootfs ok.
LOG_INFO:  >>>>>> [rootfs] upgraede success! <<<<<<
LOG_INFO: now write oem to /dev/block/by-name/oem.              # 4. 烧录oem分区
LOG_INFO:  >>>>>> [oem] upgrade start... <<<<<<
LOG_INFO: update_cmd.flash_offset = 0.
LOG_INFO: flash_normal:205 start.
LOG_INFO: Current device is not MTD
LOG_INFO: flash_normal:227, diff check for oem
LOG_WARN: Not a diff image, ret = 80
LOG_INFO: block_write src /userdata/update.img dest /dev/block/by-name/oem. 
LOG_INFO: Current device is not MTD
LOG_INFO: new md5:2c377f6e23b558e81438cdfd1ce606df
LOG_INFO: MD5Check is ok of /dev/block/by-name/oem
LOG_INFO: new md5:2c377f6e23b558e81438cdfd1ce606df
LOG_INFO: MD5Check is ok of /userdata/update.img
LOG_INFO: check /dev/block/by-name/oem ok.
LOG_INFO:  >>>>>> [oem] upgraede success! <<<<<<
LOG_INFO: RK_ota_start is ok!
LOG_INFO: rk ota success.
LOG_INFO: Current Mode is recovery.
LOG_INFO: rk m_status = 0.
LOG_INFO:  >>>>>> updateEngine upgrade OK! <<<<<<      # RK_ota_start函数执行完毕
LOG_INFO: finish_recovery Enter.....

通过查看日志信息,我们就可以了解到在recovery系统下的升级流程,即升级recovery之外的ubootbootrootfsoem分区,这同样和文章《Rockchip RK3588 - Rockchip Linux Recovery updateEngine源码分析》分析的一致。

3.2.4 本地升级测试

接下来我们进行测试,开发板从ubuntu tftp服务器下载统一镜像:

root@rk3588-buildroot:/userdata# tftp -g -l update.img 192.168.0.200

然后执行updateEngine本地升级命令:

root@rk3588-buildroot:/# updateEngine --image_url=/userdata/update.img --misc=update  --savepath=/userdata/update.img --reboot

3.3 恢复出厂设置

命令行运行update程序,设备会进入recovery,并进行格式化,格式化完成之后会自动进入normal系统;

root@rk3588-buildroot:~# ls /usr/bin/update -l
-rwxr-xr-x 1 root root 427740 Jun  9 04:58 /usr/bin/update
root@rk3588-buildroot:~# update 
update: Rockchip Update Tool
update: --wipe_all
command: --wipe_all
update: write command to command file: done
update: write command to misc file: done
update: reboot!

参考文章

[1] Rockchip Linux updateEngine升级方案介绍

[2] Rockchip Linux Recovery升级开发指南

[3] 嵌入式Linux开发之Makefile

posted @ 2024-06-25 22:56  大奥特曼打小怪兽  阅读(637)  评论(0编辑  收藏  举报
如果有任何技术小问题,欢迎大家交流沟通,共同进步