21 KiB
firmware-PP_da14585_4.2_CH.img 逆向分析报告
目标文件:
app/firmware-PP_da14585_4.2_CH.img,72228 字节 平台:Dialog DA14585(ARM Cortex-M0,仅 Thumb),SysRAM 96KB @ 0x07FC0000–0x07FD8000 工具:analysis/firmware/fw_parse.py(头解析+CRC)、analysis/firmware/disasm.py(capstone 线性扫描)、analysis/firmware/find_cmds.py(命令立即数扫描)、analysis/firmware/fw.asm(全量反汇编,32098 指令) 地址约定:文件偏移 = 映射地址 - 0x07FC0000 + 0x40(映射地址 = 文件偏移 - 0x40 + 0x07FC0000)
0. 结论速览
| 问题 | 结论 |
|---|---|
| 固件是否可控 | 完全可控。BLE 命令处理无任何鉴权/加密门槛,全部命令(图像、刷新、模式、时间)连接即可用;激活只是云端生意,固件侧不锁功能 |
| 如何实现 OTA | 固件内置完整 SPOTA 协议栈(自定义任务 0xFC,MEM_DEV/GPIO_MAP/MEM_INFO/PATCH_DATA 四消息),接收方校验 70 51+AA 头后写入 SPI Flash 0x38000 备bank,可直接复用本镜像格式做 OTA |
| 命令解析在哪 | EPD 通道分发 @ 0x07FCBC64(handle 2/7/0xB);RXTX 命令分发器 @ 0x07FCBDE4(0xDD–0xEF 跳表 @ 0x07FCBEEA + 0x14/0x15/0x23/0x88/0x99/0xCC/0xFA/0xFB/0xFF 直比链) |
| 墨水屏驱动 | SSD1683 兼容(主路径,cmd 0x01 传 0x2B 0x01=300 行、0x44/0x45 设 50×300、0x24/0x26 双平面)+ 备选 UC8151/IL0373 兼容 路径(state[0x1c] 切换);波形用驱动 IC 内部 OTP LUT,固件无 LUT 表 |
| 激活机制 | 本地弱哈希,可离线算出。激活码 = 6 字节,code[i] = rol2((MAC[i]<<1 & 0xFF) ^ 0xEF) % 101,MAC 即设备 BD 地址(BLE 广播可见 / EFEF 应答的 14 字符设备 ID 可完整还原) |
1. 镜像格式(任务1)
1.1 头结构(64 字节,Dialog SUOTA/multi-image 格式)
| 偏移 | 字段 | 值 | 验证 |
|---|---|---|---|
| 0x00 | magic | 70 51('pQ',LE 0x5170 = IMAGE_VALID) |
✓ |
| 0x02 | signature | AA 01(OTA 接收方校验首字节==0xAA,见 0x07FCB4F2 处 cmp r0,#0xaa) |
✓ |
| 0x04 | code_size | E4 19 01 00 = 0x119E4 = 72164 = 文件长 72228 - 64 |
✓ 精确匹配 |
| 0x08 | CRC32 | 10 4D 89 6C = 0x6C894D10 |
✓ = 标准 zlib CRC32(poly 0xEDB88320,init/xorout 0xFFFFFFFF)over 数据区 72164 字节(fw_parse.py 实测 match=True;BZIP2/MPEG-2/POSIX 变体均不匹配) |
| 0x0C–0x3F | reserved | 0xFF,仅 0x20 处一字节为 0x00 | ✓ |
1.2 镜像布局图
文件偏移 映射地址 内容
0x000000 - 64B 镜像头('pQ' + len + CRC32)
0x000040 0x07FC0000 向量表:SP=0x07FD2B58, Reset=0x07FC0525, SysTick=0x07FC522B,
IRQ0=0x07FC221D, IRQ1=0x07FCA975(BLE), IRQ2=0x07F0271D(ROM), ...
0x0000C0~ 0x07FC0080~ 代码(Thumb)+ 内嵌字库/模板数据
~0x00C800 ~0x07FCC800 点阵字库区(大量 16px 字形位图,如 f0x00de30 起)
~0x00F900 ~0x07FCF8C0 GATT 描述符/UUID 表/消息handler表/DIS 属性表
0x010000~ 0x07FD0000~ 初始化数据区:DIS 字符串、22 个祝福词、adv 数据模板、TLV 记录
0x0119E4 0x07FD19E4 代码区结束(= code_size)
- 0x07FD19E8 BSS:全局状态结构体 state(激活码/设备ID/时间/显示参数)
- 0x07FD2B58 初始栈顶
SPI Flash 布局(由固件内常量推得,芯片 ≥ 512KB):
| Flash 偏移 | 用途 | 证据 |
|---|---|---|
| 0x00000 | 主固件 bank(boot ROM 加载到 SysRAM) | 标准 DA14585 boot |
| 0x2E000–0x35FFF | 显示帧缓存(8×4KB sector 擦除后顺序写,整图双平面 30000B) | cmd 03 处理 0x07FCBD0C:movs r0,#0x17; lsls r5,r0,#0xd=0x2E000,循环 8 次 bl 0x07FCAB74(sector 擦除),写函数 0x07FCAE4C |
| 0x38000 | OTA 备 bank:+0x00 产品头(校验 70 52 'pR'),+0x40 镜像头(校验 70 51+AA) |
OTA 接收 0x07FCB4AA:bl 0x07FC5AC4 读 0xC 字节后 cmp #0x70/cmp #0x52;0x07FCB4F8 cmp #0x70/cmp #0x51、0x07FCB4F2 cmp #0xaa |
| 0x3F0EF+sum(MAC[0:3]) / 0x3F1DE+sum(MAC[0:6]) | 激活码写入槽(6B×2,地址由 MAC 求和混淆) | 0x07FC7C18:ldr r1,=0x0003F0EF(literal @0x07FC7C58);0x07FC7C28 adds r1,#0xef;存于 state[0x3C]/state[0x40] |
2. GATT 表(任务3)
2.1 UUID 出现位置(均小端存储)
| UUID | 文件偏移 | 映射地址 | 说明 |
|---|---|---|---|
EPD Service 13187b10-…-83d3217d9a38 |
0x00FF0C | 0x07FCFECC | 128-bit 原始 16 字节 |
EPD Char 4b646063-…-e65356ea82fe |
0x00F972 | 0x07FCF932 | 128-bit,被 0x07FCFD7C 处描述符引用 |
| RXTX Service 0x1F10 | 0x00FF28(16B 项起于 0x00FF20) | 0x07FCFEE8 | 以 128-bit 蓝牙基 UUID 形式 FB 34 9B 5F 80 00 00 80 00 10 00 00 10 1F 00 00 |
| RXTX Char 0x1F1F | 0x00F98E(项起于 0x00F982) | 0x07FCF94E | 同上形式 |
| 第三 Service 0x221F | 0x00FF38(项起于 0x00FF30) | 0x07FCFEF8 | web 端声明但未用——疑似 SUOTA 通道 |
| Char 0x331F | 0x00F99E(项起于 0x00F992) | 0x07FCF95E | 0x1F10/0x221F 服务下的另一特征 |
| DIS 属性表(0x2800/0x2803 + 0x2A29/24/25/27/26/23/2A/50) | 0x00FF3C 起 | 0x07FCFEFC 起 | 12 字节/项 {uuid32, perm, aux},被 0x07FC7094 处注册代码引用 |
| GAP/BAS 表(0x2A00/0x2A01/0x2A19 电量 + 0x2902 CCC) | 0x00FBB0 起 | 0x07FCFB70 起 | BASS 任务消息 0x2400/0x2402 @0x07FCFBC4 |
EPD svc UUID 被 0x07FCFD64 引用、EPD char UUID 被 0x07FCFD7C 引用(GATT DB 描述符簇 0x07FCFD54–0x07FCFE68,三个服务各一簇)。
SPOTA/SUOTA UUID(0xFEF6–0xFEFB)在镜像中不存在(搜 f6fe/f7fe/…/fbfe 仅命中 BL 指令编码,无相邻簇),但:
- 广播数据模板含完整 16-bit 服务列表 0x180A(DIS)+0xFEF5(SPOTA):0x07FD094A
05 03 0a 18 f5 fe(证据:文件 0x01098A) - SUOTA 功能以自定义任务 0xFC + 自定义 service(疑似 0x221F)实现,见 §5
2.2 应用消息 handler 表(ke_msg_handler {u32 id, u32 func})
- GAPM 表 @ 0x07FCFE68:0x0C13→0x07FC7EE5、0x0C15→0x07FC80C1、0x0C17→0x07FC7C6D、0x0C00→0x07FC7D19…
- 显示/应用任务 0xFD 表:0xFD06→0x07FC6B9D、0xFD03→0x07FC6C1D、0xFD08→0x07FC6B25、0xFD0E→0x07FC6591、0xFD05→0x07FC6C41(@0x07FCFE88 起)
- GATTC 表 @ 0x07FCFB00:0x0E08→0x07FC79F1、0x0E13→0x07FC7619、0x0E15→0x07FC7529、0x0E17→0x07FC7939、0x0E19→0x07FC7921、0x0D15→0x07FC7A51、0x0D21/0x0D22→0x07FC7C69/0x07FC7C65
- SUOTA 任务 0xFC 表 @ 0x07FCFB50:
FC00→0x07FCB6F9、FC01→0x07FCAEED、FC02→0x07FCB6B9、FC03→0x07FCB3F1(文件 0x00FB90–0x00FBAF)
3. 命令解析(任务4)
3.1 写入口
GATT 写总入口 0x07FCBC64(4 个 BL 调用方:0x07FC58B6/0x07FC757E/0x07FC7784/0x07FC7AB8,均为 GAP/GATT 事件包装)。按消息 id(0xFD04/0xFD0D/0xFD0A,literal @0x07FCBDB8–0x07FCBDC0)分流;0xFD0A 按 handle 分流:
| handle | 去向 | 证据 |
|---|---|---|
| 2 | EPD 数据通道(0xAA/03/04/01) | 0x07FCBC84 cmp r0,#2 |
| 7 | RXTX 命令分发器 0x07FCBDE4 | 0x07FCBC80 cmp r0,#7 |
| 0x0B | 同上(第二命令特征,疑 0x331F) | 0x07FCBC7C cmp r0,#0xb |
写参数结构:[r4,#2]=handle,[r4,#4]=len,[r4,#6]=opcode,[r4,#7..]=payload。
3.2 EPD 通道(图像数据)
@ 0x07FCBC94:ldrb r0,[r4,#6] 后依次比 0xAA / 3 / 4 / 1:
| opcode | 处理 | 证据 |
|---|---|---|
03 |
整图:首包擦除 Flash 0x2E000 起 8 sector,随后按 state[0x2A] 累计偏移经 0x07FCAE4C 顺序写 Flash(忽略包内 offset 与平面字节),长度=len-4 | 0x07FCBD0C–0x07FCBDB6 |
04 |
日历小图:按包内 BE offset 写 RAM:[7]==0xFF→0x07FD4B18+off(无边界检查!);[7]==0x00→0x07FD0A0A+off(边界 0xAA9);数据=r4+0xA,len-4 |
0x07FCBD3C–0x07FCBD80;literal @0x07FCBDC8/0x07FCBDD8/0x07FCBDDC |
01 |
整图结束:state 清零 + bl 0x07FC6E98(Flash 落盘/刷屏准备) |
0x07FCBCA2–0x07FCBCAE |
AA |
小图结束:置标志 + bl 0x07FCA880(0) 触发刷新编排 |
0x07FCBD82–0x07FCBD8E |
00 |
忽略(web 的 clearScreen 第一步是固件侧 no-op) | 0x07FCBC9A 链无匹配落 0x07FCBD02 |
3.3 RXTX 命令分发器 0x07FCBDE4(文件 0x00BDA4)
前置:opcode 0–4 且 len≥0x1F → 数据写(拷贝 (op&7)×32 字节到 0x07FD17BD,op 记入 0x07FD09D0);opcode 5–8 且 len≥0x1F → 写 0x07FD183D。这覆盖 web 的 04{128B} 倒计时前缀位图(op 4→128B ✓)。
随后 subs r1,#0xdd; cmp r1,#0x12; bls → 跳表 @ 0x07FCBEEA(19 项,target=0x07FCBEEE+entry×2,表体文件 0x00BF2C):
| opcode | target | 语义(与 web 对照) |
|---|---|---|
DD |
0x07FCBF12 | 设时间:LE 4 字节 unix → state[0x78],并换算;只用前 4 字节(web 的年月日周字节被忽略)✓ |
E1 |
0x07FCBF78 | 模式:[7]==0→图模式(0x07FCBF8C,state[2]=0+刷新);==1→日历(0x07FCC10A,循环/可指定,state[0x14]=0);==2→时钟(0x07FCC12E,state[0x14]=1)✓ |
E2 |
0x07FCBF64 | 提交:查显示状态后 → 0x07FCC0D0 → bl 0x07FCA880(1) 刷新 ✓ |
E3 |
0x07FCC0D0 | 反色 → bl 0x07FCA880(0) ✓ |
E4 |
0x07FCBF98 | 时钟字体 state[0x25] 0/1 循环 ✓ |
E5 |
0x07FCBF58 | 旋转 180°:state[0x11] 翻转 ✓ |
E6 |
0x07FCBF70 | LUT/VCOM 校准字节 → 显示参数结构 0x07FD09D0+6,然后刷新。平面写函数 0x07FC8648 @0x07FC86EA 读该字节并按 0x10 分界(<0x10 红平面 / ≥0x10 黑平面)——与 web 文档"01–0f 设红、10–f0 设黑"精确一致 ✓ |
EF |
0x07FCBFAA | 激活/取设备 ID,见 §4 |
| DE–E0, E7–EE | 0x07FCC0D6 | 空操作(含 web 在用的 E9 轮播间隔、EA 槽位——本固件忽略)✗差异 |
跳表外直比链(0x07FCBE54–0x07FCBE88):
| opcode | target | 语义 |
|---|---|---|
14 |
0x07FCC004 | 12/24h:state[0x23] 翻转 ✓ |
15 |
0x07FCC0A0 | 时钟颜色:state[0x19]^=1 ✓ |
23 |
0x07FCC058 | 三色/黑白:state[0x18]=[7]&1;并写参数[6]=0x0C/0x80 ✓ |
88 |
0x07FCC092 | 置标志位 0x8000(web 未用) |
99 |
0x07FCC068 | 日历倒计时文字:len≥0x1F 时按 [7]×0x48 拷贝 72 字节/字符 到 0x07FD18BD 基缓冲,[7]+1 记字符数 ✓(与 web 990{j}{72B} 一致) |
CC |
0x07FCBFEE | 参数[5]:>0xE0 或 ≤0x47 时钳到 0x48(web 未用) |
FA |
0x07FCC04A | 关闭倒计时:state[0x24]=1,参数[2]=2 ✓ |
FB |
0x07FCC010 | 休眠时段:BCD 解析 [7]=开关、[8]=HH、[9]=MM → state[0x13]/参数+3/+4 ✓ |
FF |
0x07FCBE8A | len==6 时:FF 00→0x07FCC152 时钟倒计时日期(BCD 年×100+月+日 → 结构+0x10/14/18,state[0xD]=1);FF FF→0x07FCBEA0 日历倒计时日期(→ +0x1C/20/24)✓ |
web 有而固件无:E9/EA(no-op)、ASCII WIFI_SSID:...(固件无此字符串、无解析路径,直接忽略)——本固件为纯 BLE 版,WiFi/天气属其他 SKU 或云端能力。
4. 激活验证逻辑(任务6)——可离线绕过
4.1 EF 处理路径(0x07FCBFAA)
[r4,#7]==0xEF 且 len==2 → "EFEF":bl 0x07FCA22C 生成设备ID,
循环 r5=0x14..0x21 把 14 字节经 ke_msg 发回(notify 应答)✓ 与 web "14B 设备ID"一致
否则 → 比较循环 @0x07FCC0AA:r4[7..12](收的 6 字节) vs state[0x44..0x49]
全部相等 → 0x07FCC0DE:state+0x4A(6B)写 Flash[state[0x40]]、state+0x44(6B)写 Flash[state[0x3C]]
(写函数 0x07FCAE4C,与图像写 Flash 同一函数,证实为 SPI Flash 写)
不等 → 0x07FCC0D6 直接返回(无任何惩罚/锁定)
4.2 比较目标 state[0x44] 的来源 = MAC 哈希(关键发现)
启动初始化函数 0x07FC23D0(被 0x07FC7C30/0x07FC877E 调用)尾部 0x07FC24C8–0x07FC24F4,对 i=0..5 循环:
t = ((MAC[i]<<1) & 0xFF) ^ 0xEF ; ldrb→lsls#1→eors ~0x10→uxtb
code1[i] = ((t<<6)+(t>>2)) & 0xFF % 101 ; = rol2(t) % 0x65,经 __aeabi_uidivmod(0x07F1DFB8)
→ 存入 state[0x44+i]
- MAC = state[0x4A..0x4F] = 设备 BD 地址,由工厂函数 0x07FC7B94 经 NVDS/TLV 读取(0x07FCA2DC,tag 1 = Dialog NVDS BD_ADDRESS;缺省记录 @0x07FD04BA:
14 00 06 00 70 ca ea 80 d0 07…) - 设备 ID(EFEF 应答)生成 @ 0x07FCA22C:
snprintf(state+0x14, "%02X"*7 @0x07FCA298, |MAC4-0x99|, |MAC5-0x99|, |MAC3-0x99|, |MAC2-0x99|, |MAC1-0x99|, |MAC0-0x99|, flags);flags=state[0x10] = 各 MAC 字节 ≥0x9A 的位掩码(0x07FC23D4–0x07FC23F4 计算)——14 个十六进制字符 + 掩码可无损还原 6 字节 MAC - state[0x3C]/[0x40](激活码 Flash 写地址)=
0x3F0EF + MAC[0]+MAC[1]+MAC[2]与0x3F1DE + sum(MAC[0..5])(0x07FC7C0C–0x07FC7C2C,常数 literal @0x07FC7C58 = 0x0003F0EF)——按 MAC 求和混淆存放 - 全镜像不存在从 Flash 读回激活码的代码(Flash 读函数 0x07FC5AC4/0x07FC5A2C 仅 OTA 路径调用);0x07FC4CDC 每次刷新都会把这两个槽清零并按 RAM 码非零置 state[0xE]/[0xF](显示合成开关,非门锁)
4.3 绕过结论
- 激活码是纯本地函数:
code[i] = rol2(((MAC[i]<<1)&0xFF)^0xEF) % 101(i=0..5),无需厂商服务器。 - MAC 获取:BLE 广播地址直接可见;或发
EFEF收 14 字符 ID 按上式反解。 - 固件侧 EF 成功/失败均不门禁任何后续命令(03/04 图传、E1/E2 刷新等在未激活状态同样解析)——激活仅是厂商云端商业模式,本地使用可直接无视;如需让屏幕不再显示激活页,发送一次正确 EF 即可(或直接 patch §8 所述字节)。
5. OTA / SUOTA(任务3+可行性)
证据链:
- 任务 0xFC 四消息(表 @0x07FCFB50):FC00=MEM_DEV(0x07FCB6F8)、FC01=GPIO_MAP(0x07FCAEED)、FC02=MEM_INFO(0x07FCB6B8)、FC03=PATCH_DATA(0x07FCB3F0)——与 Dialog SPOTA 语义一一对应。
- 写转发器 0x07FC8340:按服务内 handle 偏移(
[r4,#6]=起始 handle,偏移 2–13 跳表 @0x07FC8392,12 项=6 特征×2)把特征写打包成 0xFC00–0xFC03 消息(0x07FC83CC:movs r0,#0x3f;lsls r0,#0xa=0xFC00;literal 池 @0x07FC8520–0x07FC8528 = FC02/FC03/FC01)。6 特征 = SPOTA 标准集(mem_dev/gpio_map/mem_info/patch_len/patch_data/serv_status)。 - 接收写盘 0x07FCB3F0:state[0x1C] 状态机(0x10–0x13);0x200 字节块缓冲(0x07FCB424
lsls r1,#9);XOR 校验和累计(0x07FCB448–0x07FCB458,存 state[0x24]);收满后校验缓冲头70 51(0x07FCB486–0x07FCB492)→ 写 Flash;并回读 0x38000 校验产品头70 52(0x07FCB4BC/0x07FCB4C4)与镜像头70 51 AA(0x07FCB4F2–0x07FCB502)。 - 广播数据声明 SPOTA 0xFEF5(0x07FD094A)。
OTA 实施建议:按本镜像格式(64B 'pQ' 头 + zlib CRC32)打包 → 连接后走 SUOTA 服务(web 端声明但未用的 0x221F,待实机确认句柄;可先 btgatttool 枚举含 6 特征的服务)→ MEM_DEV 写 SPI flash 基址、PATCH_DATA 分块(块内无需应用层 ACK,结束由接收方校验头+长度+XOR)→ 完成后设备复位,boot ROM 按产品头切换 bank。风险:bank 切换依赖 boot ROM 读 0x38000 产品头,首次实机前建议先用一份仅改版本字符串的镜像验证。
6. 墨水屏驱动(任务5)
低层原语:发命令 0x07FC3646(CS/DC=cmd)、发数据 0x07FC33D0、SPI 读 0x07FC31B4、GPIO 配置 0x07FC3658(P0/P1 基 0x50003000,literal @0x07FC3694)、SPI1 基 0x50001200(literal @0x07FC32B8 等)、延时 0x07FCB8EC。
6.1 驱动 IC 识别 —— 双面板支持,state[0x1C] 选择
主路径 state[0x1C]==0:SSD1683 兼容(面板初始化 0x07FC3440,证据 @0x07FC34C8–0x07FC3562):
12 ; SWRESET,延时 200ms(0x07FC34CE bl 0x07FC3154, r0=0xC8)
74 / 54 ; 模拟块控制
7E / 3B ; 数字块控制
2B / 04 63 ; VCOM/ACVCOM
0C / 8B 9C 96 0F ; Booster soft start(GDEY042 系列特征序列)
11 / 01 ; data entry mode
44 / 00 31 ; RAM X: 0–49 → 50 字节 = 400 列 ✓
45 / 2C 01 00 00 ; RAM Y: start 0x012C=300, end 0(反向寻址) ✓ 300 行
3C / 01 ; border
22 / B1, 20 ; 装载温度+主激活
4E / 00, 4F / 2C 01 ; RAM 计数器
另有 0x07FC3344 发 01 / 2B 01 / (1-state[0x20]) = Driver Output Control,mux 0x012B=299 → 300 行(400×300 三色 4.2" 实锤)。温度读取 @0x07FC32BC:18/80、22/B1、20、1B 读 2 字节 >>4 带符号(bit 0x800)→ state[0x28]。
备选路径 state[0x1C]!=0:UC8151/IL0373 兼容(0x07FC3476 起):
01 / 03 00 26 26 (0F|03) ; Power Setting(VGH/VSH/VSL/VDHR)
06 / 17 17 17 ; Booster Soft Start
50 / (97|51) 60 ; VCOM & Data Interval
22 / 04, 延时 200
面板类型 state[0x1C] 由 TLV 记录(tag 0x40–0x44,读取器 0x07FCA2DC 跳表 @0x07FCA2F4)配置。
6.2 刷新编排 0x07FCA880
读温度→选波形参数(0x07FC3440)→ 平面写 0x07FC8648 两次:(0x24|0x10, 0) 与 (0x26|0x13, 2)——0x24/0x26 = SSD168x 写黑/红 RAM;0x10/0x13 = UC8151 写 RAM1/RAM2,按面板标志 state[0x1E]/[0x1F] 选择 → ADC 读电池(0x07FC6374,state[0x2C]=百分比)→ 计数 state[0x2B]。
6.3 LUT
固件内无 LUT 表:全程未发 0x32(Write LUT),波形用驱动 IC 内部 OTP LUT;E6 命令仅存校准字节到 0x07FD09D0+6,平面写时按 <0x10/≥0x10 分红/黑平面生效(0x07FC86EA)。两段"LUT 候选"(0x07FD06F8/0x07FD187D)实为清零/0xFF 填充的间隙区,非 LUT。
7. 字符串交叉引用(任务7)
| 字符串 | 位置 | 引用点 | 用途 |
|---|---|---|---|
TEW MI YAO: |
0x07FC2508 (f0x002548) | adr @0x07FC2414 |
开机/未激活屏第一行标题(经 0x07FCC1C4 snprintf 到显存,随 0x07FC23D0 绘制) |
H:mspppclock.tech |
0x07FC251C | adr @0x07FC244A |
激活屏:厂商主机名(仅显示用,固件无联网代码) |
V:PP_da14585_4.2 |
0x07FC2530 | adr @0x07FC2464 |
激活屏:固件版本 |
WX:2549294317 |
0x07FC2544 | adr @0x07FC247C |
激活屏:微信联系方式 |
MAC:%02X%02X… |
0x07FC2554 | adr @0x07FC24A0 |
激活屏:显示 BD 地址 |
%02X%02X%02X%02X%02X%02X%02X |
0x07FCA298 | adr @0x07FCA286 |
设备 ID(14 hex)格式串,0x07FCA22C |
%d %02d / %d %02d %02d / %s %s 等 |
0x07FC2D88/90/58/60 | adr @0x07FC2D1E/22/C4/C8 |
时钟/日历屏文本排版 |
Happiness…Motive(22 词) |
0x07FD034C–0x07FD04B8 | 指针表 @0x07FC9708 | 日历模式每日一词 |
DA14585 / PP_da14585_4.2 / 1.0.0.0-LE / Dialog Semi |
0x07FD02C4/0x07FD08B9/0x07FD08D0/0x07FD08F6 | DIS 表 | DIS 0x2A24/0x2A26/0x2A27/0x2A29 值 |
NRF-XXXXXX |
0x07FD0956 | 0x07FCA210、0x07FCBC4C | 广播名模板(X 由 MAC 填充;web 端 namePrefix:'NRF-' ✓) |
0123456789abcdef/ABCDEF |
0x07FCC638/0x07FCC64C | hex 工具 | 通用 |
Sun/Mon/Tues/Wednes/Thurs/Fri/Satu(0x07FD0482 起,定长 8B)与 中华人民共和国(0x07FD0920,UTF-8)为日历显示素材。
8. 固件修改/重打包建议
- 重打包:改完代码区后用
fw_parse.py同算法重算 zlib CRC32 写回头 0x08,长度不变则无需改 0x04;经 §5 SUOTA 通道或 UART boot 烧录。 - 免激活 patch:将 0x07FCC0AA 比较循环的首分支
beq(0x07FCC0BC 处beq #0x7fcc0ac的 fall-throughb #0x7fcc0d6)改为直接跳成功分支,或把 EF 处理改成总写 Flash——但更简单的做法仍是按 §4.3 公式算码发送。 - 去激活开机屏:0x07FC23D0 的 r0 判分支(0x07FC23F6
cmp r0,#0; beq)强制走 0x07FC24C4 即可跳过 TEW MI YAO/MAC/WX 屏。 - RAM 无边界写注意:cmd 04 的 0xFF 平面分支(0x07FCBD48)无长度检查,自研上位机时不要越界(会踩 0x07FD4B18 之后的 BSS)。
- 手柄速查:EPD 数据 handle 2;命令 handle 7 与 0x0B(同一解析器);SUOTA 服务=含 6 特征(12 句柄)的服务(枚举确认)。
- 排产注意:固件忽略 E9/EA/WIFI 命令——自研上位机不必实现;倒计时文字位图经 opcode 0–8 数据通道(len≥0x1F)而非 0x99 之外的格式。
附:关键地址速查
| 名称 | 映射地址 | 文件偏移 |
|---|---|---|
| 镜像头 | - | 0x000000 |
| Reset handler | 0x07FC0525 | 0x0004E5 |
| GATT 写总入口 | 0x07FCBC64 | 0x00BC24 |
| RXTX 命令分发器 | 0x07FCBDE4 | 0x00BDA4 |
| 0xDD–0xEF 跳表 | 0x07FCBEEA(表体) | 0x00BF2C |
| EF 激活处理 | 0x07FCBFAA | 0x00BF6A |
| 激活码 keygen(boot) | 0x07FC24C8 | 0x002488 |
| 设备 ID 生成 | 0x07FCA22C | 0x00A1EC |
| SUOTA PATCH_DATA 接收 | 0x07FCB3F0 | 0x00B3B0 |
| SUOTA 写转发器 | 0x07FC8340 | 0x008300 |
| 面板初始化(SSD1683/UC8151) | 0x07FC3440 | 0x003400 |
| 刷新编排 | 0x07FCA880 | 0x00A840 |
| 平面写(0x24/0x26/0x10/0x13) | 0x07FC8648 | 0x008608 |
| Flash 写(页) | 0x07FCAE4C | 0x00AE0C |
| Flash 读 | 0x07FC5AC4 / 0x07FC5A2C | 0x005A84 / 0x0059EC |
| Flash sector 擦除 | 0x07FC58E0 / 0x07FCAE8C | 0x0058A0 / 0x00AE4C |
| 全局状态 state | 0x07FD19E8(BSS) | - |
| 显示参数结构(E6 字节 +6) | 0x07FD09D0 | 0x010990 |
| cmd04 RAM 缓冲 0xFF/0x00 | 0x07FD4B18 / 0x07FD0A0A | - |
| 文字位图缓冲(op0–8/99) | 0x07FD17BD / 0x07FD183D / 0x07FD18BD | - |