9.2.7. 设计说明

9.2.7.1. Luban OTA 升级包制作过程

../../../_images/swu.png

注解

  1. OTA升级包配置文件:sw-images.cfg

  2. OTA策略描述文件:sw-description

  3. OTA升级包生成工具:swupdate_pack_swu

9.2.7.1.1. OTA升级包配置文件:sw-images.cfg

sw-images.cfg由Luban提供, 用于指导哪些文件会被打包进OTA升级包, 路径为: ${TARGET_BOARD_DIR}/swupdate/sw-images.cfg

9.2.7.1.1.1. 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包。

9.2.7.1.1.2. SPINAND 平台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
)

9.2.7.1.1.3. 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

9.2.7.1.2. 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

9.2.7.1.2.1. 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";
                        }
                    );
        };
    };
}

注解

  1. U-Boot环境变量boot_partition用来指导主系统和Recovery系统之间切换过程。

  2. 当U-Boot使能了Falcon功能, SPL程序会直接引导内核启动, 不会执行U-Boot程序, 也就不会判断环境变量boot_partition进行系统之间的切换, 因此需要通过设置boot_os=no, 临时关闭Falcon功能。

9.2.7.1.2.2. 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";
                }
            );
                };
        };
}

9.2.7.1.3. OTA升级包生成工具:swupdate_pack_swu

制作OTA升级包通过功能命令swupdate_pack_swu, 相关文件路径如下:

target/d211/common/post-image.sh

swupdate_pack_swu具体调用了cpio命令进行打包。

使用方法: 在编译主系统完成后, 会自动执行swupdate_pack_swu命令生成<board>.swu。

OTA包组成:

../../../_images/pack_swu.png

解压OTA包的方法:

cpio -idv < xxx.swu

9.2.7.1.4. 升级脚本:swupdate_cmd.sh

OTA的升级由SWUpdate程序完成, 但是如何使用SWUpdate完成整个OTA流程, 需要一个应用程序对流程进行控制, swupdate_cmd.sh脚本就是一个OTA流程控制脚本。

swupdate_cmd.sh脚本主要功能如下:

  1. 触发和进入OTA升级

  2. 生成和传递合适的参数给SWUpdate程序

  3. 阶段升级完成后, 控制系统重启

swupdate_cmd.sh位于以下路径:

package/third-party/swupdate/swupdate_cmd.sh

9.2.7.1.4.1. 启动升级脚本命令解析

具体解析过程如下:

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执行程序

9.2.7.1.4.2. 主系统下启动升级命令过程

当带参调用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”启动升级

9.2.7.1.4.3. 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”启动升级

9.2.7.1.4.4. 升级过程中的重启实现

当主系统或者Recovery系统对应的程序升级完成以后, 在sw-description里面设置swu_reboot =yes, swupdate_cmd.sh在检测到该值以后, 会调用重启命令。

9.2.7.1.4.5. 环境变量其它用法

如果客户需要传递其它信息, 比如wifi密码, ip地址等可以通过修改swupdate_cmd.sh 在env.txt里面添加设置对应。