03-OTA (SPI-nand Flash) 在线升级方案

【1】说明

  1. 本文档编辑时间:2026-10-12

  2. 本文以 X2000 Halley5 SPI-NAND 为例介绍 OTA 升级方案,SDK 中的目录也以 X2000 Halley5 环境为例,其他平台可根据实际目录和配置进行调整。

  3. SPI-NAND OTA 分为两种模式:

    • recovery OTA:先升级并启动 kernel_recovery,进入 recovery ramdisk 后再升级 U-Boot、kernel 和 system 等镜像。该模式需要制作 recovery 镜像和 ramdisk,完整流程见本文【3】至【8】章节。

    • A/B OTA:将 kernel 和 system 划分为 A、B 两组,设备运行过程中把升级内容写入当前未启动的备用分区,再切换启动分区完成升级。该模式不需要 kernel_recovery,具体配置、制作、部署和测试方法见本文【9】和【10】章节。

  4. 两种 OTA 模式共用版本检测、升级包制作、服务器部署、下载和校验等基础流程;分区布局、镜像准备、设备端升级入口和回滚机制存在差异,使用时应选择与产品配置对应的 OTA 模式。

【2】OTA升级简介

【2.1】OTA介绍

OTA: 是一整套的设备在线升级方案,支持升级uboot,kernel,recovery,system分区。

【2.2】升级策略

  • 在服务器端升级包路径下存放VERSION文件,记录升级包的版本;设备端在/usr/data/VERSION文件中记录设备当前的系统版本。

  • 检测升级时,设备通过/usr/data/ota_res/recovery.conf配置文件中的url得到current_version_full.conf。解析这个文件得到升级包路径,获取升级包版本,与当前系统版本做比较,如果升级包版本大于当前系统版本,则启动升级程序进行升级。升级成功后,更新本地/usr/data/VERSION文件,否则不进行升级。

【2.3】OTA升级时序图

img_01.png

【3】OTA服务器的搭建

在《01_OTA简介与docker服务器搭建.md》中介绍了一个通过nginx+python实现的https服务器,该服务器使用docker方式搭建,如果需要可以参考。在服务器搭建完成之后,需要在指定的OTA升级目录(以上述搭建服务器为例,该目录为$DOCK_SERVER_PATH/ota)下存放一个current_version_full.conf文件,在这个文件中保存着OTA升级包在服务器中的存放位置,可以参考device/x2000halley5/ota-overlay/package_config/current_version.conf文件示例进行修改,示例如下:

{
  "server":{
    "ip":"10.1.4.187",
    "url":"https://10.1.4.187/version3"
  }
}

其中ip是OTA服务器的IP地址,url是升级包在服务器的存放位置,上述示例中指定的OTA升级包路径为$DOCK_SERVER_PATH/ota/versions(以上述搭建服务器为例)。

【4】开发板初始环境搭建

对于下载的SDK,首先需要在SDK顶层目录下执行source build/envsetup.sh配置环境变量,然后在执行lunch,如下(以Halley5 V30开发板为例,基于NAND介质的OTA升级为例):

img_02.png

修改device/x2000halley5/ota-overlay/package_config/recovery.conf文件来配置服务器中current_version_full.conf文件的存放位置,以【3】OTA服务器的搭建中配置的环境为例,recovery.conf内容如下:

{
  "server":{
    "ip":"10.1.4.187",
    "url":"https://10.1.4.187",
    "rpt_url":""
  }
}

其中ip是OTA服务器的IP地址,url是current_version_full.conf文件在服务器上的存放位置,在此处的环境配置下也就是$DOCK_SERVER_PATH/ota/,rpt_url为上报升级状态的服务器地址,如果没有,设置为空。

然后执行make命令编译镜像,编译出来的镜像如下:

test@user:~/release/x2000$ ll out/product/x2000halley5.v30_nand_6.6_ota-eng/image/
total 64096
drwxr-xr-x 2 test sw     4096 Nov 18 15:47 ./
drwxr-xr-x 4 test sw     4096 Nov 18 15:44 ../
-rw-r--r-- 1 test sw  6058048 Nov 18 15:45 kernel
-rw-r--r-- 1 test sw  9781312 Nov 18 15:46 kernel_recovery
-rw-r--r-- 1 test sw 49393664 Nov 18 15:47 system.ubifs
-rw-r--r-- 1 test sw   381360 Nov 18 15:47 uboot

执行cat out/product/x2000halley5.v30_nand_6.6_ota-eng/system/etc/ota_res/recovery.conf验证配置的recovery是否正确,如果正确则将编译出来的镜像拷贝到PC上,用于后续的烧录操作。

【5】OTA升级包制作

【5.1】修改分区表信息配置

修改device/x2000halley5/ota-overlay/package_config/partition_nand.conf文件配置NAND的大小和分区情况,具体的分区情况应与烧录工具保持一致(即与产品NAND的实际分区情况保持一致):

img_03.png

img_04.png

【5.2】修改升级信息配置

修改device/x2000halley5/ota-overlay/package_config/customization_nand.conf文件配置升级信息,参考如下:

img_05.png

上述提供的文档先升级kernel_recovery,启动kernel_recovery(ramdisk)之后再升级uboot、kernel、system,具体所需升级的文件可根据实际情况进行修改。

【5.3】待升级镜像文件制作

【5.3.1】kernel_recovery升级镜像文件制作

【5.3.1.1】ramdisk的制作

因为编译生成kernel_recovery时需要ramdisk,ramdisk的制作是根据ramdisk_nand.conf文件(以NAND为例,文件位置为:device/x2000halley5/ota-overlay/ramdisk_config/ramdisk_nand.conf)中列出的文件列表信息从out/product/x2000halley5.v30_nand_6.6_ota-eng/obj/buildroot-intermediate/target目录(即target目录)下进行抽取的。如果需要修改ramdisk中的文件,则可以通过修改ramdisk_nand.conf文件进行添加和删除。

下面看一下ramdisk_nand.conf文件的内容:

img_06.png

每一行的内容都是文件在target目录下的相对路径,以./lib/firmware和./etc/init.d/S21mount为例(参见下图),因为./lib/firmware是一个目录,其在制作ramdisk的时候会将这个目录抽取出来,而./etc/init.d/S21mount是一个文件,则只会抽取这一个文件,若当前行以#开头,则不进行抽取。

img_07.png

如果想要验证抽取的ramdisk是否是自己所需要的,可以在编译完kernel_recovery之后到out/product/x2000halley5.v30_nand_6.6_ota-eng/obj/kernel_recovery-intermediate/ramdisk目录(根据实际情况修改路径)下进行查看,如下图:

img_08.png

【5.3.1.2】kernel_recovery的defconfig配置

以X2000 Halley5 NAND OTA升级为例,其所需要的默认配置文件是halley5_v30_linux_sfc_nand_recovery_defconfig文件,具体开发板所对应的是哪个配置可参见device/x2000halley5/kernel-recovery.mk文件(以halley5开发板为例),如下图所示:

img_09.png

如果需要修改kernel_recovery的配置,可以在SDK顶层目录下执行make kernel_recovery-menuconfig命令,需要注意必须配置CONFIG_BLK_DEV_INITRD并且将CONFIG_INITRAMFS_SOURCE配置为ramdisk.cpio.gz,如下图所示(必须配置):

img_10.png

【5.3.1.3】kernel_recovery文件的编译生成

在SDK顶层目录下执行make kernel_recovery命令单独编译kernel_recovery,执行make命令时进行整体编译的过程中会编译kernel_recovery,生成的镜像文件存储在out/product/x2000halley5.v30_nand_6.6_ota-eng/image/目录下。

如果生成的kernel_recovery不能启动到ramdisk环境,请转到【8】OTA升级测试常见问题。

【5.3.2】uboot升级镜像文件制作

和uboot编译相关的文件可参考device/x2000halley5/uboot.mk,对于Halley5 V30 Nand介质的开发板其对应的config为halley5_xImage_sfc_nand_ota,如下图所示:

img_11.png

需要注意halley5_uImage_sfc_nand和halley5_xImage_sfc_nand_ota的主要区别是halley5_xImage_sfc_nand_ota增加了SPL_OS_BOOT和OTA_VERSION30选项(Option)。

在SDK顶层目录下执行make uboot可单独编译uboot,生成的文件在out/product/x2000halley5.v30_nand_6.6_ota-eng/image/目录下,然后将生成的uboot镜像文件拷贝到本地PC上用烧录工具合成镜像并填充分区表信息,必须确保与产品分区保持一致,其操作如下:

img_12.png

img_13.png

然后在将要编译生成OTA升级包之前将生成的image.bin拷贝到out/product/x2000halley5.v30_nand_6.6_ota-eng/image目录下(根据实际情况进行修改),并重新命名为uboot。

【5.3.3】kernel升级镜像文件制作

和产品的kernel制作方法一致,生成的镜像文件在out/product/x2000halley5.v30_nand_6.6_ota-eng/image目录下。

【5.3.4】rootfs升级镜像文件制作

【5.3.4.1】buildroot的defconfig配置

X2000 Halley5 OTA升级时buildroot的默认配置文件是halley5_linux_ota_defconfig,具体开发板对应的是哪个配置可参见device/x2000halley5/device.mk文件(以halley5开发板为例),如下图所示:

img_14.png

如果需要修改,必须配置BR2_PACKAGE_CJSON(编译recovery等依赖的库)和BR2_PACKAGE_HOST_PYTHON3(制作升级镜像包时使用)。

【5.3.4.2】rootfs-overlay的使用

在device/x2000halley5目录下的rootfs-overlay用于存储最基本的一些文件供开发板使用,对于NAND OTA升级时所需要的文件则存储在device/x2000halley5/ota-overlay/rootfs_nand_overlay目录下,比如挂载usrdate分区、拷贝/etc/ota_res/到/usr/data/目录下等相关的脚本文件等:

img_15.png

【5.4】编译生成升级镜像包

上述镜像文件制作完成之后都在out/product/x2000halley5.v30_nand_6.6_ota-eng/image目录下,如下:

test@user:~/release/x2000/out/product/x2000halley5.v30_nand_6.6_ota-eng/image$ ls -l
total 64088
-rw-r--r-- 1 test sw  6058048 Nov 18 15:45 kernel
-rw-r--r-- 1 test sw  9781312 Nov 18 16:47 kernel_recovery
-rw-r--r-- 1 test sw 49393664 Nov 18 15:47 system.ubifs
-rw-r--r-- 1 test sw   381360 Nov 18 17:26 uboot

需要注意此处的uboot镜像文件是在PC上使用烧录工具填充分区表信息之后再拷贝到服务器上的(详见【5.3.2】uboot升级镜像文件制作)。然后在SDK顶层目录下执行make ota_mkpackage命令来制作OTA升级镜像包,其结果如下图所示:

img_16.png

img_17.png

【6】升级包部署

在【3】OTA服务器的搭建中提到的current_version_full.conf文件中保存着OTA升级包在服务器中的存放位置,以上述配置为例,我们则需要将OTA升级包上传到服务器的$DOCK_SERVER_PATH/ota/versions目录下,上传完之后$DOCK_SERVER_PATH/ota/versions目录内容如下所示:

.
├── global.xml
├── nand
│   ├── update000.zip
│   ├── update001.zip
│   ├── ......
├── ota-package.7z
└── sha1Tab

然后在服务器存放升级包的位置处执行mkdir full ; 7zr x ota-package.7z -ofull命令解压升级包,解压后服务器存放升级包的目录下内容如下所示:

.
├── full
│   ├── global.xml
│   ├── nand
│   │   ├── update000.zip
│   │   ├── update001.zip
│   │   ├── ......
│   └── sha1Tab
├── global.xml
├── nand
│   ├── update000.zip
│   ├── update001.zip
│   ├── .......
├── ota-package.7z
└── sha1Tab

然后在服务器升级包路径下创建VERSION文件并写入版本号,例如echo 16 > VERSION。

【7】OTA升级测试

将制作OTA升级包时升级的zero文件拷贝到PC上和【4】开发板初始环境搭建中生成的镜像文件一起烧录到开发板上,烧录工具配置参考下图:

img_18.png

启动到system后需要配置网络连接服务器,下面分别介绍WIFI和以太网的网络配置方法:

WIFI网络配置方法:

方法一 —— 在编译builroot时直接将其打包在根文件系统中的:

修改buildroot/package/wpa_supplicant/wpa_supplicant.conf文件来配置要连接的WIFI或者在device/x2000halley5/rootfs-overlay/etc目录下添加wpa_supplicant.conf文件

方法二 —— 开发板启动后动态配置:

在开发板启动之后可以使用wpa_passphrase命令动态配置要连接的WIFI,比如wpa_passphrase "ssid" "passphrase" | tee -a /etc/wpa_supplicant.conf。也可以手动修改/etc/wpa_supplicant.conf文件进行配置。

配置完wpa_supplicant.conf文件后执行wifi_download_fw_and_up.sh启动WIFI。

以太网网络配置方法:

对于通过以太网升级的目前还没有提供配置IP地址的脚本,如果需要可自行添加。

配置好网络后,使用ping命令来确认是否与服务器成功连接。ping通之后执行ota_update_script.sh检验是否有更新待升级,如果需要进行升级,输入y,如下图所示:

img_19.png

输入y之后开始进行OTA升级,系统先升级recovery,然后启动ramdisk升级uboot、kernel和system(具体的根据上面配置的升级信息),最后再次启动,本地VERSION被更新。(详细的升级流程参见【2.3】OTA升级时序图)

【8】OTA升级测试常见问题

【8.1】升级包制作失败,出现如下错误信息

Could not find the main class: com.android.signapk.SignApk. Program will exit.  
 adding: update008/ (stored 0%)  
 adding: update008/xImage_003 (deflated 0%)  
Exception in thread "main" java.lang.UnsupportedClassVersionError: com/android/signapk/SignApk : Unsupported major.minor version 51.0  
 at java.lang.ClassLoader.defineClass1(Native Method)  
 at java.lang.ClassLoader.defineClassCond(ClassLoader.java:631)  
 at java.lang.ClassLoader.defineClass(ClassLoader.java:615)  
 at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)

由于升级包制作程序中有提前编译好的jar包,编译jar包时的java版本和您当前制作升级包的服务器java版本不匹配导致。解决办法,执行如下命令:

/* 以halley5为例 */  
cd packages/updater/ota_package_maker/otapackage/depmod/signature/signapk  
rm -f signapk.jar  
./build.sh  
cd -  
rm out/product/halley5/obj/ota/ -rf  
rm out/product/halley5/image/ota/ -rf  
make ota_mkpackage

【8.2】升级开始解析sha1Tab出错

每次制作升级包前需要删除之前升级包的sha1Tab

rm out/product/"板级"/image/ota/ -rf  
make ota_mkpackage

【8.3】无法启动recovery,Uncompressing Linux...后无打印

可能由于recovery镜像太大(通常为10M左右),内核自解压覆盖了自解压程序,可以通过配置CONFIG_XIMAGE_LDADDR(比如将0x80F00000改为0x81000000)或者裁剪ramdisk或recovery内核来解决。

【8.4】recovery启动失败:Failed to execute /linuxrc (error -2)

错误信息如下:

img_20.png

可能的原因是缺少了busybox所需的库,首先通过readelf -d busybox确定busybox所依赖的库,如下:

img_21.png

如果ramdisk中缺少库,则将其补上,重新编译测试。如果还不能启动ramdisk,则看是否缺少必要的C库。

【9】SPI-NAND A/B OTA升级方案

前面的【3】至【8】章节介绍的是 SPI-NAND recovery OTA,原有 recovery OTA 的流程图、配置、镜像制作和常见问题保持不变。本章补充 SPI-NAND A/B OTA。两种模式共用 OTA 服务器、版本检查、升级包制作、下载和校验流程,只有分区布局、镜像准备和设备端写入目标不同。

ab partition OTA 提供一种双缓存OTA机制,该模式上存在两个 kernerl 分区 和 两个system 分区分别为 kernelA、systemA、kernelB、systemB,该模式不需要组建 recovery kernel,第一次默认烧录在 A 区(kernelA , squashfsA),OTA 升级在 B 区(kernelB , squashfsB),自此之后 OTA 升级在 A/B 区域轮换(由 NV 分区特定位决定)。

此模式相比recovery OTA 模式需要占用更多的 flash 空间,但可以保留上一个可用版本,在更新后出现任何问题可以进行版本回退。

【9.1】两种OTA模式说明

X2000 Halley5 的 OTA 模式由 TARGET_EXT2_SUPPORT 选择:

  • 设置为 ota 时使用 RECOVERY_OTA,需要制作 kernel_recovery 和 recovery ramdisk。

  • 设置为 abota 时使用 AB_OTA,不制作 kernel_recovery,由设备端执行 recovery -m ab,将升级内容写入当前未启动的备用分区。

两种模式的共同点如下:

  1. 使用相同的 OTA 服务器、recovery.conf、版本检查和版本更新策略。

  2. 使用相同的 make ota_mkpackage 命令制作 OTA 升级包。

  3. 使用 global.xml、分片 update*.zip、sha1Tab 和签名对升级包进行描述和校验。

  4. 设备端都需要先检查服务器版本,再下载、校验并写入升级镜像。

  5. 服务器部署、网络配置和升级包目录结构可直接参考本文【3】、【4】、【6】和【7】章节,不在 A/B 章节中重复说明。

两种模式的主要差异如下:

项目 recovery OTA A/B OTA
升级环境 recovery ramdisk 当前运行的 Linux 系统
recovery 镜像 需要 kernel_recovery 和 ramdisk 不需要
system 写入位置 配置指定的 system 分区 当前未启动的 systemA 或 systemB
分区布局 单组 kernel/system 两组 kernel/system
完成升级后 通常由 recovery 重启 设置下一次启动分区后重启
回滚 依赖 recovery 流程 依赖 U-Boot 启动状态和 ota_rollback

【9.2】A/B OTA工作原理

SPI-NAND A/B OTA 将 kernel 和 system 分为 A、B 两组。设备从其中一组启动时,升级程序选择另一组作为目标分区,先写入目标组并完成校验,再更新 NV 分区中的启动状态。设备重启后由 U-Boot 选择新的启动分区。

以当前 Halley5 配置为例:

  • 从 A 组启动时,第一次升级写入 kernelB 和 systemB。

  • 从 B 组启动时,下一次升级写入 kernelA 和 systemA。

  • uboot 和 nv 是公共分区,不属于 A/B 轮换的系统分区。

  • userdata 不参与升级,升级过程中应保留用户数据。

A/B OTA 的核心是“先升级备用分区,再切换启动分区”,因此不会覆盖当前正在运行的 system 分区。目标分区下载失败、校验失败或写入失败时,不应切换到不完整的目标分区。

【10】SPI-NAND A/B OTA开发和使用

【10.1】A/B分区规划

当前 X2000 Halley5 SPI-NAND A/B OTA 的分区配置文件为:

device/x2000halley5/ota-overlay/package_config/partition_nand_ab.conf

当前分区表如下:

[storageinfo]
mediumtype=nand
capacity=128MB

[partition]
item1=uboot,0x0,0x100000,mtdblock0
item2=nv,0x100000,0x100000,mtdblock1
item3=kernelA,0x200000,0x800000,mtdblock2
item4=systemA,0xa00000,0x2800000,mtdblock3
item5=kernelB,0x3200000,0x800000,mtdblock4
item6=systemB,0x3a00000,0x2800000,mtdblock5
item7=userdata,0x6200000,0x1e00000,mtdblock6

kernel 镜像必须小于 0x800000(8 MiB),system.ubifs 必须小于 0x2800000(40 MiB)。分区起始地址和大小必须与烧录工具、U-Boot 实际使用的 MTD 分区表一致;修改 A/B 分区时需要同步检查这三处配置。

【10.2】A/B升级信息配置

A/B OTA 的升级信息配置文件为:

device/x2000halley5/ota-overlay/package_config/customization_nand_ab.conf

当前配置如下:

[update]
mediumtype=nand
imgcnt=3

[image1]
name=uboot
type=normal
offset=0x0
bootmode=normal
updatemode=slice

[image2]
name=kernel
type=normal
offset=0x200000
bootmode=normal
updatemode=slice

[image3]
name=system.ubifs
type=ubifs
offset=0xa00000
bootmode=normal
updatemode=slice

kernel 和 system.ubifs 是逻辑镜像名称,offset 使用 A 组分区的基准地址;实际写入 A 还是 B 由当前启动分区和设备端升级逻辑决定,不能理解为永远只写 A 分区。

【10.3】A/B模式编译配置

NAND A/B OTA 使用以下配置:

  • TARGET_EXT2_SUPPORT=abota 转换为 OTA_MODE=AB_OTA。

  • Buildroot 使用 x2000_halley5_linux_abota_defconfig,生成 A/B OTA 所需的裁剪文件系统。

  • U-Boot 使用 x2000_halley5_xImage_sfc_nand_abota 配置。

  • A/B OTA 不编译 kernel_recovery 和 recovery ramdisk。

  • 设备端保留 recovery、libupdater、libsysutils 和 ota_rollback;NAND 在线下载不依赖本地 getpackage 流程。

【10.4】A/B镜像制作和升级包生成

A/B OTA 不需要制作 kernel_recovery,需要准备以下镜像:

out/product/<NAND A/B产品目录>/image/
├── kernel
├── system.ubifs
└── uboot

确认镜像大小满足【10.1】的分区限制,且 uboot 与产品实际 A/B 分区布局匹配后,在 SDK 顶层目录执行:

make ota_mkpackage

NAND A/B 的 ota.mk 会将 A/B 专用配置转换为 OTA 工具默认读取的配置:

customization_nand_ab.conf -> <输出目录>/ota/package_config/customization_nand.conf
partition_nand_ab.conf     -> <输出目录>/ota/package_config/partition_nand.conf

生成目录如下:

out/product/<NAND A/B产品目录>/image/ota/
├── global.xml
├── nand/
│   ├── update000.zip
│   ├── update001.zip
│   └── ...
├── ota-package.7z
└── sha1Tab

如果在 recovery OTA 和 A/B OTA 之间切换过,建议清理对应产品的 OTA 中间目录后重新制作:

rm -rf out/product/<NAND A/B产品目录>/obj/ota
rm -rf out/product/<NAND A/B产品目录>/image/ota
make ota_mkpackage

【10.5】A/B设备端升级流程

NAND A/B OTA 使用在线下载流程,设备端执行:

update
recovery -m ab

升级过程如下:

  1. update 根据 /usr/data/ota_res/recovery.conf 连接 OTA 服务器,读取版本信息。

  2. 设备比较服务器版本与 /usr/data/VERSION,确认有新版本后进入升级流程。

  3. recovery -m ab 下载并校验 global.xml、sha1Tab 和各个 update*.zip。

  4. 解析 NAND 分区表和升级信息,识别当前活动分区。

  5. 选择另一组 kernel、system 分区作为目标分区。

  6. 下载并写入 U-Boot、kernel 和 system 镜像,其中 system 使用 UBIFS 方式处理。

  7. 校验目标分区,调用 ota_rollback 设置下一次启动分区。

  8. 重启后由 U-Boot 从新分区启动,启动成功后更新版本信息。

升级过程中如果下载失败、镜像校验失败或目标分区写入失败,不应切换到不完整的目标分区;设备应保留当前启动分区,便于重新执行升级。

【10.6】A/B启动分区和回滚

NAND A/B OTA 升级完成后,设备会通过 U-Boot 的启动状态切换到新升级的分区;如果新分区启动失败,则由 ota_rollback 根据启动检测结果执行回退。当前工程的具体回滚机制和使用方法请参考 Gitee 文档:AB OTA rollback。

验证 A/B OTA 时,建议至少完成一次 A 到 B 和一次 B 到 A 的升级,并确认启动分区切换和 userdata 数据保持正常。

【10.7】A/B OTA远程部署

【10.7.1】服务器目录结构

NAND A/B OTA 推荐使用远程 HTTP/HTTPS 部署。当前 recovery 程序会根据 recovery.conf 的 url 进入版本目录,再选择 full 或 difference 目录,并逐个下载 global.xml、sha1Tab 和 nand/update*.zip。

服务器目录建议如下:

ota/
├── current_version_full.conf
└── version3/
    └── full/
        ├── global.xml
        ├── sha1Tab
        └── nand/
            ├── update000.zip
            ├── update001.zip
            └── ...

current_version_full.conf 示例:

{
  "server":{
    "ip":"10.1.4.187",
    "url":"https://10.1.4.187/version3"
  }
}

在 version3/full 目录下创建版本号文件:

echo 17 > VERSION

如果使用本工程前面介绍的 ota-package.7z,应先解压到版本目录,而不是直接把 7z 文件地址填写到 recovery.conf:

mkdir -p version3/full
7zr x ota-package.7z -oversion3/full

解压后必须确认以下文件存在:

version3/full/global.xml
version3/full/sha1Tab
version3/full/nand/update000.zip

【10.7.2】设备端远程升级检查

在设备端确认资源和网络配置:

cat /usr/data/ota_res/recovery.conf
ping 10.1.4.187
cat /usr/data/VERSION
update

设备检测到新版本后执行:

recovery -m ab

日志中应看到类似信息:

OTA mode is AB OTA
Downloading .../full/sha1Tab
Downloading .../full/global.xml
Updating device: "nand"
Downloading .../full/nand/update000.zip

如果日志仍然出现 /storage/update/update.zip,通常说明当前产品仍编译了 OTA_LOCAL_PACKAGE,或实际运行的 recovery 不是当前 A/B 产品生成的版本,需要检查 OTA_MODE、编译产物和设备端 /usr/data/ota_res/ 文件。

【10.8】A/B OTA本地升级包部署

本地部署适合无网络环境或快速验证。NAND A/B 的本地升级包应放在设备可访问的本地存储目录中,推荐使用 file: URL 复用在线升级流程。与 EMMC 的单个 mmc/update.zip 不同,NAND A/B 使用 global.xml、sha1Tab 和多个 nand/update*.zip 分片文件。

【10.8.1】本地 recovery.conf

将设备端 recovery.conf 配置为 file: 路径:

{
  "server":{
    "ip":"127.0.0.1",
    "url":"file:/storage/ota_download",
    "rpt_url":""
  }
}

修改后重新编译对应产品,或在测试设备上临时替换 /usr/data/ota_res/recovery.conf。file: 后面必须填写设备端的绝对路径,不能填写 PC 端路径,也不能填写 ota-package.7z 文件路径。

【10.8.2】本地目录结构

本地目录示例:

/storage/ota_download/
├── current_version_full.conf
└── version3/
    ├── VERSION
    └── full/
        ├── global.xml
        ├── sha1Tab
        └── nand/
            ├── update000.zip
            ├── update001.zip
            └── ...

current_version_full.conf 示例:

{
  "server":{
    "ip":"127.0.0.1",
    "url":"file:/storage/ota_download/version3"
  }
}

其中,recovery.conf 中的 URL 用于获取 current_version_full.conf,current_version_full.conf 中的 URL 用于获取版本号和升级包。设备端实际读取的路径如下:

/storage/ota_download/current_version_full.conf
/storage/ota_download/version3/VERSION
/storage/ota_download/version3/full/global.xml
/storage/ota_download/version3/full/sha1Tab
/storage/ota_download/version3/full/nand/update000.zip
/storage/ota_download/version3/full/nand/update001.zip

准备目录后,将 VERSION 写入大于设备当前版本的升级版本号:

echo 17 > /storage/ota_download/version3/VERSION

【10.8.3】本地升级包导入设备

先在 PC 端将 ota-package.7z 解压到 version3/full 目录:

mkdir -p ota_download/version3/full
7zr x out/product/<NAND A/B产品目录>/image/ota/ota-package.7z \
    -oota_download/version3/full
echo 17 > ota_download/version3/VERSION

确认目录内容完整后,可以使用 adb 导入整个目录:

adb push ota_download /storage/

或者通过业务程序、U 盘或其他方式将文件复制到设备的 /storage/ota_download。导入后检查:

ls -l /storage/ota_download/current_version_full.conf
ls -l /storage/ota_download/version3/VERSION
ls -l /storage/ota_download/version3/full/global.xml
ls -l /storage/ota_download/version3/full/sha1Tab
ls -l /storage/ota_download/version3/full/nand/update000.zip

【10.8.4】本地部署注意事项

  • /storage 必须已经挂载,并且剩余空间能够容纳全部 nand/update*.zip 分片文件。

  • current_version_full.conf 中的路径必须与 recovery.conf 中的路径和设备实际目录一致。

  • VERSION 位于 current_version_full.conf 的 URL 指向目录下,即本例中的 /storage/ota_download/version3/VERSION。

  • NAND A/B 的 global.xml、sha1Tab 和全部 nand/update*.zip 必须来自同一次 make ota_mkpackage,不能只复制 update000.zip。

  • 使用 file: 时,recovery 通过 /bin/cp 读取本地文件,因此路径必须存在,并且文件权限必须允许 recovery 读取。

  • 当前 NAND A/B 默认使用多分片流程,设备端不需要开启 OTA_LOCAL_PACKAGE,也不能将多分片包改名为 /storage/update/update.zip。

  • 如果日志仍然读取 /storage/update/update.zip,应检查运行中的 recovery 是否为 A/B 版本,以及产品是否误开启了 OTA_LOCAL_PACKAGE。

  • 本地部署仍会执行版本、设备类型、分区匹配、SHA1 和签名校验。

本地目录准备完成后,执行下面的命令进行升级:

update
recovery -m ab

【10.8.5】本地部署和远程部署对比

项目 远程部署 本地部署
recovery.conf URLhttps://服务器地址file:/storage/ota_download
升级包来源 OTA 服务器 设备本地存储
NAND A/B 包路径version3/full/nand/update*.zip/storage/ota_download/version3/full/nand/update*.zip
是否需要网络 需要 不需要
主要限制 网络、HTTPS 和服务器连通性 本地存储空间、目录层级和文件权限

【10.9】A/B OTA完整测试清单

建议按照下面顺序验证,避免只验证“包能下载”而遗漏分区切换:

  1. 编译检查:确认使用 A/B lunch 目标,生成 kernel、system.ubifs、uboot 和 ota-package.7z,且没有依赖 kernel_recovery。

  2. 包结构检查:确认服务器存在 VERSION、global.xml、sha1Tab 和完整的 nand/update*.zip。

  3. 配置检查:确认生成的 partition_nand.conf 是由 partition_nand_ab.conf 转换而来,分区地址与烧录工具一致。

  4. 网络检查:设备能够 ping 通服务器,recovery.conf 的 URL 可访问 current_version_full.conf。

  5. A 到 B 升级:从 partitionA 启动,执行 update 和 recovery -m ab,确认写入 B 组并从 B 组启动。

  6. B 到 A 升级:再次制作更高版本或部署下一版本,确认写入 A 组并从 A 组启动。

  7. 回滚检查:使用 ota_rollback -i 验证主动切换;模拟目标系统启动失败,确认自动回退逻辑符合预期。

  8. 数据检查:确认 userdata 中的用户文件、/usr/data/VERSION 和 OTA 资源符合预期。

常见问题定位时,优先区分以下阶段:

现象 优先检查内容
下载不到 global.xmlrecovery.conf、current_version_full.conf、服务器目录和网络
下载不到 update001.zip 服务器是否完整解压、global.xml 中的包索引是否与文件一致
image can not mapped in partition 镜像大小、分区偏移和 A/B 配置是否匹配
UBIFS 写入失败systemA/systemB 容量、坏块/ECC、烧录工具分区和镜像大小
升级后仍从旧分区启动ota_rollback、NV 启动状态和 U-Boot A/B 启动逻辑

【10.10】NAND A/B OTA与recovery OTA差异

两种模式的通用配置和流程见本文前面的 recovery OTA 章节,本节只列出 NAND 下的差异:

  • recovery OTA 使用 partition_nand.conf 和 customization_nand.conf;A/B OTA 使用 partition_nand_ab.conf 和 customization_nand_ab.conf 作为源配置。

  • recovery OTA 需要 kernel_recovery、ramdisk 和 recovery 启动过程;A/B OTA 不需要这些镜像。

  • recovery OTA 通常将系统镜像写入固定的 system 分区;A/B OTA 根据当前启动状态写入备用 system 分区。

  • recovery OTA 使用单组 kernel/system;A/B OTA 必须配置 kernelA/systemA 和 kernelB/systemB,且两组容量应一致。

  • 两种模式都使用 NAND、UBIFS、分片升级包和相同的服务器部署方式,但 A/B OTA 需要额外验证启动分区切换和回滚。