1 修改项
1.1 配置主系统
lunch 选择方案后,make menuconfig,选上 swupdate,其它使用默认即可。(Allwinner->System->swupdate)
1.2 sys_partition.fex 分区表
分区配置文件/device/config/chips/ai985/configs/evb/linux-5.15/sys_partition.fex。(可以在 lunch 选择方案后,通过命令 cconfigs 快速跳转到其目录)。
1)将原有的 boot 分区和 rootfs 分区,分区名改为 bootA 和 rootfsA。将这两个分区配置拷贝一份,即新增两个分区,并把名字改为 bootB 和 rootfsB。
2)新增appA 和 appB分区。
[partition]
name = bootA
size = 56320
downloadfile = "boot.fex"
user_type = 0x8000
[partition]
name = bootB
size = 56320
downloadfile = "boot.fex"
user_type = 0x8000
[partition]
name = rootfsA
;size = 327680
;size = 606208
size = 1048576
downloadfile = "rootfs.fex"
user_type = 0x8000
[partition]
name = rootfsB
;size = 327680
;size = 606208
size = 1048576
downloadfile = "rootfs.fex"
user_type = 0x8000
[partition]
name = appA
size = 1048576
downloadfile = "app.fex"
user_type = 0x8000
[partition]
name = appB
size = 1048576
downloadfile = "app.fex"
user_type = 0x8000
1.3 env 环境变量
/device/config/chips/ai985/configs/evb/linux-5.15/env-5.15.cfg
新增变量boot_partition、root_partition、app_partition。分别用于对应bootA、bootB;rootfsA、rootfsB;appA、appB分区的切换。
boot_partition=bootA
root_partition=rootfsA
app_partition=appA
1.4 rc.local(分区切换逻辑 )
1)bootA、bootB的切换逻辑系统自带不用新增,在/device/config/chips/ai985/configs/evb/linux-5.15/env-5.15.cfg
boot_normal=sunxi_flash read 45000000 ${boot_partition};bootm 45000000
2)rootfsA、rootfsB的切换逻辑系统自带不用新增。
3)新增appA、appB的切换逻辑,根据app_partition分别将/dev/by-name/appA或appB挂载到/mnt/app
当前启动用的是procd,procd的启动脚本文件是 rc.local,在rc.local中新增: (/openwrt/target/ai985/ai985-evb/base-files/etc/rc.local)
if [ "x$(fw_printenv -n app_partition | grep appA)" != "x" ];then
/bin/mount /dev/by-name/appA /mnt/app
fw_setenv parts_clean rootfs_data:UDISK
else
/bin/mount /dev/by-name/appB /mnt/app
fw_setenv parts_clean rootfs_data:UDISK
fi
1.5 新增挂载点
/root/data/–/–/openwrt/package/allwinner/system/busybox-init-base-files/Makefile
mkdir -p $(1)/mnt/app
挂载文件系统需要有挂载点。如创建空目录,由于 git 不管理空目录,因此需在 Makefile 中动态创建,可仿照现有 Makefile 中创建 UDISK 目录的写法。
1.6 sw-subimgs-ab.cfg (app.fex打包到升级包中)
openwrt/target/ai985/ai985-evb/swupdate/sw-subimgs-ab.cfg
${LICHEE_PACK_OUT_DIR}/app.fex:app
swupdate将app.fex打包到 **.swu升级文件中。
1.7 sw-description-ab(swupdate策略描述文件)
openwrt/target/ai985/ai985-evb/swupdate/sw-description-ab
当前使用emmc,所以在 now_A_next_B_emmc{}和now_B_next_A_emmc{}中分别新增:
{
filename = "app";
device = "/dev/by-name/appB";
installed-directly = true;
}
{
filename = "app";
device = "/dev/by-name/appA";
installed-directly = true;
}
在writenv_now_A_next_B{}和writenv_now_B_next_A{}中分别新增:
{
name = "app_partition";
value = "appB";
},
{
name = "app_partition";
value = "appA";
},
1.8 应用打包到app.fex
/root/data/–/–/build/pack
使用SDK现有的make_app_res(),将文件路径修改为应用对应的即可。执行指令pack / pack ‑s即可触发打包。
local APP_PART_FILE_PATH=$CFG_TOP_DIR/out/ai985/evb/openwrt/build_dir/target/--/.pkgdir/--/mnt/app
pack脚本修改 (解决打包异常问题)
打包时提示拿不到文件的size,导致打包失败。
修改相关代码如下:
if [ x"${PACK_PLATFORM}" = x"openwrt" ]; then
cd ${LICHEE_PACK_OUT_DIR}/
echo "vmlinux" > ${LICHEE_PACK_OUT_DIR}/vmlinux.fex
if [ "x${PACK_NOR}" = "xnor" ] ; then
make_user_res sys_partition_nor.fex
make_app_res sys_partition_nor.fex
make_data_res sys_partition_nor.fex
else
make_user_res sys_partition.fex
make_app_res sys_partition.fex
make_data_res sys_partition.fex
fi
cd - > /dev/null
fi
function make_app_res()
{
local APP_PART_NAME=appA
cp $1 sys_partition_tmp_app.fex
sed -i '/^[ \t]*downloadfile/d' sys_partition_tmp_app.fex
/bin/busybox unix2dos sys_partition_tmp_app.fex
script sys_partition_tmp_app.fex > /dev/null
update_mbr sys_partition_tmp_app.bin 1 sunxi_mbr_tmp_app.fex > /dev/null
local APP_PART_DOWNLOAD_FILE=app.fex
local APP_PART_FILE_PATH=$CFG_TOP_DIR/out/ai985/evb/openwrt/build_dir/target/--/.pkgdir/--/mnt/app
local APP_PART_SIZE_IN_SECTOR=`parser_mbr sunxi_mbr_tmp_app.fex get_size_by_name ${APP_PART_NAME}`
local TINA_TOOLS_PATH=$CFG_TOP_DIR/out/$PACK_IC/$PACK_BOARD/$PACK_PLATFORM/staging_dir/host/bin
if [ x${APP_PART_DOWNLOAD_FILE} != x'' -a x${APP_PART_SIZE_IN_SECTOR} != x'' ]; then
let APP_PART_SIZE_IN_K=$APP_PART_SIZE_IN_SECTOR/2
echo "APP_PART_DOWNLOAD_FILE = ${LICHEE_PACK_OUT_DIR}/${APP_PART_DOWNLOAD_FILE}"
rm -f ${LICHEE_PACK_OUT_DIR}/${APP_PART_DOWNLOAD_FILE}
${TINA_TOOLS_PATH}/make_ext4fs -l ${APP_PART_SIZE_IN_K}k -b 1024 -m 0 -j 1024 ${LICHEE_PACK_OUT_DIR}/${APP_PART_DOWNLOAD_FILE} ${APP_PART_FILE_PATH}
else
printf "no app resource partitions\n"
fi
}
pack文件:
do_prepare:制作前的准备工作,重命名,复制,粘贴
do_common:制作uboot,boot-resource.ini文件
do_pack_dragonboard: 执行pctools中相应的命令,制作成img文件
do_finish:制作完成,退出,提示用户
do_pack_dragonboard() 打包内核和rootfs
1.9 清空 rootfs_data 和 UDISK (解决升级异常问题)
升级后应用还是旧的,MD5值和应用LOG都未变化。因为 /overlay/upper/usr/bin/-- 此处还保存着之前的旧应用,所以OTA时需要清空 rootfs_data 和 UDISK。
在openwrt/target/ai985/ai985-evb/base-files/etc/rc.local 中添加 fw_setenv parts_clean rootfs_data:UDISK
if [ "x$(fw_printenv -n app_partition | grep appA)" != "x" ];then
/bin/mount /dev/by-name/appA /mnt/app
fw_setenv parts_clean rootfs_data:UDISK
else
/bin/mount /dev/by-name/appB /mnt/app
fw_setenv parts_clean rootfs_data:UDISK
fi
openwrt/openwrt/package/base-files/files/lib/preinit/79_format_partition
设置env parts_clean后会触发 clean_parts()的清空rootfs_data和UDISK逻辑。
1.10 压缩镜像( .fex文件),减少升级包大小
app.fex、boot.fex、rootfs.fex压缩生成生成 app.fex.gz、boot.fex.gz、rootfs.fex.gz,然后再打包生成 升级包。
不压缩镜像打包生成的升级包大小为836M byte,压缩镜像打包生成的升级包大小为240M byte。
1)生成 app.fex.gz、boot.fex.gz、rootfs.fex.gz
对app.fex、boot.fex、rootfs.fex进行压缩生成生成 app.fex.gz、boot.fex.gz、rootfs.fex.gz。
pack / pack ‑s 之后在 \out\ai985\evb\pack_out 生成app.fex、boot.fex、rootfs.fex,然后使用命令压缩生成对应的.gz。
在 build/pack/do_finish() 末尾添加
gzip -k -f $CFG_TOP_DIR/out/ai985/evb/pack_out/app.fex
gzip -k -f $CFG_TOP_DIR/out/ai985/evb/pack_out/boot.fex
gzip -k -f $CFG_TOP_DIR/out/ai985/evb/pack_out/rootfs.fex
2)修改打包文件
openwrt/target/ai985/ai985-evb/swupdate/sw-subimgs-ab.cfg
改一下打包的文件的名称,加上.gz后缀。
${LICHEE_PACK_OUT_DIR}/boot.fex.gz:kernel.gz
${LICHEE_PACK_OUT_DIR}/rootfs.fex.gz:rootfs.gz
${LICHEE_PACK_OUT_DIR}/app.fex.gz:app.gz
3)修改策略文件
openwrt/target/ai985/ai985-evb/swupdate/sw-description-ab
now_A_next_B_emmc = {
images: (
{
filename = "kernel.gz";
device = "/dev/by-name/bootB";
installed-directly = true;
compressed="zlib";
},
{
filename = "rootfs.gz";
device = "/dev/by-name/rootfsB";
installed-directly = true;
compressed="zlib";
},
{
filename = "app.gz";
device = "/dev/by-name/appB";
installed-directly = true;
compressed="zlib";
}
);
now_B_next_A_emmc = {
images: (
{
filename = "kernel.gz";
device = "/dev/by-name/bootA";
installed-directly = true;
compressed="zlib";
},
{
filename = "rootfs.gz";
device = "/dev/by-name/rootfsA";
installed-directly = true;
compressed="zlib";
},
{
filename = "app.gz";
device = "/dev/by-name/appA";
installed-directly = true;
compressed="zlib";
},
{
filename = "uboot";
type = "awuboot";
},
{
filename = "boot0_emmc";
type = "awboot0";
}
);
2 验证
2.1 生成OTA升级包
source build/envsetup.sh
lunch 1
make -j64
muboot
pack / pack ‑s
swupdate_pack_swu -ab
生成的**.swu文件在 \out\ai985\evb\openwrt\swupdate\openwrt_ai985_evb-ab.swu
2.2 执行OTA
直接推入OTA包
adb push '\out\ai985\evb\openwrt\swupdate\openwrt_ai985_evb-ab.swu' /mnt/UDISK
查看AB系统
fw_printenv -n boot_partition
fw_printenv -n root_partition
fw_printenv -n app_partition
启动OTA
当前处于A系统:
swupdate_cmd.sh -i /mnt/UDISK/openwrt_ai985_evb-ab.swu -e stable,now_A_next_B_emmc
当前处于B系统:
swupdate_cmd.sh -i /mnt/UDISK/openwrt_ai985_evb-ab.swu -e stable,now_B_next_A_emmc
查看应用升级结果
查看当前挂载情况
df -h
查看当前的分区节点
ll /dev/by-name
查看应用的MD5值和应用LOG
md5sum /overlay/upper/usr/bin/--
md5sum /usr/bin/--
cat /mnt/app/--/logs/--.log
2.3 升级截图
升级前
1)/dev/by-name/appB 挂载到 /mnt/app
2)app_partition = appB
3)
升级后
1)/dev/by-name/appA 挂载到 /mnt/app
2)app_partition = appA
3)
代表升级成功。