Rockchip RK3588 - Rockchip Linux Recovery updateEngine测试
----------------------------------------------------------------------------------------------------------------------------
开发板 :ArmSoM-Sige7
开发板
eMMC
:64GB
LPDDR4
:8GB
显示屏 :15.6
英寸HDMI
接口显示屏
u-boot
:2017.09
linux
:5.10
----------------------------------------------------------------------------------------------------------------------------
在《Rockchip RK3588 - Rockchip Linux Recovery updateEngine
源码分析》中我们已经对updateEngine
源码的来龙去脉做了详细的介绍,本节将会介绍如何使用updateEngine
进行固件的升级。
一、制作系统镜像
首先我们需要将我们制作的统一固件update.img
(这里以buildroot
系统为例)烧录到开发板eMMC
中,具体烧录步骤可以参考《Rockchip RK3588 - Rockchip Linux SDK
编译》。
制作统一固件update.img
有多种方式:
- 采用
./build.sh all
进行一键全自动编译(包含了uboot
、kernel
等): - 按模块进行编译;
由于《Rockchip RK3588 - Rockchip Linux SDK
编译》中我们已经编译了uboot
、kernel
、rootfs
等模块,因此在这里我们采用按模块编译的方式重新编译rootfs
,recovery
,具体步骤如下文所述。
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.ext2
有700M+
。
编译出来的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.img
有40M+
。
编译出来的recovery.img
包含用于升级的updateEngine
、rkupdate
可执行文件;
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
配置,为了减少一下依赖的库(png
、drm
、bm
等)。此处编译我们采用的是动态链接,当然我们也可以制作libcurl.a
、libbz2.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
系统升级
OTA
(Over-the-Air
)即空间下载技术。 OTA
升级是Android
系统提供的标准软件升级方式。它功能强大,可以无损失升级系统,主要通过网络,例如WIFI
、3G/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
:now
:Linux A/B mode: Setting the current partition to bootable
,即Linux A/B
模式,将当前分区设置为可引导分区;other
:Linux A/B mode: Setting another partition to bootable
,即Linux A/B
模式,将另外一个分区设置为升级完成分区,重启之后会尝试从另外一个分区引导;update
:Recovery mode: Setting the partition to be upgraded
,供recovery
模式使用,在normal
系统升级recovery
分区,在recovery
系统升级其余分区;display
:Display misc info
,输出misc
信息;wipe_userdata
:Format data partition
;
--partition
:设置将要升级的分区,比如uboot
、trust
、boot
、recovery
、rootfs
、oem
等;- 如果没有传入要升级的分区,在
recovery
模式默认升级uboot/trust/boot/recovery/rootfs/oem
,partition=0x3F0000
; - 如果指定了
parameter
和misc
:parameter
和misc
分区会自动忽略; - 如果升级
uboot
分区,指定partition=0x200000
; - 如果升级
trust
分区,指定partition=0x100000
; - 如果升级
boot
分区,指定partition=0x80000
; - 如果升级
recovery
分区,指定partition=0x40000
; - 如果升级
rootfs
分区,指定partition=0x20000
; - 如果升级
oem
分区,指定partition=0x10000
; - 如果升级
misc
分区,指定partition=0x200
; - 如果升级
userdata
分区,指定partition=0x100
;
- 如果没有传入要升级的分区,在
--update
:Upgrade 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
命令升级了uboot
、boot
、rootfs
、oem
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
之外的uboot
、boot
、rootfs
、oem
分区,这同样和文章《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
升级开发指南