first commit
This commit is contained in:
commit
669f49b1d6
342 files changed
+320811
No files matched your search
@@ -0,0 +1,422 @@
|
||||
# PX3 升级流程说明
|
||||
|
||||
> 范围:仅梳理 PX3 本地 MPU 升级和 MCU 升级
|
||||
> 代码:`D:\zdCode\zhongqi_px3`
|
||||
> 分支:`zhongqi_th7_px3_plus_security`,HEAD `8497c2da8`
|
||||
|
||||
## 1. 总体说明
|
||||
|
||||
PX3 当前有两条升级链路:
|
||||
|
||||
| 类型 | 触发方式 | 新版包 | 旧版兼容 |
|
||||
| -------- | ------------ | ---------------- | ---------------------------- |
|
||||
| MPU/系统升级 | 开机或介质挂载后自动扫描 | `update_mpu.zip` | 受属性控制的 `update.img` |
|
||||
| MCU 升级 | 工程菜单手动触发 | `update_mcu.zip` | ZIP 不存在时兼容 `m3/cortex-*.bin` |
|
||||
|
||||
如果 `update_mpu.zip` 就走验签流程,如果有 `update.img` 就走老的升级流程,
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
PX3 计划保留的 MPU 新旧兼容与 RK3568 不同:
|
||||
|
||||
- RK3568:外层都叫 `update.zip`,根据包内是否存在 `ValidationFile.ini` 判断新旧格式。
|
||||
- PX3 业务目标:按外层文件名分流,优先级是 `update_mpu.zip → update.img`。
|
||||
- 当前 `1224` 源码尚未完全符合该目标:扫描函数仍主动检查 `update.zip`,独立裸 `update.img` 默认还会被属性开关拦截。
|
||||
|
||||
---
|
||||
|
||||
## 2. MPU 升级流程
|
||||
|
||||
### 2.1 触发和扫描
|
||||
|
||||
`RKUpdateReceiver` 在以下场景启动本地升级扫描:
|
||||
|
||||
| 场景 | 延时 |
|
||||
|---|---:|
|
||||
| 系统启动完成 `BOOT_COMPLETED` | 20 秒 |
|
||||
| 存储介质挂载 `MEDIA_MOUNTED` | 7 秒 |
|
||||
| 特定 USB 状态变化 | 5 秒 |
|
||||
|
||||
扫描目录:
|
||||
|
||||
```text
|
||||
/data/media/0/
|
||||
Environment.getExternalStorageDirectory()/
|
||||
/mnt/external_sd0/
|
||||
/mnt/usb_storage/
|
||||
```
|
||||
|
||||
如果根目录没有命中,还会扫描 `/mnt/usb_storage` 的一级子目录。
|
||||
|
||||
### 2.2 MPU 业务目标优先级
|
||||
|
||||
| 优先级 | 文件 | 处理方式 |
|
||||
|---:|---|---|
|
||||
| 1 | `update_mpu.zip` | 解压、验签内层 `update.img`、产品检查、RK image 升级 |
|
||||
| 2 | `update.img` | 属性允许时执行产品检查和 RK image 升级 |
|
||||
| 3 | 其他文件 | 不处理 |
|
||||
|
||||
服务发现第一个候选文件后立即返回。
|
||||
|
||||
### 2.3 当前源码与目标的差异
|
||||
|
||||
当前 `getValidFirmwareImageFile()` 实际扫描顺序为:
|
||||
|
||||
```text
|
||||
update_mpu.zip → OTA_PACKAGE_FILE(默认 update.zip)→ update.img
|
||||
```
|
||||
|
||||
另外,`1224` 版本处理独立裸 `update.img` 时会读取:
|
||||
|
||||
```text
|
||||
persist.sys.update.show
|
||||
```
|
||||
|
||||
- 属性为 `false`:直接忽略裸 `update.img`。
|
||||
- 属性为 `true`:才允许继续产品检查和升级。
|
||||
- 当前仓库中,唯一把该属性设置为 `true` 的位置在 `update_mpu.zip` 处理分支。
|
||||
- `1009`、`1010` 等早期压缩版本没有该属性拦截。
|
||||
|
||||
因此,当前源码不能直接表述为“已经实现 `update_mpu.zip → update.img` 两级兼容”。要达到业务目标,还需要停止扫描 `update.zip`,并明确恢复裸 `update.img` 的允许条件。
|
||||
|
||||
### 2.4 新版 `update_mpu.zip`
|
||||
|
||||
包结构:
|
||||
|
||||
```text
|
||||
update_mpu.zip
|
||||
├── update.img
|
||||
└── ValidationFile.ini
|
||||
```
|
||||
|
||||
`ValidationFile.ini` 当前读取:
|
||||
|
||||
```ini
|
||||
sign=<十六进制 RSA 签名>
|
||||
```
|
||||
|
||||
流程:
|
||||
|
||||
```text
|
||||
检测到 update_mpu.zip
|
||||
↓
|
||||
设置 persist.sys.update.show=true
|
||||
↓
|
||||
解压到 update_mpu.zip 所在目录
|
||||
↓
|
||||
读取 update.img 和 ValidationFile.ini
|
||||
↓
|
||||
计算 update.img 的 SHA-256
|
||||
↓
|
||||
使用硬编码 RSA-2048 公钥和 SHA256withRSA 验签
|
||||
↓
|
||||
JNI 读取 update.img 产品名
|
||||
↓
|
||||
与 ro.product.model 比较
|
||||
↓
|
||||
弹出升级确认页
|
||||
↓
|
||||
用户确认
|
||||
↓
|
||||
RecoverySystem.installRKimage()
|
||||
↓
|
||||
写入 /cache/recovery/last_flag 和 command
|
||||
↓
|
||||
执行 sync,等待 2 秒
|
||||
↓
|
||||
重启 Recovery 安装 update.img
|
||||
```
|
||||
|
||||
Recovery 命令:
|
||||
|
||||
```text
|
||||
--update_rkimage=<update.img完整路径>
|
||||
--locale=<当前语言>
|
||||
```
|
||||
|
||||
当前验签失败分支缺少 `return`,仍会打开确认页,并把外层 `update_mpu.zip` 当成标准 OTA 包再次校验。这是现有缺陷,不是兼容流程。
|
||||
|
||||
### 2.5 旧版裸 `update.img`
|
||||
|
||||
```text
|
||||
检测到 update.img
|
||||
↓
|
||||
读取 persist.sys.update.show
|
||||
├── false:忽略,不弹确认页
|
||||
└── true:继续
|
||||
↓
|
||||
检查镜像产品名是否匹配 ro.product.model
|
||||
↓
|
||||
用户确认
|
||||
↓
|
||||
installRKimage()
|
||||
↓
|
||||
重启 Recovery 安装
|
||||
```
|
||||
|
||||
裸 `update.img` 没有新增 RSA 验签,只做产品名检查。
|
||||
|
||||
### 2.6 MPU 结果处理
|
||||
|
||||
服务下次启动时读取:
|
||||
|
||||
```text
|
||||
/cache/recovery/last_flag
|
||||
```
|
||||
|
||||
| 标记 | 含义 |
|
||||
|---|---|
|
||||
| `success$path=...` | Recovery 报告升级成功 |
|
||||
| `updating$path=...` | 上次升级未形成成功状态 |
|
||||
|
||||
当前结果流程尚未闭环:
|
||||
|
||||
- 成功/失败提示 Activity 的启动代码被注释。
|
||||
- 没有统一结果广播。
|
||||
- 升级包删除没有稳定执行。
|
||||
- 新版包验签后用户取消,升级锁没有释放。
|
||||
- Recovery 写回 `last_flag` 的实现不在当前项目中。
|
||||
|
||||
---
|
||||
|
||||
## 3. MCU 升级流程
|
||||
|
||||
### 3.1 页面入口
|
||||
|
||||
```text
|
||||
Pro 版本设置页
|
||||
↓
|
||||
在硬件版本位置 3 秒内连续点击 10 次
|
||||
↓
|
||||
工程菜单 ProjectMenuActivity
|
||||
↓
|
||||
升级菜单 UpgradeMainActivity
|
||||
↓
|
||||
选择“M3程序升级”
|
||||
↓
|
||||
ZhongQiM3UpdateActivity
|
||||
↓
|
||||
用户确认
|
||||
↓
|
||||
IM0ManagerService.sendUpdateRequest(type, flashType)
|
||||
↓
|
||||
ImplM0ManagerService
|
||||
↓
|
||||
MonitorM0Update.sendUpdateRequest()
|
||||
```
|
||||
|
||||
升级通过 Binder 发起。广播只用于 MCU 返回最终结果后通知页面。
|
||||
|
||||
### 3.2 介质和文件
|
||||
|
||||
| 介质 | `flashType` | 文件路径 |
|
||||
|---|---:|---|
|
||||
| U 盘 | `0` | `/mnt/usb_storage/update_mcu.zip` |
|
||||
| TF 卡 | `1` | `/mnt/external_sd0/update_mcu.zip` |
|
||||
|
||||
当前正常 UI 没有传入 `FLASHTYPE=1`,所以实际默认走 U 盘。
|
||||
|
||||
代码保留 TF 卡分支,但页面状态检测历史上使用 `/mnt/external_sd`,通讯服务读取 `/mnt/external_sd0`,两边路径不一致。
|
||||
|
||||
`update_mcu.zip` 只在介质根目录查找,不递归搜索子目录。
|
||||
|
||||
### 3.3 包结构
|
||||
|
||||
```text
|
||||
update_mcu.zip
|
||||
├── cortex-gdm4.bin
|
||||
├── cortex-m3.bin
|
||||
└── ValidationFile.ini
|
||||
```
|
||||
|
||||
根据设备类型,实际刷写文件是 `cortex-gdm4.bin` 或 `cortex-m3.bin`。
|
||||
|
||||
### 3.4 解压和验签
|
||||
|
||||
```text
|
||||
开始 sendUpdateRequest()
|
||||
↓
|
||||
删除 /sdcard/zhongqi_mcu_update/
|
||||
↓
|
||||
解压 update_mcu.zip 到该目录
|
||||
↓
|
||||
根据 MCU 版本选择实际目标固件
|
||||
↓
|
||||
计算 SHA-256
|
||||
↓
|
||||
读取 ValidationFile.ini 中的 sign
|
||||
↓
|
||||
使用硬编码 RSA-2048 公钥和 SHA256withRSA 验签
|
||||
├── 失败:返回 -2
|
||||
└── 成功:选择实际固件并进入协议传输
|
||||
```
|
||||
|
||||
当前算法先计算文件 SHA-256,再把摘要传给 `SHA256withRSA`,实际相当于:
|
||||
|
||||
```text
|
||||
RSA-Sign(SHA256(SHA256(payload)))
|
||||
```
|
||||
|
||||
制包工具必须使用相同的双重摘要方式。
|
||||
|
||||
### 3.5 固件选择
|
||||
|
||||
页面选择升级类型:
|
||||
|
||||
| MCU 版本 | 升级类型 |
|
||||
|---|---:|
|
||||
| `110px02m3`、`110rv01m3` | `0x01` |
|
||||
| `ae6501` | `0x0F` |
|
||||
| 其他版本 | `0x1F` |
|
||||
|
||||
通讯服务选择实际文件:
|
||||
|
||||
| MCU 版本 | 实际传输文件 |
|
||||
|---|---|
|
||||
| `110px02m3`、`110rv01m3` | `cortex-m3.bin` |
|
||||
| 其他情况 | `cortex-gdm4.bin` |
|
||||
|
||||
当前工作区已改为使用同一个目标文件名完成验签和传输:M3 设备验签并传输 `cortex-m3.bin`,其他设备验签并传输 `cortex-gdm4.bin`。页面按 `-` 分割版本字符串后判断,通讯服务直接比较原始版本字符串,这个差异仍需后续统一。
|
||||
|
||||
### 3.6 MCU 协议
|
||||
|
||||
| 消息号 | 名称 | 作用 |
|
||||
|---:|---|---|
|
||||
| `0xE1` | `MSG_REQUEST_UPDATE` | MCU 主动请求升级 |
|
||||
| `0xE2` | `MSG_SEND_UPDATE_REQUEST` | 主机发送固件总长度 |
|
||||
| `0xE3` | `MSG_REQUEST_UPDATE_DATA` | MCU 按偏移请求固件数据 |
|
||||
| `0xE4` | `MSG_RECV_UPDATE_RESULT` | MCU 返回最终结果 |
|
||||
|
||||
主时序:
|
||||
|
||||
```text
|
||||
Android 完成解压和验签
|
||||
↓
|
||||
E2:主机发送固件总长度
|
||||
↓
|
||||
MCU 返回状态和最大分包长度
|
||||
↓
|
||||
E3:MCU 发送 offset(4B) + length(2B)
|
||||
↓
|
||||
主机按偏移读取并返回固件数据
|
||||
↓
|
||||
重复 E3 直到传输完成
|
||||
↓
|
||||
MCU 校验并执行升级
|
||||
↓
|
||||
E4:MCU 返回最终结果
|
||||
↓
|
||||
主机回复 ACK
|
||||
↓
|
||||
通讯服务发送 ACTION_M0_UPDATE_FILE 广播
|
||||
↓
|
||||
升级页面显示结果
|
||||
```
|
||||
|
||||
收到 MCU 主动 E1 后,当前代码会再次删除临时目录、解压、验签并发送 E2,可能与已经开始的 Binder 升级会话冲突。
|
||||
|
||||
### 3.7 状态码
|
||||
|
||||
E2 阶段:
|
||||
|
||||
| 返回值 | 含义 |
|
||||
|---:|---|
|
||||
| `-2` | ZIP 不存在、验签失败或目标固件不可读 |
|
||||
| `-1` | 发送失败或等待响应超时 |
|
||||
| `0` | MCU 不支持升级 |
|
||||
| `1` | MCU 已准备好,开始传输 |
|
||||
| `2` | 固件长度超限 |
|
||||
|
||||
E4 最终结果:
|
||||
|
||||
| 返回值 | 含义 |
|
||||
|---:|---|
|
||||
| `1` | 升级成功 |
|
||||
| `2` | 固件校验和错误 |
|
||||
| `3` | 版本错误或固件非法 |
|
||||
| `4` | 文件或数据获取失败 |
|
||||
|
||||
E2 成功响应当前没有检查至少包含 3 字节,截断响应可能导致数组越界。
|
||||
|
||||
### 3.8 MCU 新旧兼容
|
||||
|
||||
历史裸固件路径:
|
||||
|
||||
```text
|
||||
<介质根目录>/m3/cortex-m3.bin
|
||||
<介质根目录>/m3/cortex-gdm4.bin
|
||||
```
|
||||
|
||||
当前工作区已恢复历史裸固件路径。
|
||||
|
||||
| 输入 | 当前行为 |
|
||||
|---|---|
|
||||
| 合法 `update_mcu.zip` | 解压、验签、传输 |
|
||||
| 非法 `update_mcu.zip` | 返回失败,不回退裸 bin |
|
||||
| ZIP 不存在,存在 `m3/cortex-m3.bin` | M3 设备使用旧版文件 |
|
||||
| ZIP 不存在,存在 `m3/cortex-gdm4.bin` | GDM4 设备使用旧版文件 |
|
||||
| ZIP 与裸 bin 同时存在 | 只处理 ZIP |
|
||||
|
||||
PX3 当前分支不包含 RK3568 的 `446193a73` 新旧包兼容提交。
|
||||
|
||||
---
|
||||
|
||||
## 4. 当前待完善点
|
||||
|
||||
### MPU
|
||||
|
||||
1. 将未跟踪的 `ZQ_TH7_RKUpdateService` 纳入正式源码和构建基线。
|
||||
2. 从业务扫描流程中移除 Rockchip 遗留 `update.zip` 分支。
|
||||
3. 明确恢复裸 `update.img` 时对 `persist.sys.update.show` 的处理方式。
|
||||
4. 验签失败后立即结束,不得回退裸 `update.img`。
|
||||
5. 使用安全解压和私有暂存目录,保证验签文件与安装文件一致。
|
||||
6. 补齐取消、异常、Recovery 结果和升级包清理流程。
|
||||
|
||||
### MCU
|
||||
|
||||
1. 统一页面和通讯服务的 MCU 版本解析。
|
||||
2. 增加升级会话互斥,避免 E1 重复初始化。
|
||||
3. 修复 ZIP 路径校验、共享目录替换和文件流关闭问题。
|
||||
4. 明确裸 bin 兼容允许使用的工程授权场景。
|
||||
|
||||
---
|
||||
|
||||
## 5. 关键代码
|
||||
|
||||
### MPU
|
||||
|
||||
| 文件 | 行号 | 说明 |
|
||||
|---|---:|---|
|
||||
| `ZQ_TH7_RKUpdateService/src/android/rockchip/update/service/RKUpdateReceiver.java` | 53 | 本地升级触发 |
|
||||
| `ZQ_TH7_RKUpdateService/src/android/rockchip/update/service/RKUpdateService.java` | 328 | MPU 本地升级主流程 |
|
||||
| 同上 | 498 | 文件扫描和优先级 |
|
||||
| `ZQ_TH7_RKUpdateService/src/android/rockchip/update/service/ZipFileVerifier.java` | 86 | MPU 解压和验签 |
|
||||
| `ZQ_TH7_RKUpdateService/src/android/rockchip/update/service/UpdateAndRebootActivity.java` | 159 | 选择 RK image 或 OTA 模式 |
|
||||
| `ZQ_TH7_RKUpdateService/src/android/rockchip/update/service/RecoverySystem.java` | 354 | 安装 `update.img` |
|
||||
|
||||
### MCU
|
||||
|
||||
| 文件 | 行号 | 说明 |
|
||||
|---|---:|---|
|
||||
| `YX_MainInterface_ZhongQi/src/main/java/com/yaxon/base/system/UpgradeMainActivity.java` | 111 | MCU 升级入口 |
|
||||
| `YX_MainInterface_ZhongQi/src/main/java/com/yaxon/base/system/ZhongQiM3UpdateActivity.java` | 321 | 发起 Binder 调用 |
|
||||
| `YX_CommunicatePro_ZhongQi/src/main/java/com/yaxon/telematics/service/ImplM0ManagerService.java` | 30 | AIDL 转发 |
|
||||
| `YX_CommunicatePro_ZhongQi/src/main/java/com/yaxon/telematics/service/protocol/monitor/m0/MonitorM0Update.java` | 75 | E1~E4 协议处理 |
|
||||
| 同上 | 203 | 查包、验签和 E2 请求 |
|
||||
| 同上 | 264 | 实际固件选择 |
|
||||
| `YX_CommunicatePro_ZhongQi/src/main/java/com/yaxon/utils/ZipFileVerifier.java` | 80 | MCU 解压和验签 |
|
||||
|
||||
## 6. 代码状态说明
|
||||
|
||||
- MPU 升级目录 `ZQ_TH7_RKUpdateService` 当前未纳入 Git。
|
||||
- 当前源码实际扫描三种文件;业务目标只保留 `update_mpu.zip` 和 `update.img`。
|
||||
- MCU 签名升级由 `aeb1d9c9e`、`897dc0607` 两笔提交引入。
|
||||
- 2026-08-19 当前工作区恢复 `m3/cortex-m3.bin`、`m3/cortex-gdm4.bin` 旧版兼容,并改为验签实际传输的 ZIP 内固件。
|
||||
- 本文只描述 MPU 和 MCU 本地升级,不包含其他升级类型。
|
||||
|
||||
|
||||
|
||||
不签名: 新版本 - >旧版本
|
||||
Reference in new issue
Block a user