3、固件镜像格式:S19/HEX/BIN格式解析、镜像签名与校验、镜像加密原理
各位做ADAS量产的朋友,今天我们来聊聊固件镜像。这玩意儿看着不起眼,但搞不好能让你的产线直接停摆。我见过太多工程师在镜像格式上翻车了——烧进去的车载摄像头不工作,查了半天发现是S19文件解析错了地址。嗯,咱们今天就把这事彻底讲透。
3.1 三大镜像格式:S19、HEX、BIN
先说个基本概念。固件镜像说白了就是芯片要执行的二进制代码,但怎么组织这些代码,不同格式有不同玩法。ADAS系统里最常见的就是这三种:S19、Intel HEX、纯BIN。
3.1.1 S19格式(Motorola S-record)
S19格式在汽车电子领域用得特别多。我个人习惯用这个格式做量产烧录,因为它自带校验,省心。
一个典型的S19记录长这样:
S1137A00 48656C6C6F20576F726C642100 4A
我来拆解一下:
- S1:记录类型。S1表示数据记录,S0是文件头,S5是记录计数,S9是结束记录
- 13:字节长度(0x13 = 19字节,包含地址+数据+校验)
- 7A00:起始地址(16位地址)
- 48656C6C6F20576F726C642100:实际数据
- 4A:校验和
关键点:S19的校验和是取反加一。计算方法是:把长度、地址、数据全部加起来,取低8位,然后取反加一。我当年调试一个ADAS雷达时,发现校验老报错,最后发现是工具链把S19的校验算法搞混了。
S19格式有几种变体:
| 类型 | 地址宽度 | 适用场景 |
|---|---|---|
| S1 | 16位 | 小容量MCU,比如车身控制 |
| S2 | 24位 | 中等容量,ADAS摄像头常用 |
| S3 | 32位 | 大容量,比如域控制器 |
3.1.2 Intel HEX格式
Intel HEX是另一种主流格式。和S19比,它更灵活,但解析起来稍微麻烦点。
:10010000214601360121470136007EFE09D2190140
解析规则:
- : 起始标记
- 10:数据长度(16字节)
- 0100:起始地址
- 00:记录类型(00=数据,01=结束,02=扩展段地址,04=扩展线性地址)
- 214601360121470136007EFE09D21901:数据
- 40:校验和
避坑指南:我曾经遇到一个坑——Intel HEX的地址扩展记录。如果你的固件超过64KB,必须用04类型记录来扩展地址。有次产线烧录,工具没处理扩展地址,结果所有数据都写到了错误的位置。排查了整整两天。
3.1.3 纯BIN格式
BIN格式最简单,就是纯粹的二进制数据,没有地址信息,没有校验。你想想看,烧录器拿到BIN文件,只能从起始地址开始顺序写。
BIN的优缺点很明显:
- 优点:体积最小,解析最快,适合量产
- 缺点:没有地址映射,没有校验,出错很难排查
我个人建议:量产阶段用BIN,但开发调试阶段用S19或HEX。为什么?因为BIN出了问题你根本不知道数据写到哪去了。
3.2 镜像签名与校验
ADAS系统涉及安全,镜像签名是必须的。说白了,就是防止有人篡改你的固件。
3.2.1 签名流程
签名过程其实不复杂:
- 对固件镜像做哈希运算(SHA256或SHA512)
- 用私钥对哈希值加密,生成签名
- 把签名附加到镜像末尾,或者放在特定位置
// 伪代码示例
uint8_t firmware[] = { ... }; // 固件数据
uint8_t hash[32]; // SHA256哈希值
SHA256(firmware, sizeof(firmware), hash);
uint8_t signature[256]; // RSA签名
RSA_sign(private_key, hash, sizeof(hash), signature);
// 把签名附加到固件末尾
append_to_firmware(signature, sizeof(signature));
注意:签名用的私钥必须妥善保管。我见过一个项目,私钥直接硬编码在量产工具里,结果被逆向工程了。整个产线被迫停产,重新换密钥。
3.2.2 校验流程
芯片启动时,Bootloader会做校验:
- 读取固件数据,计算哈希值
- 读取签名,用公钥解密得到原始哈希
- 比较两个哈希值,一致则通过
这里有个细节:校验时机。我建议在烧录完成后立即做一次校验,芯片启动时再做一次。双重保险。
3.3 镜像加密原理
签名只能防篡改,不能防窃取。如果你的固件被读出来,别人照样能分析你的算法。ADAS的算法可是核心资产,必须加密。
3.3.1 对称加密 vs 非对称加密
| 类型 | 算法 | 速度 | 适用场景 |
|---|---|---|---|
| 对称加密 | AES-128/256 | 快 | 固件本体加密 |
| 非对称加密 | RSA/ECC | 慢 | 密钥交换、签名 |
实际量产中,我通常用AES加密固件,用RSA加密AES密钥。这叫混合加密,既安全又高效。
3.3.2 加密流程
// 1. 生成随机AES密钥
uint8_t aes_key[16]; // AES-128
RNG_generate(aes_key, sizeof(aes_key));
// 2. 用AES密钥加密固件
uint8_t encrypted_firmware[MAX_SIZE];
AES_encrypt(firmware, firmware_size, aes_key, encrypted_firmware);
// 3. 用RSA公钥加密AES密钥
uint8_t encrypted_key[256];
RSA_encrypt(public_key, aes_key, sizeof(aes_key), encrypted_key);
// 4. 打包:加密密钥 + 加密固件 + 签名
经验之谈:我曾经在量产工具里用了一个固定的AES密钥,结果被客户的安全审计发现了。后来改成每颗芯片单独生成密钥,虽然增加了复杂度,但安全性提升了一个量级。
3.3.3 解密流程
芯片端解密是反过来的:
- 用私钥解密得到AES密钥
- 用AES密钥解密固件
- 校验签名
这里有个性能问题。AES解密很快,但RSA解密很慢。如果每颗芯片都做RSA解密,产线节拍会受影响。我建议在量产工具端就完成解密,烧录时只烧录解密后的固件。但这样安全性会降低——你得确保产线环境安全。
3.4 量产中的实战建议
说了这么多理论,来点实际的。我在做ADAS量产工具时,总结了几个原则:
- 格式统一:整个产线只用一种镜像格式,别混用。我推荐S19,因为地址信息完整,校验机制成熟
- 签名必做:哪怕是非安全芯片,也建议做签名。万一哪天客户要求安全认证,你就不用返工了
- 加密可选:如果固件不涉及核心算法,可以不做加密。加密会拖慢产线速度
- 日志记录:每颗芯片的烧录日志都要保存,包括镜像哈希、签名值、烧录时间。出了问题好追溯
最后说一句:镜像格式、签名、加密,这三件事看起来是技术问题,其实是流程问题。把流程定好了,工具写好了,产线跑起来就很顺。我见过太多团队,技术方案很牛,但量产时各种掉链子。嗯,细节决定成败。