Skip to content

# 6.5. J6X OTA 实现详解

## 6.5.1. J6X OTA 升级机制

### 6.5.1.1. AB无缝更新

J6X OTA支持android的AB无缝更新机制来对系统AB分区进行更新。

下图是AB更新时各个阶段两个slot的状态，详细原理可参考:https://source.android.google.cn/docs/core/ota?hl=zh-cn

### 6.5.1.2. back升级

在J6X中HSM相关分区是back类型的分区，back分区一般启动总是会从主分区启动，只有当启动失败时才会依次进入备份分区启动，故需要采用back的方式来对他们进行升级。

- back分区只升级主分区，主分区升级并验证成功后，将内容同步到备份分区。

- 主分区升级成功后，重启验证。若验证失败，进入back分区。若验证成功，将主分区内容同步到back分区，并校验md5值。

## 6.5.2. 分区烧写方式

J6X OTA以分区为单位来进行升级，每个要升级的分区都有自己的镜像，升级时主要是将该镜像写入到外部存储器对应的分区上。在镜像类型上又分为全镜像与差分镜像两种形式。

### 6.5.2.1. 全镜像升级

- 全镜像指的是提供的目标分区完整镜像，升级时将镜像直接写到外部存储器对应分区的方式。

### 6.5.2.2. 差分镜像升级

- 差分镜像是通过差分算法对原始镜像和目标镜像进行差分计算得到的镜像。差分一般会提取目标镜像与原始镜像之间的差异信息，精简冗余信息。通过差分得到的镜像大小一般会远远小于目标镜像（具体大小取决于原始与目标之间的差异度，差异越小，镜像越小），可用于节省流量。

- 当差分升级时，J6X OTA会根据差分镜像和板端原始分区数据通过逆差分还原成目标镜像，并写入到对应的外部存储器分区，完成最终的升级。

- J6X 上使用的是开源的差分算法工具hdiffz/hpatch，详细信息请参考:https://github.com/sisong/HDiffPatch。

## 6.5.3. J6X OTA 安全保护措施

### 6.5.3.1. 镜像防回滚保护

OTA 升级支持进行镜像防回滚保护，目的为了防止OTA 升级到低于当前设备antirollback 之前的版本。

- OTA 升级包中的antirollback 版本号：通过解析镜像头部的antirollback 版本号获取。

- 升级设备的antirollback 版本号：存储于eFuse中。

若需要修改镜像的antirollback版本，则需在源码顶层目录执行 make menuconfig 并修改 HOST_ANTIROLLBACK_VER

当前默认关闭镜像antirollback校验，若需要使能或跳过某镜像的antirollback版本校验，则需要修改 device/horizon/j6/partition_config_files/sub_config 下的分区配置，加入 “have_anti_ver”: true 或 “have_anti_ver”: false 这一选项。

### 6.5.3.2. OTA版本校验

除了镜像的防回滚之外，J6X OTA也支持升级前对升级包的version版本校验，验证升级包的版本是否低于系统的版本，如果低于系统版本，则停止升级。

- OTA 升级包中的版本：OTA配置文件data.json中包含版本信息字段sys_version。

- 升级设备的version版本号：目标板子上含有/etc/version文件，通过解析这个文件得到当前系统的version版本。

注：如果用户拥有root权限，可通过修改 echo 20 > /etc/version来临时解锁降级的能力。

### 6.5.3.3. 分区校验

J6X OTA支持对镜像中的fpt/GPT分区文件校验，通过与当前系统的fpt/GPT分区进行对比，验证fpt/GPT分区表是否有调整，如果fpt/GPT分区有调整，则停止升级。

- OTA升级包含有通过编译系统生成的分区文件gpt.conf，具体内容格式如下：

    fpt:0:262143:0
    misc:262144:524287:0
    HB_APDP:524288:786431:0
    ddr_quickboot:786432:1048575:0
    HSM_FW:1048576:1572863:0
    HSM_FW_bak:1572864:2097151:0
    HSM_RCA_a:2097152:2359295:0
    ...

- 由于J6X 分区支持最后一个分区的自动扩展，其结束地址会动态变化，所以校验GPT只校验到userdata分区，且最后一个分区一般不含镜像，不影响正常使用。

## 6.5.4. Recovery升级

J6X 使用Recovery镜像防止变砖。

Recovery镜像中包含sbl到kernel启动链路中所有需要的镜像和一个小的rootfs。该rootfs中包含了客户OTA Service, libupdate.so及相关依赖。 当ab slot全部损坏或外围电路要求进入recovery模式时，HSM会通过recovery分区中的镜像启动J6X。 进入recovery镜像后，客户OTA Service应发起升级，进行变砖恢复。

## 6.5.5. 典型升级流程

1. OTA Service 从云端下载并校验升级包，并调用otaInitLib初始化动态库。

2. 调用otaRequestStart发起升级。该API会解压升级包中的ota_process程序，并fork一个进程，执行ota_process程序进行实际烧写。同时，该API还会创建文件锁（防止同时存在多次升级）、创建pipe文件（用于和ota_process通信）。另外，该API还会创建一个线程，用于定期读取pipe，获取实时升级进度、升级结果、升级分区等信息。

3. 子进程升级阶段，OTA Service可以调用otaGetResult获取升级结果、调用otaGetProgress获取升级进度、调用otaGetUpdatingImageName获取正在升级的镜像。

4. 当otaGetResult返回OTA_UPGRADE_SUCCESS时，代表镜像烧写成功，需要进入校验阶段。

5. 调用otaSetPartition将下次启动分区设置为对向分区，并执行重启流程。

6. 重启后，OTA Service 调用otaGetOwnerFlag获取升级owner，如果owner为OTA Service，则 OTA Service 为该次升级的校验负责，进入校验流程。

7. 调用otaCheckUpdate，获取升级结果。该API主要会检查镜像是否完整写入、是否从期望AB slot、Backup slot启动。

8. 调用otaMarkOTASuccessful，标记当前分区启动成功。该API操作AB状态机，将本slot标记为boot_successful，保证后续从该slot启动。若在此步骤前发生任何重启，则下次将从旧版本镜像所在slot启动，升级失败。同时，本步骤中会更新antirollback版本。

9. 调用otaPartitionSync，进行bak分区、ab分区同步。

10. 调用otaClearFlags清除升级标记，结束升级。