Files
Obsidian/项目文档/重汽/PX3 升级流程说明.md
2026-11-05 14:35:04 +08:00

12 KiB
Raw Permalink Blame History

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 秒

扫描目录:

/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() 实际扫描顺序为:

update_mpu.zip → OTA_PACKAGE_FILE(默认 update.zip)→ update.img

另外,1224 版本处理独立裸 update.img 时会读取:

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

包结构:

update_mpu.zip
    ├── update.img
    └── ValidationFile.ini

ValidationFile.ini 当前读取:

sign=<十六进制 RSA 签名>

流程:

检测到 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 命令:

--update_rkimage=<update.img完整路径>
--locale=<当前语言>

当前验签失败分支缺少 return,仍会打开确认页,并把外层 update_mpu.zip 当成标准 OTA 包再次校验。这是现有缺陷,不是兼容流程。

2.5 旧版裸 update.img

检测到 update.img
    ↓
读取 persist.sys.update.show
    ├── false:忽略,不弹确认页
    └── true:继续
             ↓
         检查镜像产品名是否匹配 ro.product.model
             ↓
         用户确认
             ↓
         installRKimage()
             ↓
         重启 Recovery 安装

裸 update.img 没有新增 RSA 验签,只做产品名检查。

2.6 MPU 结果处理

服务下次启动时读取:

/cache/recovery/last_flag
标记 含义
success$path=... Recovery 报告升级成功
updating$path=... 上次升级未形成成功状态

当前结果流程尚未闭环:

  • 成功/失败提示 Activity 的启动代码被注释。
  • 没有统一结果广播。
  • 升级包删除没有稳定执行。
  • 新版包验签后用户取消,升级锁没有释放。
  • Recovery 写回 last_flag 的实现不在当前项目中。

3. MCU 升级流程

3.1 页面入口

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 包结构

update_mcu.zip
    ├── cortex-gdm4.bin
    ├── cortex-m3.bin
    └── ValidationFile.ini

根据设备类型,实际刷写文件是 cortex-gdm4.bin 或 cortex-m3.bin。

3.4 解压和验签

开始 sendUpdateRequest()
    ↓
删除 /sdcard/zhongqi_mcu_update/
    ↓
解压 update_mcu.zip 到该目录
    ↓
根据 MCU 版本选择实际目标固件
    ↓
计算 SHA-256
    ↓
读取 ValidationFile.ini 中的 sign
    ↓
使用硬编码 RSA-2048 公钥和 SHA256withRSA 验签
    ├── 失败:返回 -2
    └── 成功:选择实际固件并进入协议传输

当前算法先计算文件 SHA-256,再把摘要传给 SHA256withRSA,实际相当于:

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 返回最终结果

主时序:

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 新旧兼容

历史裸固件路径:

<介质根目录>/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 本地升级,不包含其他升级类型。

不签名: 新版本 - >旧版本