Graphorall

Back

机械革命IMINI主机EC控制器逆向

  • public:: true

  • 背景#

    • 2025 年 5 月 30 日首发购入机械革命 IMINI Series mini PC(AMD Ryzen AI 9 H365 / Strix Point),次日到货。

    • 2025_06_01 就发现问题:节能模式下室温 37°C,风扇转速在 1200-1500 rpm 之间横跳,反复启停导致异响。客服毫无作用。后来在 BIOS 里开了 CPU Smart FAN(AMD 自家的控制),转速降不下去但至少不自毁了。

    • 但这只是绕过,风扇策略仍然不可调。这类 mini PC 没有 BIOS 风扇曲线选项,系统层面 thinkfanfancontrol 也指望不上——它们依赖 hwmon 的 PWM 接口,而这台机器的风扇完全由 EC(Embedded Controller)固件管理,内核不直接暴露控制接口。

    • 于是开始了一轮手工逆向。

  • 第一次尝试:NBFC(6 月 2 日)#

    • 试了 NBFC(NoteBook FanControl),跨平台笔记本风扇控制工具,通过 EC 寄存器读写控制风扇。

    • 但 IMINI Series 没有对应配置文件,最接近的 MECHREVO Jiaolong Series GK5NR0O.json 寄存器偏移对不上。NBFC 依赖的 ec_sys 内核模块也只暴露 debugfs 的 GPE 和 lock 信息,没有寄存器读写接口。

    • 走不通。

  • 第二次尝试:acpi_ec + ec_probe 盲探(2025_06_04#

    • 转向 saidsay-so/acpi_ec 内核模块,它提供 /dev/ec 字符设备,可以直接读写 EC 寄存器。

    • ec_probe 盲探:

      • ec_probe read 0x70 发现是温度,读数和 k10temp 一致

      • ec_probe read 0x35 0x36 猜测是风扇转速,数值随风扇声音变化

      • ec_probe write 0x35 06 / write 0x36 0x1e 试着写转速,确实能影响风扇

      • ec_probe watch 实时观察各寄存器变化

    • 基本确定了三个寄存器:

      • 0x31 → 风扇模式

      • 0x70 → CPU 温度

      • 0x35-0x36 → 风扇转速(big-endian)

    • 当晚写了 /usr/local/sbin/ecinfo,Python 脚本通过 /dev/ec 读这三个寄存器并格式化输出。 后续几天继续摸索,发现直接写 0x31 可以切换风扇模式(0-5),从静音到暴力扇,基本解决了问题。

    • 但这次逆向不全面:只搞清了 3 个寄存器,其余 200 多个字节没碰,寄存器名字都是猜的,也不知道固件内部怎么处理。

  • 时隔一年的完整逆向(2026 年 8 月 12 日)#

    • 一年多过去,ecinfo 一直在 /usr/local/sbin 安静地跑着。最近折腾 NPU 时发现这台机器的 ACPI 表里缺失 NPU 的条目,导致内核驱动无法读取 NPU 传感器。排查过程中翻了 ACPI 表,顺便意识到:DSDT 里就有完整的 EC 寄存器映射表,当年完全可以不用盲探。

    • DSDT 的 Device (EC0) 里有一个 OperationRegion (ERAX, EmbeddedControl, 0x00, 0xFF),紧跟 Field 块,逐字节命名了 EC 的全部 256 字节寄存器——这是固件自己的声明,比任何猜测都权威。

    • 发现 GLM-5.2(本地 vLLM 部署)逆向 ACPI 表和寄存器干得不错,于是让它从 DSDT 出发重新做了一次完整逆向。

  • 完整发现#

    • 首先确认了我当年的三个发现完全正确——DSDT 的 ERAX Field 块里,这三个寄存器的名字正好就是 FCMO/CPUT/FN1L/FN1H:

      • 0x31 FCMO — 风扇模式(Fan Mode)

      • 0x70 CPUT — CPU 温度

      • 0x35 FN1L / 0x36 FN1H — 风扇 1 转速(big-endian,与当年的猜测一致)

    • 我特别提醒了一个关键认知:fan mode 决定的是转速对温度响应的灵敏度(静音/均衡/暴力扇),而不是直接设转速值。GLM 最初误以为 FN1L/FN1H 是反向计数,被我纠正——就是 big-endian 的 RPM。

    • 另一个我强调的发现:FCMO(0x31)可以直接写 0-5 全 6 档,而 FCMI(0x32)命令路径(写 0x80|N)会被 EC 固件封顶在 3。也就是说当年直接写 0x31 设模式 5 是唯一能用 4/5 档的方法。我还实测了写 FCMI 0x84/0x85,FCMO 确实只到 3。

    • 其余由 GLM 独立发现的内容(WMI 接口 GUID 99D89064 的 WMAA 方法、ITS0 风扇策略表与 ALIB/SMU 协议、ACPI _Qxx 事件映射、6 档负载实测曲线等)已在仓库 README 中详细记录,此处不再展开。

  • 反思#

    • ACPI 表是逆向 EC 的第一手资料。DSDT 的 OperationRegion (ERAX, EmbeddedControl, ...) + Field 块就是固件自己对 EC 寄存器的命名声明,比盲探高效得多。当年要是先翻 DSDT,至少寄存器名和偏移不用猜。

    • 盲探并非无用。当年靠 ec_probe read/write 盲探出的三个寄存器(0x31/0x70/0x35-36)后来证明完全正确。盲探的结果可以验证,但效率远低于直接读固件声明。

    • 直接写寄存器有时比走正规路径更强大。ACPI 的 WMI/FCMI 路径把风扇模式封顶在 3(4 档),而直接写 FCMO 能用全部 6 档。这不是 bug,是厂商刻意设的限制。

机械革命IMINI主机EC控制器逆向
https://blog.graphorall.top/blog/%E6%9C%BA%E6%A2%B0%E9%9D%A9%E5%91%BDIMINI%E4%B8%BB%E6%9C%BAEC%E6%8E%A7%E5%88%B6%E5%99%A8%E9%80%86%E5%90%91
Author rubbishzyc
Published at August 12, 2026