Toyota 固件指纹:子版本不同也能命中同一车型的三级匹配

作者:

在

结论:Toyota 的固件指纹识别是三级顺序匹配:先精确固件匹配,再通用「至少两个唯一 ECU」模糊匹配,最后才调用品牌自定义的平台码回退。平台码只比较「零件号-平台-主版本」键,不比较子版本,所以小版本更新仍可能命中旧车型数据库;而「模糊」只是容忍子版本差异,并不容忍任意 ECU 集合。候选不唯一时必须保持被动或人工核验,不能在控制插件里猜。

平台配置不是运行时健康

CAR 的每个枚举成员包含 CarSpecs、车型文档、动力/雷达 DBC 映射和静态 flags。构造平台时执行配置 init(),创建 CAR 枚举时写入平台名并冻结配置对象——这是一份冻结的静态表,不是运行时健康状态。

几个容易混淆的映射:TSS2 配置默认指向 toyota_nodsu_pt_generated 和 toyota_tss2_adas;SecOC 配置改用 toyota_secoc_pt_generated。若配置含 RADAR_ACC,两个配置类都只留下动力 DBC,表示本快照不按对应雷达 DBC 解析该路径——不能推论车辆没有物理雷达。

同理,ToyotaCarDocs 默认标注 Toyota A 线束,SecOC 车型文档另用 CUSTOM 支持类型。源文档强调:文档展示字段、DBC 可用性、CarParams.radarUnavailable 和实车传感器健康是四个不同维度。EPS_SCALE 对大多数车型默认 73,少数车型显式覆盖;它进入 Toyota safety 参数低字节与状态侧 EPS 扭矩缩放,不能作为插件自报的可信运行标定。

固件查询的实际覆盖

FW_QUERY_CONFIG 声明三组总线 0 诊断请求,各组有独立 ECU 白名单:

组别 请求流程 边界
KWP tester-present 后查询 0x1a8801 与其他组共享 ECU 白名单机制
OBD 版本 短 tester-present 后查询 OBD 版本 独立白名单
UDS 版本 tester-present / 默认会话 / 扩展会话后查询 UDS 版本 独立白名单

其中 extra_ecus 只列出额外可查地址,并不表示都参与模糊匹配;部分车型的 ABS 或发动机 ECU 被列为 non_essential_ecus,用来处理缺报或多地址。源文档特别提醒:不能把「可缺席」理解成「该 ECU 的所有错误版本都允许通过」,具体精确匹配语义由通用的 match_fw_to_car_exact() 实施。

匹配顺序:精确、通用模糊、品牌回退

通用识别顺序是固定的三级,越靠后越宽松,但每一级都不做「最像的一款」打分:

阶段 条件 结果处理
精确固件匹配 固件版本与数据库精确命中 返回是否精确及候选集
通用唯一 ECU 模糊匹配 「至少两个唯一 ECU」 可返回多个候选
Toyota 平台码回退 仅当前品牌在模糊阶段尚无候选时调用 返回所有通过的候选

关键规则在 get_car():只有固件候选恰好一个时,才用它覆盖 CAN 指纹结果;零个或多个候选则保留 CAN 识别结果,显式固定车型设置又可覆盖两者。源文档明确这里没有把唯一固件候选与 CAN 指纹做一致性合取。此外,match_fw_to_car_fuzzy() 虽然接收 vin 参数,但 Toyota 此实现没有读取该参数——VIN 字符串不能消解平台码歧义。

平台码算法逐步拆解

get_platform_codes() 从固件字节提取零件号/平台/主版本键,并保留子版本集合。它的步骤可以逐条核对:

  1. 检查首字节是否为 0x01 至 0x03 的块数;未命中则按单块处理。
  2. 总字节长度必须等于块数乘 16,否则跳过该固件。
  3. 每块去掉头尾零和空格,但仅解析第一块;第一块长度 8、10、12 时分别尝试 short、medium、long 正则,且正则使用 search(),不是额外的全字节锚定校验。
  4. 返回字典键为 platform-major(短格式)或 part-platform-major(中/长格式),值是子版本集合。
  5. 第二块和子版本可被保留或解析出来,却不参与最终车型键比较——因此小版本更新可以命中旧车型数据库。

在模糊匹配阶段,match_fw_to_car_fuzzy() 对每个候选车型遍历数据库里类型属于 fwdCamera、fwdRadar、eps 的 ECU,以地址/子地址从实车固件表取版本;每个预期 ECU 至少要找到一个平台键,否则该候选失败;通过的部分必须覆盖候选的这些预期地址。最后减去 FUZZY_EXCLUDED_PLATFORMS——该集合在本快照为空。

歧义与插件契约

跨地址、漏回包、固件格式异常会导致匹配缺席;共享平台/主版本键则可能导致多个候选。源文档对此的定性很直白:这里的「模糊」是容忍子版本差异,不是容忍任意 ECU 集合,更不是把单条相机固件当作充分身份凭证。

对于硬件自制或插件化平台,错误识别会连带选择错误的 DBC、转向模式和 safety 参数。因此源文档提出一条比现状更严格的拟议契约:车型识别服务应返回 CAN 候选、固件候选及其交叉一致性、证据 ECU/地址/原始回包、精确或模糊等级、冲突原因和数据集版本;安全核心在候选唯一、且 DBC/固件/safety 组合得到验证前,保持 noOutput。这是重构建议,不是当前行为。

测试层面,test_toyota.py 检查角度/RADAR_ACC 标志属于 TSS2、当前 LTA 车型集合、TSS2 动力 DBC、必要 ECU 项和固件格式,并遍历数据库版本检查专属回退的唯一性与排除集合。但这只证明「现有固件数据库样本」受到约束,不能证明未知地区、替换 ECU 或故意构造的相似固件不会误识别;且本轮未运行这些测试。

常见问题

为什么小版本固件更新后还能识别成同一车型?

因为 get_platform_codes() 返回的键只到「零件号-平台-主版本」,值是子版本集合,而子版本不参与最终车型键比较。第二块和子版本可被保留或解析出来,却不会被用来区分车型,所以小版本更新可以命中旧车型数据库。

固件匹配失败一定会退回到品牌专用逻辑吗?

不一定。顺序是精确固件匹配、通用模糊匹配,最后一层才调用 Toyota 自定义平台码回退,而且仅当当前品牌在模糊阶段尚无候选时才调用。若前面的阶段已经返回候选,就不会进入品牌回退。

VIN 能帮助消除固件候选歧义吗?

在这份实现里不能。match_fw_to_car_fuzzy() 虽然接收 vin 参数,但 Toyota 该实现没有读取该参数,因此 VIN 字符串不能消解平台码歧义。

多个固件候选时,最终选哪个车型?

get_car() 只有在固件候选恰好一个时才用它覆盖 CAN 指纹结果;零个或多个候选则保留 CAN 识别结果,显式固定车型设置又可覆盖两者。源文档说明这里没有把唯一固件候选与 CAN 指纹做一致性合取,因此歧义不会被自动「合取」消解。

延伸阅读

参考资料

  • 项目 02 —— openpilot-research/TOYOTA_PLATFORM_FIRMWARE_MATCHING_DEEP_DIVE.md(取用了 FW_QUERY_CONFIG 三组请求、三级匹配顺序、平台码算法步骤与拟议插件契约)。
  • 项目 02 —— openpilot-research/CAR_PROTOCOL_IMPLEMENTATIONS.md(仅用于确认 match_fw_to_car() 与 get_car() 在整条识别链中的位置)。

说明:本文为对固定源码快照的静态结构分析,未运行完整测试套件、未连接硬件、未验证目标车型的真实参数组合。文中所有阈值、行号索引与配置均出自源文档,标注为未验证的结论保留其原有边界。

更新记录

首次发布 2026-10-11 最近核对:2026-10-11

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注