Luban OTA 升级包制作过程
OTA 升级包配置文件:sw-images.cfg
-
sw-images.cfg 文件名称是固定的,如果名称不对,则编译 OTA 升级包时会出错。
-
${TARGET_BOARD_DIR}/swupdate 目录下的 sw-description 文件名称可以指定为其它,但需修改 sw-images.cfg 中的描述信息。
将最终的文件打包到 OTA 升级包中,重命名为 sw-description 并放在第一个文件即可。比如将 sw-description 改为 sw-description-ubi,则在 sw-images.cfg 中添加如下信息:
${TARGET_BOARD_DIR}/swupdate/sw-description-ubi: sw-description
-
SPINAND 平台 sw-images.cfg
swota_file_list=( ${TARGET_BOARD_DIR}/swupdate/sw-description: sw-description ${BINARIES_DIR}/recovery.itb:recovery ${BINARIES_DIR}/kernel.itb:kernel ${BINARIES_DIR}/boot_logo.png:logo ${BINARIES_DIR}/rootfs_page_2k_block_128k.ubifs:rootfs #下面这行给使用 Page 为 4K 的 SPINAND 方案预留, 目前注释掉 #${BINARIES_DIR}/rootfs_page_4k_block_256k.ubifs:rootfs )
注:指示打包 SWUpdate 升级包所需的各个文件的位置,这些文件会被拷贝到 out/images/swupdate 目录后生成 OTA 包。
-
eMMC 平台 sw-images.cfg
swota_file_list=( ${TARGET_BOARD_DIR}/swupdate/sw-description ${BINARIES_DIR}/recovery.itb:recovery ${BINARIES_DIR}/kernel.itb:kernel ${BINARIES_DIR}/boot_logo.png:logo ${BINARIES_DIR}/rootfs.ext4:rootfs )
OTA 策略描述文件: sw-description
OTA 升级包需要包含 sw-description 文件以及升级使用的其他文件,包括 Kernel 和 RootFS。整个 OTA 升级包是 cpio 格式,且 sw-description 文件必须放在第一,包名称必须使用 .swu 后缀才能被 SWUpdate 程序识别到。
sw-description 文件是 SWUpdate 官方规定的 OTA 策略描述文件,具体语法可以参考 SWUpdate 官方文档,使用 libconfig 格式。
Luban 为 eMMC SPINAND 提供了一个示例,参考 sw-images.cfg,默认指定路径为 ${TARGET_BOARD_DIR}/swupdate/sw-description: sw-description。
-
SPINAND sw-description 文件使用说明
software = { /*版本号和描述符*/ version = "1.0.0.0"; description = "Firmware update for Luban Project"; stable = { /* * upgrade_recovery stage: * Running in main system, and upgrade the "recovery" partition, * then reboot to the new recovery system * Step1: Download image and upgrade the "recovery" partition * Step2: Setup bootenv "swu_entry, boot_partition, boot_os, swu_status" * Step3: Reboot to the new recovery system to run "upgrade_kernel" */ /* * 内层 entry, upgrade_recovery, * 当调用 swupdate xxx -e stable,upgrade_recovery 时, 会匹配到这部分, 执行{}内的动作, * 可以修改, 调用的时候传入匹配的字符串即可 */ upgrade_recovery = { images: ( { filename = "recovery"; //烧录文件名称 device = "/dev/mtd8"; //对应设备节点 type = "flash"; //操作 mtd 分区 sha256 = "@recovery"; //自动获取对应镜像的 sha256 值 } ); /* * Some key env variables: * swu_boardname: The selected board name. Here is "stable" * swu_entry: The upgrade entry selection. Value can be * "upgrade_recovery" and "upgrade_kernel" * boot_os: SPL Falcon mode flag. Should be set to "no" * during OTA * swu_status: OTA status flag, Value can be "progress", * "finish" * swu_reboot: When this flag is set to "yes", the * system will be reboot when all works done for current * stage. */ /* * image 处理完以后, 需要设置一些标志, 切换状态, * swu_entry= upgrade_kernel, 下次升级 upgrade_kernel, * boot_partition= recovery, 下次引导 recovery 里面的内核启动, * boot_os= no, 临时关闭 Falcon 模式, 请查看后面注释信息, * swu_status OTA 升级的状态, 备用, Luban 添加, * swu_reboot=yes,升级 upgrade_recovery 完成, 和外部脚本配合, 指示外部脚本做 reboot 动作 */ bootenv: ( { name = "swu_entry"; value = "upgrade_kernel"; }, { name = "boot_partition"; value = "recovery"; }, { name = "boot_os"; value = "no"; }, { name = "swu_status"; value = "progress"; }, { name = "swu_reboot"; value = "yes"; } ); }; /* * upgrade_kernel stage: * Running in Recovery system, it will upgrade some key * partitions, then reboot to main system. * Step1: Download and upgrade partitons * Step2: Setup ENV variables, and mark OTA "finish" * Step3: Reboot to main system */ upgrade_kernel = { images: ( { filename = "logo"; device = "/dev/mtd5"; type = "flash"; sha256 = "@logo"; }, { filename = "kernel"; device = "/dev/mtd6"; type = "flash"; sha256 = "@kernel"; }, { filename = "rootfs"; volume = "rootfs"; //ubi 分区名称 installed-directly = true; //读取升级镜像使用流控方式, 不用先拷贝到本地 flash 上 sha256 = "@rootfs"; } ); bootenv: ( { name = "boot_partition"; value = "kernel"; }, { name = "swu_param"; //情况环境变量 value = ""; }, { name = "swu_boardname"; value = ""; }, { name = "swu_entry"; value = ""; }, { name = "swu_status"; value = "finish"; }, { name = "swu_reboot"; value = "yes"; } ); }; }; }
-
U-Boot 环境变量 boot_partition 用来指导主系统和 Recovery 系统之间切换过程。
-
当 U-Boot 使能了 Falcon 功能,SPL 程序会直接引导内核启动,不会执行 U-Boot 程序,也就不会判断环境变量 boot_partition 进行系统之间的切换,因此需要通过设置 boot_os 为 no,临时关闭 Falcon 功能。
-
-
eMMC sw-description 文件使用说明
software = { version = "1.0.0.0"; description = "Firmware update for Luban Project"; stable = { /* * upgrade_recovery stage: * Running in main system, and upgrade the "recovery" partition, * then reboot to the new recovery system * Step1: Download image and upgrade the "recovery" partition * Step2: Setup bootenv "swu_entry, boot_partition, boot_os, swu_status" * Step3: Reboot to the new recovery system to run "upgrade_kernel" */ upgrade_recovery = { images: ( { filename = "recovery"; device = "/dev/mmcblk0p10"; type = "raw"; //eMMC 存储介质 sha256 = "@recovery"; } ); /* * Some key env variables: * swu_boardname: The selected board name. Here is "stable" * swu_entry: The upgrade entry selection. Value can be * "upgrade_recovery" and "upgrade_kernel" * boot_os: SPL Falcon mode flag. Should be set to "no" * during OTA * swu_status: OTA status flag, Value can be "progress", * "finish" * swu_reboot: When this flag is set to "yes", the * system will be reboot when all works done for current * stage. */ bootenv: ( { name = "swu_entry"; value = "upgrade_kernel"; }, { name = "boot_partition"; value = "recovery"; }, { name = "boot_os"; value = "no"; }, { name = "swu_status"; value = "progress"; }, { name = "swu_reboot"; value = "yes"; } ); }; /* * upgrade_recovery stage: * Running in main system, and upgrade the "recovery" partition, * then reboot to the new recovery system * Step1: Download image and upgrade the "recovery" partition * Step2: Setup bootenv "swu_entry, boot_partition, boot_os, swu_status" * Step3: Reboot to the new recovery system to run "upgrade_kernel" */ upgrade_kernel = { images: ( { filename = "logo"; device = "/dev/mmcblk0p8"; type = "raw"; sha256 = "@logo"; }, { filename = "kernel"; device = "/dev/mmcblk0p9"; type = "raw"; sha256 = "@kernel"; }, { filename = "rootfs"; device = "/dev/mmcblk0p11"; type = "raw"; installed-directly = true; //使用流控方式 sha256 = "@rootfs"; } ); bootenv: ( { name = "boot_partition"; value = "kernel"; }, { name = "swu_param"; value = ""; }, { name = "swu_boardname"; value = ""; }, { name = "swu_entry"; value = ""; }, { name = "swu_status"; value = "finish"; }, { name = "swu_reboot"; value = "yes"; } ); }; }; }
OTA 升级包生成工具 swupdate_pack_swu
制作 OTA 升级包通过功能命令 swupdate_pack_swu,相关文件路径为 target/d211/common/post-image.sh。
swupdate_pack_swu 调用 cpio 命令进行打包。在主系统编译完成后,自动执行 swupdate_pack_swu 命令生成 <board>.swu。
OTA 包组成:
cpio -idv < xxx.swu
升级脚本 swupdate_cmd.sh
OTA 的升级由 SWUpdate 程序完成, 但是如何使用 SWUpdate 完成整个 OTA 流程, 需要一个应用程序对流程进行控制。swupdate_cmd.sh 脚本就是一个 OTA 流程控制脚本。
swupdate_cmd.sh 脚本路径为 package/third-party/swupdate/swupdate_cmd.sh,主要功能如下:
-
触发和进入 OTA 升级。
-
生成和传递合适的参数给 SWUpdate 程序。
-
阶段升级完成后,控制系统重启。
swupdate_cmd.sh 功能实现细节如下所示:
-
启动升级脚本命令解析
swupdate_cmd() { while true do swu_param=$(fw_printenv -n swu_param 2>/dev/null) swu_boardname=$(fw_printenv -n swu_boardname 2>/dev/null) swu_entry=$(fw_printenv -n swu_entry 2>/dev/null) swu_version=$(fw_printenv -n swu_version 2>/dev/null) # 从 env 环境变量里面读取 swu 相关环境变量 echo "swu_param: ##$swu_param##" echo "swu_boardname: ##$swu_boardname##" echo "swu_entry: ##$swu_entry##" check_version_para="" [ x"$swu_version" != x"" ] && { # 解析 swu_version echo "now version is $swu_version" check_version_para="-N $swu_version" } [ x"$swu_entry" = x"" ] && { # 如果$swu_entry 为空, 跳出 swupdate_cmd 函数 echo "no swupdate_cmd to run, wait for reboot swupdate" return } echo "###now do swupdate###" echo "##swupdate -v$swu_param -e "$swu_boardname,$swu_entry" ##" swupdate -v$swu_param -e "$swu_boardname,$swu_entry" # 执行具体的升级过程 swu_reboot=$(fw_printenv -n swu_reboot 2>/dev/null) echo "swu_reboot: ##$swu_reboot##" if [ x"$swu_reboot" = "xyes" ]; then # $swu_reboot == yes 强制重启 fw_setenv swu_reboot reboot -f fi sleep 1 done } # 当$swu_entry 为空, 跳转到此处执行程序 mkdir -p /var/lock # 读取传递的参数信息,写入到环境变量里面 [ $# -ne 0 ] && { echo "config new swupdate" swu_input=$* echo "swu_input: ##$swu_input##" swu_param=$(echo " $swu_input" | sed -E 's/ -e +[^ ]*//') # echo "swu_param: ##$swu_param##" echo "swu_param=$swu_param" > /tmp/swupdate_param_file swu_param_e=$(echo " $swu_input" | awk -F ' -e ' '{print $2}') swu_param_e=$(echo "$swu_param_e" | awk -F ' ' '{print $1}') swu_boardname=$(echo "$swu_param_e" | awk -F ',' '{print $1}') # echo "swu_boardname: ##$swu_boardname##" echo "swu_boardname=$swu_boardname" >> /tmp/swupdate_param_file swu_entry=$(echo "$swu_param_e" | awk -F ',' '{print $2}') # echo "swu_entry: ##$swu_entry##" echo "swu_entry=$swu_entry" >> /tmp/swupdate_param_file fw_setenv -s /tmp/swupdate_param_file # 一次写入所有的环境变量,延长存储介质寿命 sync echo "## set swupdate_param done ##" } swupdate_cmd # 跳转到 swupdate_cmd 执行程序
-
主系统下启动升级命令过程
当带参调用 swupdate_cmd.sh 时,脚本取出 “-e xxx,yyy” 部分信息并保存到 swu_boardname 和 swu_entry 环境变量,将其余参数原样保存到 swu_param 环境变量。
SPINAND 主系统下启动升级命令:
./usr/lib/swupdate/swupdate_cmd.sh -i /mnt/ota/d211_per2_spinand.swu -e stable,upgrade_recovery
自动调用
swupdate $swu_param -e “$swu_boardname,$ swu_entry”
启动升级。 -
Recovery 系统下启动升级命令过程
当不带参调用 swupdate_cmd.sh 时,脚本从 env 读取 “swu_boardname”、“swu_entry” 和 “swu_param” 环境变量。
SPINAND Recovery 系统下自动启动升级命令
./usr/lib/swupdate/swupdate_cmd.sh
。自动调用
swupdate $swu_param -e “$swu_boardname,$ swu_entry”
启动升级。 -
升级过程中的重启实现
当主系统或者 Recovery 系统对应的程序升级完成以后,在 sw-description 文件中设置 swu_reboot =yes。swupdate_cmd.sh 在检测到该值以后会调用重启命令。
-
环境变量其它用法
如需传递其它信息,比如 WIFI 密码和 IP 地址,可修改 swupdate_cmd.sh 文件,在 env.txt 中添加设置对应。