OpenHarmony开发者论坛
标题:
OTA升级开发指导
[打印本页]
作者:
Laval社区小助手
时间:
2023-11-6 15:21
标题:
OTA升级开发指导
[md]> 本帖最后由 hyacinth养花人 于 2023-11-17 09:19 编辑
## 简介
升级包安装组件运行在updater分区,其功能主要包括读取misc分区信息获取升级包状态,对升级包进行校验,确保升级包合法有效;然后从升级包中解析出升级的可执行程序,创建子进程并启动升级程序。具体升级的动作由升级脚本控制。本文将介绍如何针对OpenHarmony L2场景适配updater模式。
## 前置条件
* 参考OpenHarmony官方指导,完成正常系统编译和内核启动,能进入正常模式,且运行正常。
* 芯片需配置包含updater分区和misc分区的分区表。updater分区大小不小于32M。
# 1、OTA升级实现原理
## 1.1 OTA实现主要流程:
![](
https://devpress.csdnimg.cn/ad718f13314947e392838a1a420d9012.png
)
## 1.2 升级服务组件
升级服务组件是一个SA(System Ability), 由OHOS 的init 进程负责启动。
升级服务器引擎主要功能包括:
1、查找可用的升级包
2、下载升级包
3、设置/获取升级策略
4、触发升级
代码目录
```
base/update/updateservice # 升级服务代码仓目录
├── interfaces # 升级客户端接口目录
│ ├── kits # 对外接口封装目录
│ │ └── js # 提供给升级客户端应用的JS 接口目录
│ └── inner_api # SA 接口定义和封装目录
├── frameworks # 部件无独立进程的实现
│ └── js # JS API的实现
│ └── napi # napi代码实现
│ └── client # 升级客户端napi 接口目录
├── services # 独立进程的实现
│ ├── callback # 提供给升级客户端应用的callback接口目录
│ └── engine # 升级客户端引擎服务目录
│ ├── etc # 升级客户端引擎rc配置文件目录
│ ├── include # 升级客户端引擎头文件目录
│ ├── sa_profile # SA 配置文件目录
│ └── src # 升级客户端引擎源码目录
├── test # 测试代码目录
│ ├── unittest # 升级客户端UT代码目录
│ └── fuzztest # 升级客户端FT代码目录
├── BUILD.gn # 编译入口
└── bundle.json # 部件描述文件
```
JS接口说明
| **接口** | 说明 |
| ------------------- | ---------------------------------------------------------------------- |
| checkNewVersion | 检查是否有可用的升级包版本 |
| download() | 下载升级包 |
| upgrade() | 将升级命令写入到misc分区,最终调用reboot命令,进入到updater 子系统中。 |
| getNewVersionInfo() | 升级完成后,获取升级后的版本信息 |
| setUpgradePolicy | 设置升级策略 |
| getUpgradePolicy | 获取升级策略 |
使用说明
1,导入updateclient lib
```
import client from 'libupdateclient.z.so'
```
2,获取update对象
```
let updater = client.getUpdater('OTA');
```
3,获取新版本信息
```
updater.getNewVersionInfo(info => {
info "新版本信息"
});
```
4,检查新版本
```
updater.checkNewVersion(info => {
info "新版本信息"
});
```
5,下载新版本,并监听下载进程
```
updater.download();
updater.on("downloadProgress", progress => {
progress "下载进度信息"
});
```
6,启动升级
```
updater.upgrade();
updater.on("upgradeProgress", progress => {
progress "升级进度信息"
});
```
7,设置升级策略
```
updater.setUpgradePolicy(result => {
result "设置升级策略结果"
});
```
8,查看升级策略
```
updater.getUpgradePolicy(policy => {
policy "升级策略"
});
```
## 1.3 升级包安装组件
升级包安装组件运行在updater分区,其功能主要包括读取misc分区信息获取升级包状态,对升级包进行校验,确保升级包合法有效;然后从升级包中解析出升级的可执行程序,创建子进程并启动升级程序。具体升级的动作由升级脚本控制。
**图 1** 升级子系统架构图
![](
https://devpress.csdnimg.cn/7225e21e95cc4554b9c1a843bf4c645c.png
)
代码目录
```
base/update/updater/
├── resources # 升级子系统用户界面图片资源目录
├── services # 组件服务层代码目录
│ ├── applypatch # 升级包数据更新代码目录
│ ├── diffpatch # 差分还原代码目录
│ ├── etc # 启动相关配置文件目录
│ ├── flashd # flashd模式镜像写入和升级功代码目录
│ ├── fs_manager # 文件系统和分区管理代码目录
│ ├── hdi # 硬件相关接口定义
│ ├── include # 升级子系统头文件目录
│ ├── log # 升级子系统日志模块目录
│ ├── package # 升级包管理模块目录
│ ├── ptable_parse # 分区表解析代码目录
│ ├── script # 升级脚本管理目录
│ ├── ui # 升级ui界面代码目录
│ └── updater_binary # 升级可执行程序目录
├── interfaces
│ └── kits # 对外模块接口定义
└── utils # 升级子系统通用代码目录
└── include # 升级子系统通用函数头文件目录
```
使用说明
升级包安装组件运行在updater分区里,需要如下的操作
1、创建updater分区
updater是一个独立的分区,分区大小建议不小于20MB。updater分区镜像是ext4 格式文件系统。确保系统内核ext4 文件系统的config 是打开状态。
2、创建misc分区
misc 分区中存储了升级子系统在升级过程中需要的元数据(metadata),如升级命令,掉电续传记录等。 misc 分区的大小约1MB,是一个裸分区,无需制作文件系统, 升级子系统直接访问。
3、分区配置表
升级包安装组件在运行过程中,需要通过分区配置表操作分区。默认的分区配置表文件名是fstab.updater,在编译的时候,打包到升级包安装组件中。
4、升级包安装组件启动
updater分区的init 进程有单独的配置文件 init.cfg,升级包安装进程启动配置在该文件中。
5、升级包安装组件编译
a、在build/subsystem\_config.json文件添加配置。
如下:
```
"updater": {
"project": "hmf/updater",
"path": "base/update/updater",
"name": "updater",
"dir": "base/update"
},
```
b、 产品中添加需要编译的组件
以Hi3516DV300为例,在productdefine/common/products/Hi3516DV300.json 中添加updater:
```
"updater:updater":{},
```
6、updater分区镜像编译
编译配置在build仓下,build\_updater\_image.sh 脚本中,该脚本由OHOS 编译系统调用
## 1.4 配置MISC分区
OpenHarmony使用MISC分区保存启动时的指令,默认的MISC分区的结构体为:
```
struct UpdateMessage {
char command[32];
char update[1280];
char reserved[736];
};
```
command为当前的命令,update存放升级包路径,reserved存放保留信息。
## 1.5 镜像编译
使能镜像编译选项,编译脚本会将out/rk3568/packages/phone/updater文件夹作成updater.img镜像。先使用gzip工具压缩,然后使用cpio工具制作镜像。镜像格式为ASCII cpio archive (SVR4 with no CRC)。updater.img没有内核,以根文件系统挂载。out/rk3568/packages/phone/updater目录结构与根文件系统结构一致。过多添加文件到updater.img会导致镜像超过32M编译失败。
## 1.6 镜像启动流程
完整的启动流程如下:
![](
https://devpress.csdnimg.cn/8ed21eff862440cc83ff4329e0e63cb7.png
)
## 1.7 配置uboot和内核
uboot需要读取MISC分区的指令,如果command为updater,uboot能启动到updater模式。内核需要根据uboot的指令加载updater.img。
Updater 子系统与主系统共用同一个内核,但用户态是从不同的分区启动。
Misc 分区是裸盘,是主系统和updater 子系统的一个沟通介质。当主系统OTA service下载到升级包后,会将升级包的位置记录到Misc分区。系统重启后,将从updater 分区启动并进入Updater子系统。
updater模式启动与正常模式启动流程一致。当正常模式调通后,参考正常模式完成updater模式的调试。 updater.img镜像是ramdisk格式且没有内核,需要uboot先拉起内核,然后加载updater.img到内存,作为根文件系统挂载到内核。如果芯片不支持ramdisk格式,需要进一步适配。
如果缺少misc或updater分区是无法升级的,需要将其加上。
## 1.8 init服务启动
根文件系统挂载完成,会启动init服务,参考内核启动[内核启动]。 init启动引导组件对应的进程为init进程,是内核完成初始化后启动的第一个用户态进程。init进程启动之后,读取init.cfg配置文件,依次启动各关键系统服务进程。updater模式下的init组件功能与正常模式一致,但是updater模式会根据自身业务对配置文件进行精简,只保留必须的命令。 启动配置文件由以下配置文件组成:
* 与产品相关的配置文件 以RK3568为例,updater模式的init.cfg文件位于产品目录device/board/hihope/rk3568/updater下。init.cfg是启动的入口,通过import方式导入其他配置文件。init.rk3568.usb.cfg主要是USB和HDC相关的配置,与产品特性有关。
* updater\_common.cfg updater模式通用的启动,代码目录。updater\_common.cfg包含了多个基础服务,这些服务与产品解耦,依赖系统组件。
* 复用正常模式的配置文件 为了降低耦合复用正常模式的配置文件。这部分配置文件适用于正常模式和updater模式,不需要针对性适配。通过BUILD.g设置复制到updater.img,通过import方式调用。 init.usb.cfg:HDC相关的配置 init.usb.configfs.cfg :USB相关的配置 faultloggerd.cfg:faultloggerd服务配置文件,用于捕获updater模式的crash异常 hilogd.cfg:hilogd配置文件,用于打印OpenHarmony所有组件的日志。
配置文件执行顺序:默认依序执行执行pre-init,init,post-init。 常见的设置:
* ueventd服务:pre-init阶段启动,所有组件的依赖项,不同产品ueventd配置不一样,建议放产品目录
* 软连接:通过软连接方式将产品的路径转换为openharmony的路径。
* 挂载分区:updater模式启动阶段不挂载分区,升级流程中根据业务场景选择性挂载。
* 设置文件权限:如果二进制没有执行权限,服务会无法正常启动,需要在服务启动前设置权限。
* 执行脚本:updater模式部分场景不挂载data分区,出现异常无法保存日志,会调用脚本保存日志。
## 1.9 升级服务启动
完成配置文件的适配,单板运行时会根据配置文件顺序依次执行配置中的命令。最终拉起升级子系统核心服务updater进程。updater服务启动以后,屏幕会显示UI界面,进行安装包升级,恢厂,重启等功能。升级服务功能如下所示:
![](
https://devpress.csdnimg.cn/1e4c463c3c0944598b744816145aadc8.png
)
初次适配会出现进程功能缺失等情况,参考如下方法进行调试
* 使用ps -A命令查询进程是否启动。
* 使用dmesg查看内核日志。
* 使用hilog和faultlogger查看进程是否出现crash。
* 手动拉起服务,如果服务能启动,检查启动配置文件是否正确。
# 2、OTA升级适配
正常模式有两个子程序用于操作misc分区。 执行write\_updater命令向misc分区的update字段写入指令,指令格式参考参考write\_updater源码base/update/updater/utils/write\_updater.cpp。 执行reboot updater命令,向misc分区的command写入指令,单板会重新启动,重启过程中uboot读取misc分区的命令,从command命令判断当前要进入updater模式,依次加载内核和updater.img,完成从正常模式到updater模式的启动流程。 updater进程启动后读取update字段的命令,获取升级包的路径,单板进入升级流程,直至升级成功重启。
## 2.1 配置uboot和内核
uboot需要读取MISC分区的指令,如果command为updater,uboot能启动到updater模式。内核需要根据uboot的指令加载updater.img。
Updater 子系统与主系统共用同一个内核,但用户态是从不同的分区启动。
Misc 分区是裸盘,是主系统和updater 子系统的一个沟通介质。当主系统OTA service下载到升级包后,会将升级包的位置记录到Misc分区。系统重启后,将从updater 分区启动并进入Updater子系统。
updater模式启动与正常模式启动流程一致。当正常模式调通后,参考正常模式完成updater模式的调试。 updater.img镜像是ramdisk格式且没有内核,需要uboot先拉起内核,然后加载updater.img到内存,作为根文件系统挂载到内核。如果芯片不支持ramdisk格式,需要进一步适配。
如果缺少misc或updater分区是无法升级的,需要将其加上。misc分区建议配置大小为1M,updater分区建议配置大小为32M以上。
## 2.2 升级镜像需要的fstab配置
执行升级的时候,如果没有在该文件中配置对应的镜像,是无法升级成功的。
./device/board/hihope/rk3568/updater/config/fstab.updater
![](
https://devpress.csdnimg.cn/4191e73bedbc4a94a1ab851e45261c2d.png
)
## 2.3 updater模式界面
正常模式只输入reboot updater命令,进入updater模式界面。此模式可以进行SD卡升级。
# 3、升级包制作工具
升级包制作工具是使用python开发,运行在PC端用来制作升级包的工具,功能主要包括:全量升级包制作、差分升级包制作以及变分区升级包制作。它首先会打包各个升级镜像,然后对升级包进行签名,同时生成升级包执行脚本,最后制作出升级包。
* 全量升级包制作:升级包中只包括镜像全量升级相关数据,用于镜像全量升级;
* 差分升级包制作:升级包中只包括镜像差分升级相关数据,用于镜像差分升级;
* 变分区升级包:升级包中包括分区表、镜像全量数据,用于变分区处理和变分区后的镜像恢复。
代码目录
```
/base/update/packaging_tools
├── lib # 制作升级包工具依赖库目录
├── blocks_manager.py # BlocksManager类定义,用于block块管理
├── build_update.py # 差分包制作工具入口代码,入口参数定义
├── build_pkcs7.py # 升级包签名
├── create_update_package.py # 升级包制作
├── gigraph_process.py # 生成Stash,重置ActionList的顺序
├── image_class.py # 全量镜像、稀疏镜像解析处理
├── log_exception.py # 全局log系统定义,自定义exception
├── patch_package_process.py # 差分镜像处理,Block差分获取patch差异
├── script_generator.py # 升级脚本生成器
├── transfers_manager.py # 创建ActionInfo对象
├── unpack_update_package.py # 升级包反解
├── update_package.py # 升级包格式管理、升级包写入
├── utils.py # Options管理,其他相关功能函数定义
└── vendor_script.py # 厂商升级流程脚本扩展
```
约束
工具运行环境配置:
* Ubuntu18.04或更高版本系统;
* python3.5及以上版本;
* python库xmltodict, 解析xml文件,需要单独安装;
使用说明
* bsdiff可执行程序,差分计算,比较生成patch;
* imgdiff可执行程序,差分计算,针对zip、gz、lz4类型的文件,对比生成patch;
* e2fsdroid可执行程序,差分计算,用于生成镜像的map文件。
工具参数配置说明:
# 4、 升级包制作流程
## 4.1 升级包简介
升级包里面有两个文件,包括build\_tools.zip 和update.bin。
build\_tools.zip:用来辅助升级的工具,包括升级的可执行文件updater\_binary和升级脚本,镜像描述
update.bin:TLV编码的文件,所有的升级内容按照TLV格式序列化存储,最终生成update.bin
工具对update.bin 和最终生成的升级包(zip 压缩文件)分别进行签名。
## 4.2 制作全量升级包
1.首先在base\\update\\packaging\_tools目录下,创建文件夹target\_package和output\_package。
2.进入 cd target\_package文件夹,创建 mkdir updater\_config。
3.进入 cd updater\_config 文件夹,
从device\\board\\hisilicon\\hispark\_taurus\\linux\\updater\\config路径下,拷贝BOARD.list和VERSION.mbn到base\\update\\packaging\_tools\\target\_package\\updater\_config。
从device\\board\\hisilicon\\hispark\_taurus\\linux\\system下拷贝updater\_specified\_config.xml到base\\update\\packaging\_tools\\target\_package\\updater\_config。
3.从out\\rk3568\\packages\\phone\\images路径所有文件拷贝至base\\update\\packaging\_tools\\target\_package。
从out\\rk3568\\packages\\phone\\system\\bin路径下拷贝文件updater\_binary 至base\\update\\target\_package。
4.将文件base\\update\\updater\\test\\unittest\\test\_data\\src\\rsa\_private\_key2048.pem拷贝至base\\update\\packaging\_tools下
文件说明:
BOARD.list:存放当前升级包支持的产品list
![](
https://devpress.csdnimg.cn/43f2608d2f36479ebb309c69ba7104d2.png
)
如果是rk3568,请在文件中添加RK3568
VERSION.mbn:存放当前升级包所支持的版本范围
![](
https://devpress.csdnimg.cn/230eb029222d410eb1748d2324ffa979.png
)
查询当前设备软件版本,rk3568开机后,点击设置,点击关于设备->软件版本,然后添加到文件里面去。
updater\_specified\_config.xml:分区表文件,结构参考下图
![](
https://devpress.csdnimg.cn/c5c1d8ddb2294eca8ed0b3371b64e01c.png
)
updater\_specified\_config.xml 组件配置文件节点说明
![](
https://devpress.csdnimg.cn/a2fa9de4812b451a8217555369fce0d4.png
)
在base\\update\\packaging\_tools终端执行升级包制作命令: `python3 build_update.py ./target_package/ ./output_package/ -pk ./rsa_private_key2048.pem`
![](
https://devpress.csdnimg.cn/c9a48d71ab4543f19b2f1b8aa8e56594.png
)
## 4.3 手动命令触发全量包升级
1. 进入设备:hdc\_std shell
2. 切换到 data 文件夹:cd data
3. 新建 updater 目录:mkdir updater
4. 退出设备:exit
5. 传输升级包:hdc\_std file send + 升级包地址 /data/updater/updater.zip (在设备侧的文件明一定要是updater.zip)
6. 进入设备:hdc\_std shell
7. 输入指令:
write\_updater updater /data/updater/updater.zip
8. 触发升级:
reboot updater
获取版本号命令:param get hw\_sc.build.os.version
升级查看日志文件
1. 查看日志文件列表:ls -l data/updater/log
2. 打开日志文件:cat data/updater/log/updater\_log
3. 升级成功标志文件:data/updater/updter\_result
## 4.4 升级包安装
升级包安装是升级子系统的核心功能,主要包括:
1.从misc分区获取升级命令,根据不同的命令执行不同的任务。
2.对升级包进行解压和合法性效验。
3.启动升级进程,并解析出升级脚本。
4.根据升级脚本安装各个组件包。
5.完成升级后,进行后处理。如清理升级包,记录升级状态等。
# 5、OTA升级UX界面适配
## 5.1 打开升级界面 `UI`开关。
```
// base/update/updater/updater_default_cfg.gni
declare_args() {
updater_cfg_file = ""
updater_ui_support = true
}
```
## 5.2 修改产品init编译配置项
需要产品 `init`编译配置项增加以下配置
```
// device/board/hihope/rk3568/updater/BUILD.gn
...
updater_usb_init_cfg_path = "//base/startup/init/services/etc/init.usb.cfg"
updater_init_usb_configfs_path_cfg =
"//drivers/peripheral/usb/cfg/init.usb.configfs.cfg"
updater_faultloggerd_cfg =
"//base/hiviewdfx/faultloggerd/services/config/faultloggerd.cfg"
updater_hilog_cfg = "//base/hiviewdfx/hilog/services/hilogd/etc/hilogd.cfg"
ohos_prebuilt_etc("updater_hilog.cfg") {
source = "${updater_hilog_cfg}"
install_images = [ "updater" ]
part_name = "huanglong_sdk"
}
ohos_prebuilt_etc("updater_faultloggerd.cfg") {
source = "${updater_faultloggerd_cfg}"
install_images = [ "updater" ]
part_name = "huanglong_sdk"
}
ohos_prebuilt_etc("updater_init_usb.cfg") {
source = "${updater_usb_init_cfg_path}"
install_images = [ "updater" ]
part_name = "huanglong_sdk"
}
ohos_prebuilt_etc("updater_init_usb_configfs.cfg") {
source = "${updater_init_usb_configfs_path_cfg}"
install_images = [ "updater" ]
part_name = "huanglong_sdk"
}
...
group("init_configs") {
deps = [
":signing_cert.crt",
":init_fstab_ramdisk",
":init_fstab_vendor",
":init_fstab_updater",
":updater_init.cfg",
":updater_init.wudangstick.usb.cfg",
":updater_faultloggerd.cfg",
":updater_hilog.cfg",
":updater_init_usb.cfg",
":updater_init_usb_configfs.cfg"
]
}
```
## 5.3 UX界面资源配置项
在\`base/update/updater/resources 下配置对应产品的图片资源和界面配置文件。
![img](
https://devpress.csdnimg.cn/6729793f1b724f4db19a5d13d73f1f33.png
)
## 5.4 更改升级UX界面配置文件名
base/update/updater/resources/rk3568/`的目录`pages文件夹下,更改 `config.json`文件配置。
```
// base/update/updater/resources/rk3568/pages/config.json
{
"config" : "/resources/pages/rk3568.json" //界面文件
}
```
## 5.5 更改base/update/updater/resources 编译配置文件。
```
// base/update/updater/resources/BUILD.gn
...
if (product_name == "rk3568") { // 更改为对应的产品名称
updater_resources_list += [
...
"${product_name}/pages/config.json",
"${product_name}/pages/rk3568.json", // 更改对应文件名
"${product_name}/pages/confirm.json",
...
]
}
...
```
# 6、示例服务器开发概述
**## 基本概念**
- 搜包服务:升级服务(UpdateService)提供的服务能力之一,依赖支持TCP和SSL协议的服务器。
- 搜包服务器:即支持搜包服务的通过TCP连接并支持SSL协议的服务器,本概述提及的升级服务示例服务器即是符合要求的搜包服务器之一。
- 下载服务器:普通的HTTP服务器即可满足下载服务器的要求。
- update.serverip.search:系统参数,指升级服务(UpdateService)侧配置的搜包服务器IP地址,默认值:127.0.0.1。
**## 约束与限制**
- 服务器返回报文格式Json示例,注意verifyInfo字段是升级包的sha256值,size字段是升级包的大小,单位为字节。
{
"searchStatus": 0,
"errMsg": "success",
"checkResults": [{
"versionName": "versionNameSample",
"versionCode": "versionCodeSample", 升级包版本号
"verifyInfo": "verifyInfoSHA256Value1234567", 升级包的sha256
"size": 1234567, 升级包大小
"packageType": 1,
"url": "[http://serverAddressSample/packageNameSample.fileTypeSample](http://serveraddresssample/packageNameSample.fileTypeSample?login=from_csdn)",
"descriptPackageId": "abcdefg1234567ABCDEFG"
}],
"descriptInfo": [{
"descriptPackageId": "abcdefg1234567ABCDEFG",
"content": "This package is used for update."
}]
}
示例服务器部署到设备上,客户端就可以直接通过127.0.0.1访问
1. 考虑将服务器生成为一个可执行的二进制文件,我们将模块放到base/update/updater/updateservice下面,制作build.gn文件,需要一些相关依赖。
![img](
https://devpress.csdnimg.cn/0b197b46fb7448f199e964123e27a117.png
)
编译后就会生成二进制文件,可以将文件推到设备上运行。
1. 参考下面文档生成服务器对应的crt和pem文件,和测试服务器文件推到开发板同一个目录。
2. 使用命令chmod 给二进制文件添加可执行权限。
out目录下编译生成的文件路径:
![](
https://devpress.csdnimg.cn/a0aaeb53bf3f4745bb10f6f99f671a03.png
)
文档参考目录:
openharmony/docs/zh-cn/application-dev/device/sample-server-guidelines.md
openharmony/docs/zh-cn/application-dev/device/sample-server-overview.md
[/md]
作者:
igolang
时间:
2023-11-9 08:50
[md]感谢分享👍
[/md]
作者:
Laval社区小助手
时间:
2023-11-14 15:14
回复
igolang
: 不客气。
作者:
Mart!nHu
时间:
2023-11-15 11:40
[md]差分包制作和升级步骤能不能也分享下🎉️
[/md]
作者:
martinhu
时间:
2023-11-15 19:06
[md]文档版本并非最新,updater\_specified\_config.xml fileVersion已更新为2。
https://gitee.com/openharmony/do ... subsys-ota-guide.md
[/md]
欢迎光临 OpenHarmony开发者论坛 (https://forums.openharmony.cn/)
Powered by Discuz! X3.5