系统 OTA 升级
概述
OTA :( Over-the-Air Technology,空中下载技术)是指通过无线网络实现远程软件升级的技术。最早由安卓系统引入到手机设备中, OTA 技术大幅简化了传统软件升级过程,无需通过计算机连接设备,用户可直接在设备上下载并安装更新。这一技术极大地方便了用户,提高了设备维护的效率。

- 在 OTA 的广义应用中,可以划分为云端和设备端两个主要组成部分。云端部分负责处理设备的升级请求,包括执行升级校验、下发升级包以及收集升级结果等任务。而设备端则主要依赖云端下发的升级包, 完成系统软件( FOTA, Firmware Over-the-Air)或应用程序( SOTA, Software Over-the-Air)的更新与升级。
- 本文旨在提供底层设备端 OTA 的用户手册,详细阐述 OTA 在底层系统软件和应用程序升级中的机制及其实现方法,同时提供相关的开发指导。需要特别指出的是,通过 OTA 升级的系统软件与应用程序,主要是指更新存储在外部存储器(如 eMMC )中的数据。
- OTA 的对外交付物主要为一套 API 及其相应的实现库(如 libupdate.so),该库实现了底层烧写校验等关键功能。上层的 OTA 服务架构则由客户方实现,用以对接客户的云端服务。在成功从云端下载升级包后, OTA 服务会通过调用 libupdate.so 中的接口,实现版本的升级和校验等操作,从而确保设备能够顺利、安全地完成软件更新。
缩略语
| 缩略语 | 英文全称 | 中文解释 |
|---|---|---|
| SoC | System on Chip | 片上系统 |
| BL[x] | Boot Loader Stage [x] | 启动的阶段 x |
| SPL | Secondary Program Loader | 二级程序加载器 |
| GPT | GUID Partition Table | GUID 磁盘分区表 |
| GUID | Globally Unique IDentifier | 全局唯一标识符 |
| RSA | RSA Algorithm | RSA 公开密钥密码体制 |
| eMMC | embedded MultiMedia Card | 嵌入式非易失性存储器 |
系统分区表
OTA 时,将以分区为单位对目标分区进行更新,这些分区按照不同的类型做如下区分:
| 分区类型 | 属性 | 升级方 式 | 举例 |
|---|---|---|---|
| 持久化分区 | 参数分区:一般存储系统运行时需要加载的一些配置文件和参数等数据。如分区表中的 ubootenv 等 用户分区:指与系统启动无关的分区。一般在系统启动后才会被挂载,如 userdata 分区 | 单分区一般没有镜像, 分区数据需要长期保存, 不支持 OTA 升级。 | ubootenv, veeprom, userdata |
| AB 分区 | 前缀同名且尾缀带 _a 和 _b 的分区称做 AB 分区。 | AB 分区交替升级。 | boot_a, boot_b |
| BAK 分区 | 前缀同名且尾缀带bak的分区称作 BAK 分区,主要构成为 1 个主分区和若干个备份分区。 | BAK 分区只升级主分区,主分区升级并验证成功后,将主分区内容同步到备份分区。 | SBL, SBL_bak |
开启OTA
RDK默认不开启OTA功能,如需开启请按如下流程操作:
-
开启OTA前,若未编译过工程,没有生成out目录则执行下列命令,必须先编译工程或者建立编译环境。
# 编译工程,生成镜像
sudo ./pack_image.sh
# 仅建立编译环境
sudo ./pack_image.sh -p -
将build_params目录下的
ubuntu-22.04_desktop_rdk-s100_beta.conf和ubuntu-22.04_desktop_rdk-s100_release.conf中的PARTITION_FILE配置为OTA版本:export PARTITION_FILE="s100-ota-gpt.json",RDK_DM_VERIFY_ENABLE配置为开启:export RDK_DM_VERIFY_ENABLE="yes"; -
将source/bootloader/device/rdk/s100目录下的
board_s100_debug.mk和board_s100_release.mk文件中的RDK_OTA变量配置为开启export RDK_OTA="yes"; -
编译
- 制作新的miniboot的deb包
./mk_debs.sh hobot-miniboot - 重新编译本地镜像
sudo ./pack_image.sh -l
- 制作新的miniboot的deb包
根文件系统说明(OTA模式)
概述
开启 OTA 后,系统采用 system + overlayfs 的根文件系统结构。 该方案通过将系统只读部分与用户可写部分分离,使用户既可以在根文件系统中进行写操作,又能保证 system 分区 以只读方式挂载,从而在保证系统稳定与安全的同时,支持 system 分区 在 OTA 升级时进行差分更新。
OverlayFS 简要说明
OverlayFS 是一种联合文件系统(UnionFS),可将多个目录合并为一个统一的视图。 在 overlayfs 中:
-
Lowerdir(下层):只读层,提供系统的基础文件内容;
-
Upperdir(上层):可写层,保存用户的修改、增删文件;
-
Merged(合并层):提供给用户统一访问的挂载点视图。
当文件被修改或删除时,操作仅在 Upperdir 中生效,而 Lowerdir 保持不变。系统在访问时会优先读取 Upperdir 的文件,从而实现增量覆盖与只读保护的效果。
根文件系统结构方案
本系统采用以下分区结构实现 overlayfs:
| 分区类型 | 挂载角色 | 权限 | 说明 |
|---|---|---|---|
| system_A / system_B | Lowerdir | 只读 | 系统基础文件所在分区,AB 双分区结构以支持无缝 OTA 升级 |
| overlay | Upperdir | 读写 | 用户数据及修改保存区,不参与 OTA 升级 |
root (/) | Merged | 合并视图 | 提供统一的根目录访问视图 |
根文件系统的挂载逻辑如下:
-
system_A / system_B:通过 OTA 升级实现系统内容的更新;
-
overlay 分区:作为 overlayfs 的上层目录,保存运行时和用户的修改;
-
根目录 /:用户看到的文件系统合并视图。
注意事项
-
初次烧录行为
整机烧录时,overlay 分区会被格式化,system_A / system_B 分区写入只读系统镜像,此后系统启动时会自动建立 overlayfs 合并层。
-
OTA 升级行为
OTA 升级时仅更新 system 分区内容,不改动 overlay 分区。用户的配置、应用安装或修改文件将被保留。
-
文件覆盖优先级
若用户手动修改了 /etc/xxx 等文件,该修改将被写入 overlay 分区。即使 OTA 升级更新了 system 分区中的同名文件,升级后系统仍优先显示用户修改版本(overlay 优先级更高)。
OTA 打包工具
本文档以 ZIP 格式 的 OTA 包为示例进行说明。除非特别说明,TAR(img 经 Zstandard 压缩)格式 的使用方法与 ZIP 格式完全 一致,仅需将文档中的 .zip 后缀替换为 .zst.tar 即可。
当前OTA包支持zip格式和img经zstd压缩后的tar格式,后缀分别为.zip和.zst.tar。.zst.tar将img压缩成img.zst,更高压缩比,更快的解压速度,同时利用tar格式支持索引。
ota_tools目录介绍
OTA 打包工具位于 ota_tools/ 路径下。该目录包含 OTA 包构建所需的核心工具和脚本,该文件夹包含的内容如下:
tree
.
├── hdiffz # 用于生成 OTA 差分镜像的二进制差分工具
├── hooks # OTA 分区升级前/后的 Hook 脚本目录
│ ├── README.md # Hook 脚本使用说明及命名规范
│ ├── postinst_MCU.sh # MCU 分区升级完成后的后处理脚本
│ └── preinst_MCU.sh # MCU 分区升级前的前处理脚本
├── hpatchz # 用于应用 OTA 差分镜像的二进制补丁工具
├── mk_otapackage.py # OTA 升级包构建主脚本
├── ota_pack_tool.sh # OTA 升级包构建流程的 Shell 封装脚本
├── ota_process # OTA 升级核心处理逻辑目录
├── ota_sign.py # OTA 升级包签名脚本
├── parse_env.py # 构建环境与配置解析脚本
├── part_ota_cmd.json # 分区 OTA 升级命令与配置描述文件
├── private_key.pem # OTA 升级包签名使用的私钥(请妥善保管)
└── zstd.py # Zstandard 压缩/解压辅助模块
其中 hooks 目录用于提供分区烧写前和烧写后的自动执行脚本,可用于在升级过程中插入自定义处理逻辑。在使用打包工具前,建议先了解 hooks 目录的作用和使用方式。
OTA 升级 Hook 机制
-
Hook 脚本放置位置
hooks 目录用于存放 OTA 分区升级过程中的前置 / 后置处理脚本,用于在分区烧写前或烧写后执行一些自定义逻辑,包括但不限于:
-
升级前的环境检查
-
数据备份与迁移
如果某个分区不需要任何前后处理逻辑,对应的脚本文件可以省略。
-
-
脚本命名规则(必须遵守)
为确保脚本能够被正确打包并在 OTA 升级过程中执行,脚本文件名必须严格遵循以下命名规则,否则将无法被识别和加入升级包。
-
分区烧写前脚本(Pre-install Hook)
preinst_<分区名>.sh -
分区烧写后脚本(Post-install Hook)
postinst_<分区名>.sh
不符合上述命名规则的脚本文件将不会被加入 OTA 升级包,也不会在升级过程中被执行。
脚本文件名中的
<分区名>必须 与 OTA 系统中使用的分区名称完全一致,如果不确定分区名称,可通过out/product/img_packages/ota_tools/ota_info.json文件中的base_name字段进行确认。 -
-
使用示例
以MCU分区为例
-
打开
out/product/img_packages/ota_tools/ota_info.json文件,查看MCU部分的base_name字段,确认分区名称。以下仅为示例,不与实际代码挂钩,实际分区表请参考源码
"MCU_a_S600_V1.0": {
"base_name": "MCU",
"out": "/home/zxs/s600/source/bootloader/out/target/product/img_packages/MCU_S600_V1.0.img",
"medium": "nor",
"nose_support": null,
"secure": true,
"part_type": "AB",
"multi_img": true,
"life_img": false,
"multi_key": false,
"have_anti_ver": null,
"size": 6291456,
"ota_update_mode": "image"
} -
在 hooks 目录下创建以下脚本:
hooks/
├── preinst_MCU.sh # 分区烧写前执行
├── postinst_MCU.sh # 分区烧写后执行
如果该分区不需要任何前置或后置处理逻辑,则无需创建任何脚本文件。
-
-
注意事项
-
Hook 脚本为 可选项,不存在时会自动跳过执行。
-
仅会识别并处理位于 hooks 目录下、且命名规范正确的脚本文件。
-
请确保脚本内容具备正确的执行逻辑和必要的错误处理。
-
根据系统配置,脚本执行失败可能会导致 OTA 升级流程中断,请谨慎编写脚本逻辑。
-
OTA 打包工具使用方法
一般使用位于ota_tools/路径下的ota_pack_tool.sh制作所需的OTA升级包,支持OTA升级包解包,解包后重打包,制作升级包以及制作差分包等。
使用方法如下:
Usage: ./ota_pack_tool.sh [OPTIONS]...
Options:
-x, -unpack <ota_package> Unpack the given OTA package file. (compress inferred from suffix)
-r, -repack [-t <tar|zip>] Repack the files into a new OTA package. (default: tar)
-c, -create <pack_type> -d <source_dir> [-t <tar|zip>]
Generate OTA package by source dir or img_packages. (default: tar)
<pack_type>: sys, sys_signed, miniboot_signed ... etc.
<source_dir>: sys or sys_signed require img dir.
(e.g.)run "./ota_pack_tool.sh -c sys -d ../out/product/img_packages/ -t tar"
-i, -inc <pack_type> -old <old_pkg> -new <new_pkg>
Create an incremental OTA package. (compress inferred from suffix of -old)
<pack_type>: sys, sys_signed.
<old_pkg>, <new_pkg>: ota pack, xxx.zip or xxx.zst.tar.
(e.g.)run "./ota_pack_tool.sh -i sys -old all_in_one_old.zip -new all_in_one_new.zip".
-h, -help Display this help message.
OTA 制作普通升级包
通过如下命令可以制作系统升级包:
# tar格式升级包(-t参数省略),sys_signed代表打包secure版本升级包
./ota_pack_tool.sh -c sys_signed -d ~/s600/out/product/img_packages/
# zip格式升级包,sys代表打包nonsecure版本升级包
./ota_pack_tool.sh -c sys -d ~/s600/out/product/img_packages -t zip
生成的 OTA 升级包将输出到out/product/ota_packages目录,在该目录下,您将看到zip或.zst.tar结尾的升级包和signature结尾的升级包的签名文件:
all_in_one_signed.signature #secure 升级包签名文件
all_in_one_signed.zst.tar #secure 升级包文件
all_in_one.signature #nonsecure 升级包签名文件
all_in_one.zip #nonsecure 升级包文件