SSU_OTA升级使用参考


1. 概述

本文介绍的是Sigmastar平台提供的升级方案,该过程主要包含OTA升级中打包、解包、升级的流程。支持分区打包、分区升级、新旧文件夹对比批量打包和升级、文件差分升级、AB分区升级。

升级包后台服务器维护、终端下载及管理,请结合第三方服务。


2. 分区打包流程


2.1. 打包工具介绍

打包工具在Linux服务器上执行,运行环境ubuntu 20.04。只会根据当前要升级的文件生成所需的文件头。

打包工具的bin所在目录:

project/image/makefiletools/bin/otapack

解包工具的bin所在目录:

release/chip/p5/dispcam/common/glibc/$(TOOLCHAIN_VERSION)/bin/mi_demo/ota_otaunpack/otaunpack

使用make命令打包成功后,与image对应版本的otaunpack会自动release到project/image/makefiletools/bin/目录。

otapack工具命令参数介绍:

-c --create: 创建一个空的升级包文件头,此命令创建文件头的同时可以用-b或-e添加开始或结束升级的脚本。

-b --begin-script: 在服务器上指定一个shell脚本文件,并把它打包进升级包中用于板子在升级前执行的脚本。

-e --end-scrip: 在服务器上指定一个shell脚本文件,并把它打包进升级包中用于板子在升级结束后执行的脚本。

-a --append: 在已经创建的升级包中追加新的头信息,追加新的信息中必须告知升级的相关讯息,具体方法请参考范例,或者在剩余的参数介绍中根据需要配置。

-s --src-file: 指定服务器上需要更新的源文件路径。

-d --dst-file: 指定需要更新的目标文件或者分区节点在目标板子中的路径。

-t --dst-file-size: 需要更新的目标文件或者分区的大小,单位为byte,可以用16/10进制表示。

-m --file-mode: 指定更新的文件权限,参考Linux的mode_t。

-o --diff-old: 指定服务器中差分升级的旧文件或者文件夹目录。

-n --diff-new: 指定服务器中差分升级的新文件或者文件夹目录。

-l --add-log: 指定字符串信息,使升级每一个block或文件时可以获得该字符串信息,限制最大512byte。

--block-update: 设定服务器中指定的源文件为裸分区数据。

--ubi-update: 设定服务器中指定的源文件为UBI文件系统的volume。

--file-update: 设定服务器中指定的源文件为单个文件升级。

--file-add: 设定服务器中指定的源文件为目标板子中新增加的文件。

--file-delete: 仅更新打包的数据头,删除板子上指定的目标文件。

--dir-update: 扫描新旧两个文件夹中的内容,并比较差异、增加、减少的部分,然后进行批量打包。

--dir-update-diff: 扫描新旧两个文件夹中的内容,并比较差异、增加、减少的部分,然后进行批量打包其中差异的文件对其差分数据进行打包。

--script-add: 在服务器上打包-src-file指定的一个shell脚本在目标板子上执行,执行时显示的脚本文件名为-dst-file所示内容,此功能在0.3版本开始支持。

--help: 打印帮助信息。

--debug: 打开调试信息。

otaunpack工具命令参数介绍:

​ -x: 解包并升级压缩的文件

​ -r: 解包并升级非压缩的文件

​ -t: 指定一个可读写的文件夹路径用于差分升级


2.2. 一般的打包流程举例

  1. 创建一个空的header

    otapack -c SStarOta.bin
    
  2. 若有需要可以用-b/-e指令添加脚本

    otapack -c SStarOta.bin -b start.sh -e end.sh
    
  3. 根据需要打包的文件更新header数据

    otapack -a SStarOta.bin -s ./images/kernel -d /dev/mtdblock8 -t 0x500000 --block-update
    
  4. 循环执行3步骤,所有的文件进行打包

  5. 压缩升级包

    gzip SStarOta.bin
    

2.3. 在ALKAID中打包介绍

OTA打包流程目前已经整合到了Makefile中。

当程序编译和打包完成后,在project下输入指令:

make image-ota

会出现如下交互界面,指定在板子上执行的脚本路径,可以选择添加或者不添加:

Start scripts:

End scripts:

在打包分区时,列出了打包的分区数据:

Make ipl ?(yes/no)

做出相关的选择后,会在project/image/output/images/下产生SStarOta.bin.gz

在配置partition的config文件中会配置分区进行打包。

举例:

文件 spinand.ubifs.p2.partition.config中有变量:OTA_IMAGE_LIST

在此变量后面追加需要打包的分区名称,并在分区的配置中添加字段xxx$(OTABLK),配置该分区需要升级的目标节点路径。

只有在OTA_IMAGE_LIST添加了分区名,才会在make image-ota的时候会询问该分区是否要进行ota升级。

分区打包脚本的所有逻辑在image/ota.mk中实现,有兴趣的可以自行研究 。


2.4. 不带文件系统的RAW DATA打包

分区升级步骤大多相似,把需要升级的文件填到对应的mtdblock中,打包的流程也一样。不同的是在RAW DATA分区打包要自行实现升级包头的创建和数据填充,这里以spinand的IPL分区打包举例:

define makeota
@read -p "Make $(1) ?(yes/no)" select;    \
if [ "$${select}" == "yes" -o "$${select}" == "y" ]; then    \
    $(foreach n,$(3),$(PROJ_ROOT)/image/makefiletools/bin/otabinheader -s $(2) -d $(n) -t $(4) -p $(5) -a $(IMAGEDIR)/SStarOta.bin;cat $(2) >> $(IMAGEDIR)/SStarOta.bin;) \
fi;
endef

ipl_spinand_mkota_:
    $(call makeota,$(patsubst %_spinand_mkota_,%,$@),$(IMAGEDIR)/ipl_s.bin,$($(patsubst %_spinand_mkota_,%,$@)$(OTABLK)),$($(patsubst %_spinand_mkota_,%,$@)$(PATSIZE)),0)

2.5. ubifs/ squashfs/ jffs2打包

如果新创建了这些分区,并且把它们加到OTA_IMAGE_LIST中,则无需再ota.mk中添加特殊处理,这一类的分区升级文件会统一处理。

UBIFS的分区升级方式与其它两种格式稍有差异,因此在打包的时候UBIFS打包的时候请使用--ubi-update


2.6. 个别文件打包

个别文件打包的选项是--file-update,目前ALKAID中还没有专门针对文件更新的打包,因此使用者需要自己手动添加。

2.7. 脚本文件打包

选项-script-add可以在服务器上打包一个shell脚本文件,用于在板子上执行,在板子上打包的shell脚本文件名由-dst-file指定,也可以不指定。

2.8. 差分数据打包

对个别文件进行差分数据打包的选项是-file-update-diff,除了普通文件外,也可以对kernel、uboot等raw image进行差分,也可以对只读文件系统的镜像文件进行差分,但是不可以对文件系统进行差分。 差分升级所需要依赖于第三方开源的bsdiff、bspatch。 bsdiff工具在打包的时候会使用,bspatch在板子上使用。 bsdiff、bspatch工具的源码在project/tools/bsdiff 编译方式: tar -vxf bzip2-1.0.6.tar.gz cd bzip2-1.0.6 make 编译完成后在当前目录下可以看到执行档案bsdiff、bspatch。 默认编译出来的是PC上使用的,编译板子上使用bspatch请改makefile。 编译完成后的bsdiff要放到PC中的/usr/bin/路径下,或者环境变量$PATH所指定的位置,同理板子上的bspatch也要放到对应的位置。

2.9. 新旧文件夹扫描并批量文件打包

文件夹扫描分两种,一种是扫描出的有差异的文件进行强制更新。 --dir-update 命令举例:otapack -a ./test-diff.bin -o ./old/ -n ./new/ -d /config -dir-update 另一种是扫描出有差异的文件进行强制更新。 dir-update-diff 命令举例:otapack -a ./test-diff.bin -o ./old/ -n ./new/ -d /config -dir-update-diff


3. 分区更新流程


3.1. 升级流程


3.2. 分区升级前注意

在分区升级之前请确保分区umount成功。可以在start scripts脚本中作相关的umount动作。若需更新文件,请确保文件在可读写的文件系统中,并且有写权限。

otaupack工具请找FAE获取。


3.3. 压缩的升级包更新

otaupack -x SStarOta.bin.gz

3.4. 非压缩的升级包更新

otaupack -r SStarOta.bin

3.5. 升级UI显示

升级时可指定一张全屏的背景图片贴到framebuffer上,图片支持jpg和png格式。同时在framebuffer中绘制进度条,otaunpack在0.2版本之后支持进度条和文字UI旋转,设定-s参数0/½/3支持None/90°/180°/270°旋转。

otaunpack -x SStarOta.bin.gz -p upgrade.jpg

3.6. 差分升级

若压缩包中存在差分升级的数据,需要指定一个临时的可以写的文件夹,命令: otaunpack -x SStarOta.bin.gz -t /tmp


3.7. 升级状态获取

在END script中利用内部变量OTA_STATUS可以获取升级的状态。

OTA_STATUS为0则升级成功,否则为-1。


3.7. SPI-NAND坏块处理

使用--block-update命令打包升级的程序中,如果设定的是mtdblock块设备节点,这种操作不会处理坏块,推荐nor flash升级可以使用此节点,若spinand需要升级同时处理坏块,请用--block-update设定为mtd的字符设备节点,otapack和otaunpack应用程序在0.2版本后可以支援使用mtd-utils在升级的时候处理坏块,请在busybox中打开nand_write和flash_eraseall。


4. A/B分区打包升级


4.1. A/B分区打包

被升级的镜像文件有可能在升级时所要升级的目标分区或者文件可能由多个匹配,一般地会存在A、B两组分区,这两组分区互为备份。 在不考虑A/B发呢去互为备份的启动流程的基础上,A/B分区的打包要考虑到匹配多种升级目标路径,或者匹配多个备份升级文件,具体有一下两种情况: 1. 单个镜像源文件对应单个目标地址 例如:kernel分区,对应/dev/mtd4/dev/mtd5,那么在打包时,"-d"选项可以带多个目标路径:otapack -s ./kernel -d "/dev/mtd4 /dev/mtd5" 2. 多个镜像源文件对应单个目标地址 与A/B分区的打包设定无异,在打包时可以填入同样的目标地址。


4.2. 分区表

在1.3版本后支持输出分区表 命令: ./otapack -out-layout layout.txt -r pack.bin --out-layout:指定输出的分区表文件名称及路径 -r:指定OTA升级包,必须是未压缩的

输出的分区表格式

0,boot.bin,/dev/mtd0,0x1
0,boot.bin,/dev/mtd1,0x1
1,kernel,/dev/mtd3,0x1
1,kernel,/dev/mtd4,0x1
2,kernel_otaenv.sh,kernel_otaenv.sh,0x1
3,misc.fwfs,/dev/mtd6,0x1
4,miservice.ubifs,/dev/ubi0_0,0x1
5,customer.ubifs,/dev/ubi0_1,0x1

其中每一行用于描述一个分区的信息,格式如下: [image id], [dst file name],[destination path],[upgrade mask] image id:每个分区或者文件都有一个唯一的序号 dst file name:分区或者文件打包时填入的镜像源文件 destination path:目标地址,当有多个目标时有可能同样的分区不同的目标用多行表示,例如上图boot.bin upgrade mask:升级掩码,用于改变升级策略。升级掩码必须是16进制,必须带前缀'0x'。默认upgrade mask全为0x1.修改"upgrade mask"有以下两种方式。原则上采用方式a。

a) 升级前config固定升级掩码。文件spinand.squashfs.partition.config中添加字段xxx$(OTAMASK),可以在编译前配置该字段,制定生成分区表时的"updrade mask"值。 如:

//一个镜像源对应两个目标地址配置两个OTAMASK
kernel$(OTABLK)    =     /dev/mtd3 /dev/mtd4
..
kernel$(OTAMASK)   =     0x2 0x4

or

//一个镜像源对应一个目标地址配置1个OTAMASK
miservice(OTABLK)  =     /dev/ubi0_1
..
miservice(OTAMASK) =     0x2

b) 生成分区表后,人工手动修改layout.txt更新升级掩码。(注意:分区表仅由otapack工具生成,除了升级掩码之外,不可以系应该任何字符)


4.3. A/B分区升级

使用otapack工具输出分区表之后,通过上述两种方式,修改掩码用于定义升级的方式。

利用分区表进行升级的命令在原来使用otaunpack的命令基础上增加'-y'指定分区表,增加'-m'配置升级时所要参考的升级掩码。

升级时参数'-m'与实际的'-y'所指定的分区表中所定义的升级掩码进行逻辑&运算,如果结果不为0,则表示可以升级,那么otaunpack则可以进行升级操作。

工具otapack默认输出的升级掩码为0x1,在otaunpack升级时使用'-m 0x1'即可默认升级全部分区。 举例:

1,kernel,/dev/mtd3,0x2
2,kernel,/dev/mtd4,0x4

若定义的目标路径/dev/mtd3为A分区,定义/dev/mtd4为B分区,则前者使用升级掩码为'0x2'(bit1),后者使用'0x4'(bit2),那么在升级A分区时使用的命令是: ./otaunpack -r pack.bin -y layout.txt -m 0x2 升级B分区,使用的命令是: ./otaunpack -r pack.bin -y layout.txt -m 0x4 若定义的分区表中只有部分分区的,例如下表,指定A分区升级掩码为'0x2',B分区的升级掩码为'0x4',非A/B分区的多大升级掩码为'0x1'

0,boot.bin,/dev/mtd0,0x2
0,boot.bin,/dev/mtd1,0x4
1,kernel,/dev/mtd3,0x2
1,kernel,/dev/mtd4,0x4
2,kernel_otaenv.sh,kernel_otaenv.sh,0x1(将kernel的image大小写进环境变量的脚本,无需再config中配置,自动打包进SStarOta.bin,OTAMASK默认为0x1,升级kernel时需要一并升级:手动修改OTAMASK与升级kernel一致,或者'-m'携带0x1(bit0)升级部分)
3,misc.fwfs,/dev/mtd6,0x1
4,miservice.ubifs,/dev/ubi0_0,0x1
5,customer.ubifs,/dev/ubi0_1,0x1

在升级时可以用下面多种选择: 1. 只升级A分区命令: ./otaunpack -r pack.bin -y layout.txt -m 0x2 2. 只升级B分区命令: ./otaunpack -r pack.bin -y layout.txt -m 0x4 3. 升级A分区和普通分区命令: ./otaunpack -r pack.bin -y layout.txt -m 0x3 4. 升级A分区和普通分区命令: ./otaunpack -r pack.bin -y layout.txt -m 0x5 注意:

升级成功的唯一标志为OTA_UPGRADE_STATUS = 0,此升级标志在升级结束后,otaunpack工具会将OTA_STATUS重定向进end.sh以供用户获取OTA升级状态。