固件接收后台分发的设备私钥与序列号,写进一次性可编程存储区,读回确认。
读侧(应用启动时从 OTP 读身份,记录格式与判定)见 docs/otp-read.md;本文档只写写侧协议。
固件不再自己产生密钥对:密钥对由后台生成、绑定序列号,写入工具登录后取密钥,
经串口发给固件。旧的“现场产生、人工登记”流程已作废。
OK PROVISIONED 后,该台完成;写不进或读回不符的台隔离处理,
不重试写入(存储区写一次即不可改)。\n 结尾;结尾的 \r 允许(即 \r\n 也行)。ERR BAD_COMMAND。\n;调用方回复缓冲至少 64 字节,不足时不写半截回复。PROV KEY 这一行里;
设备在任何回复里都不输出私钥(原值、十六进制、指纹一律不输出),只回序列号。| 命令 | 含义 | 成功回复 |
|---|---|---|
PROV BEGIN |
打开一次写入会话 | OK PROV READY |
PROV SERIAL <序列号> |
送序列号(待提交) | OK SERIAL |
PROV KEY <64 位十六进制> |
送私钥(待提交) | OK KEY |
PROV COMMIT |
写存储区并读回确认 | OK PROVISIONED |
PROV ABORT |
放弃待提交值、关闭会话 | OK ABORT |
PROV STATUS |
查写入状态 | OK PROVISIONED <序列号> 或 OK UNPROVISIONED |
IDLE --BEGIN--> READY --COMMIT--> 已写入
^ |
+--- ABORT ----+
SERIAL 与 KEY 在 READY 下可按任意顺序送,提交前重发可覆盖纠错。BEGIN 在 READY 下可重复送(不清空待提交值);已写入后送 BEGIN 回
ERR ALREADY_PROVISIONED。STATUS 在任何状态下都可用;未写入时回 OK UNPROVISIONED。SERIAL、KEY、COMMIT 在 IDLE 下(未 BEGIN)回 ERR BAD_COMMAND。COMMIT 后待提交值从内存清掉(私钥清零,不只是遗忘)。COMMIT 按以下顺序检查,任一步失败即停:
ERR ALREADY_PROVISIONED。READY → ERR BAD_COMMAND。ERR INCOMPLETE。ERR OTP。ERR VERIFY。此时存储区已经写了、但没通过确认,
该台必须隔离处理,不能重新写入(写一次即不可改),也不能靠重试蒙过去。OK PROVISIONED。0x21–0x7E),不含空格(空格是命令分隔符)。
序列号格式本身由后台发号系统定,固件这里只做长度与字符检查,不硬编码格式。ERR BAD_KEY。ERR BAD_COMMAND;序列号非法回 ERR BAD_SERIAL。| 回复 | 含义 |
|---|---|
ERR BAD_COMMAND |
未知命令、参数个数不对、会话未打开 |
ERR BAD_SERIAL |
序列号为空、超长、含不可见字符或空格 |
ERR BAD_KEY |
私钥长度不对或含非十六进制字符 |
ERR INCOMPLETE |
提交时序列号或私钥缺失 |
ERR ALREADY_PROVISIONED |
存储区已写入,拒绝二次写入 |
ERR OTP |
存储区读写失败 |
ERR VERIFY |
写后读回不符,该台隔离处理 |
-> PROV STATUS
<- OK UNPROVISIONED
-> PROV BEGIN
<- OK PROV READY
-> PROV SERIAL GW202611020001
<- OK SERIAL
-> PROV KEY 808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f
<- OK KEY
-> PROV COMMIT
<- OK PROVISIONED
-> PROV STATUS
<- OK PROVISIONED GW202611020001
docs/固件分发全流程.md(https://github.com/ffffxxxjjj/sign/blob/main/docs/固件分发全流程.md)——开发出原始固件 → 运营上传管理后台(后端签名+加密出共用包)→ 现场下载 → 写入工具分发取密钥 → 本协议写进一次性可编程存储区 → 现场安装验在线 → 空中升级。docs/sign-server-api.md(https://github.com/ffffxxxjjj/sign/blob/main/docs/sign-server-api.md)——领号(POST /devices/allocate)、操作员登录与分发(POST /operator/login、POST /devices/issue)、包密钥包(GET /key-package)、手动推送(POST /devices/{序列号}/push、POST /devices/push-batch)、状态接入。docs/固件写入工具设计.md(https://github.com/ffffxxxjjj/firmware-tool/blob/main/docs/固件写入工具设计.md)——工具侧单台流程、界面、服务端接口。docs/package-format.md(https://github.com/ffffxxxjjj/sign/blob/main/docs/package-format.md)——GWPK v3 共用包(包头 312 字节、格式 3)与 80 字节包密钥包。注意:本协议只覆盖出厂写入(私钥与序列号进一次性可编程存储区)。空中升级的设备端处理(收 firmware_update 命令、解包密钥、解固件、验签、安装、回执)待固件侧实现,不在本协议内;回执配对跟踪与管理台推送按钮界面同样待后续。
bootloader/src/provision.rs(Provisioner + OtpStore 抽象),no_std、
无堆、无外设依赖;板上应用层把串口收到的行喂给 handle_line,把返回的回复行
写回串口即可(串口接线本身不在本批内)。OtpStore 只有读、写、查已写入三项,没有擦除与覆盖;芯片实现接
芯片的一次性可编程区,主机测试用内存模拟(同样写一次即不可改)。cargo test 里的 provision::tests(13 项),覆盖正常写入读回、
顺序可换、重复写入拒绝、缺字段、会话外命令、非法字段、未知命令、空行、
中止、读回不符、存储失败、重发覆盖、回复缓冲不足。