OpenKVM-A2:把向日葵控控 A2 改造成开源本地 KVM
之前那版写得太短了,这里重新整理成完整复盘。这个项目是一次把向日葵控控 A2 从“必须绑定向日葵客户端才能用”的状态,改造成一个本地可控、开源、可刷回官方、可一键安装的 KVM 固件的全过程。 2026-7-22 10:59:33 Author: www.zhaoj.in(查看原文) 阅读量:2 收藏

之前那版写得太短了,这里重新整理成完整复盘。这个项目是一次把向日葵控控 A2 从“必须绑定向日葵客户端才能用”的状态,改造成一个本地可控、开源、可刷回官方、可一键安装的 KVM 固件的全过程。

先说结论:整个项目从方案判断、固件备份、代码实现、真机调试、Web UI、HID 协议、视频链路、SSH 加固、刷机脚本、GitHub 开源、Release 固件发布,到这篇文章发布,全部都是 OpenAI Codex 在我的授权、设备和账号环境下完成的。我提供目标、设备接入和现场配合,Codex 负责实际工程执行和验证。

项目背景

向日葵控控 A2 本质上是一台小型硬件 KVM:一边通过 HDMI 采集目标主机画面,一边通过 USB HID 模拟键鼠。但原厂使用方式强依赖向日葵客户端和云绑定,设备要接入向日葵体系才能获得完整体验。我的目标很直接:保留硬件能力,去掉云绑定,做成局域网/VPN 内可用的开源 KVM。

一开始也考虑过能不能直接移植 PiKVM。Codex 分析后否掉了这个方向:PiKVM 的 kvmd 依赖现代 Python、systemd、nginx、Janus 等组件,视频侧常见方案也依赖 V4L2/uStreamer;而 A2 是 128MB 内存、Linux 3.4、HiSilicon MPP 专用视频链路。强行移植完整 PiKVM,风险和维护成本都会很高。

最终方案

最后采用的是“PiKVM 体验,A2 原生实现”的方案:以 OpenIPC Divinus 为底座,保留它轻量 C/MPP 的架构,再针对 OrayKVM A2 增加专用硬件路径和最小 Web KVM 功能。

  • 不引入 Python、Node、数据库、nginx、Janus 或 systemd。
  • 运行时保持为一个 ARM C 服务、静态前端、配置文件、私有 musl 运行库和 SysV 脚本。
  • 保留原厂 U-Boot、Linux 3.4 内核、ADV7611、STM32 HID、网络、Dropbear SSH。
  • 只改 rootfs 分区 mtd2,不写 U-Boot、kernel、配置分区、序列号或校准分区。
  • 官方模式保留,OpenKVM 模式可一键切换。

参考项目和资料

  • OpenIPC Divinus:工程底座,大量原始 C 代码来自这里,保留了 Git 历史和 MIT 声明。
  • PiKVM kvmd:参考 Web KVM 体验、HID 控制模型、单控制端体验和快捷键设计,但没有直接移植完整 kvmd。
  • PiKVM uStreamer:作为视频路径对照。A2 不走 V4L2/uStreamer,而是走 HiSilicon MPP。
  • SwimmingTiger/oraykvm:参考社区逆向资料、按键表和设备行为说明。最终协议实现由 Codex 根据真机观测和测试重新实现。
  • OrayKVM A2 原厂固件:作为恢复基线、启动脚本、ADV7611/STM32 行为和官方模式对照。
  • HiSilicon Hi3516A MPP SDK / B030 用户态库:本地构建依赖,闭源库不提交到 Git,只通过脚本校验导入。

固件备份和安全边界

第一步不是写代码,而是备份。Codex 先通过设备 SSH 备份 mtd0 到 mtd4,并生成 manifest 和 SHA-256 校验。后续所有刷写都以这个备份作为恢复基线。

安全边界定得很死:mtd0、mtd1、mtd3、mtd4 不刷;mtd2 是 rootfs,只有最终确认后才允许人工 flashcp 写入。mtd3 是 JFFS2 配置分区,只允许通过正常文件操作保存 /config/openkvm/,不擦除、不裸写。

视频链路实现

A2 的视频不是普通摄像头 V4L2,而是 HDMI 输入经过 ADV7611,再走 BT.1120 到 HiSilicon VI、VPSS、VENC。Codex 在 Divinus 中新增了 A2 专用输入模式,跳过 sensor/ISP 初始化,直接建立:

ADV7611 -> BT.1120 VI -> VPSS -> H.264 VENC

调试中遇到过一个关键问题:整机重启后 ADV7611 有信号,但 VI 中断计数为 0,导致没有视频帧。后来定位到原厂启动流程会设置 /dev/hi_mipi 的 BT.1120 combo input mode,而 OpenKVM 独立启动时漏了这步。补上 input mode 6 后,视频链路恢复稳定。

当前 Web 提供三种视频路径:/video.mp4、/video.264 和 /mjpeg。主路径是分片 MP4,浏览器 MediaSource 播放;如果 MP4 不可用,会自动降级到 MJPEG。之前也修过一次 CSP 问题:页面自身生成 blob: MediaSource URL,但 CSP 没放行 media-src blob:,导致 Chrome 报错并降级。修复后,Chrome 长时间播放 MP4 稳定。

HID 键鼠实现

HID 部分通过 /dev/ttyAMA1 和 STM32 MCU 通信。Codex 没有直接复制原厂客户端代码,而是根据观测到的串口帧、ACK 行为和社区按键表重新实现。

  • 键盘支持常用键、F1-F12、方向键、编辑键和左右 modifier。
  • 鼠标支持绝对坐标、相对移动、左中右键和滚轮。
  • WebSocket 断开或 15 秒无心跳会释放所有按键和鼠标按钮,避免卡键。
  • 页面加入 PiKVM 风格快捷键,包括 Ctrl+Alt+Delete、Alt+Tab、Alt+F4、Win+L、Print Screen 等。
  • 只允许一个控制端,其他浏览器只能观看视频。

HID 调试里也遇到过“刚开始能用,过一会儿没反应”的现象。Codex 加了 MCU 回包排空、ACK 统计和状态暴露,最后确认服务端持续发包和读取正常;后续某次 status=1 更像是目标机 USB HID 枚举侧没有就绪,现场重插 USB 后恢复。这类问题也被写进了排障文档。

Web 控制台

Web UI 做的是精简 PiKVM 风格控制台,而不是完整 kvmd API。保留视频、键鼠、绝对/相对鼠标切换、滚轮、全屏、连接状态、快捷键、管理密码修改;删除 ATX、电源控制、虚拟介质、GPIO、OCR、录像、宏、终端、切换器等首版不需要的功能。

认证采用 HTTP Basic Auth,密码文件只保存带随机盐的 SHA-256 校验值。Web 里可以改管理密码,SSH 下也可以执行 openkvm –set-password。配置和密码固化在 /config/openkvm/,重启和模式切换后仍保留。

去云化和双模式

OpenKVM 模式下不启动 sunlogin_client、kvm_lan_ctrl、uhttpd 旧管理页和原厂云守护。Codex 还发现原厂 LED 网络探测脚本会周期性访问公网网站,于是把它也纳入模式守卫:OpenKVM 模式关闭,官方模式恢复。

同时,官方栈没有被完全删除,而是保留为回退模式。设备上可以执行:

openkvm-mode status
openkvm-mode official
openkvm-mode openkvm
openkvm-mode toggle

如果当前在原厂 44022 chroot SSH 会话里,可以通过:

/bin/busybox chroot /proc/1/root /usr/sbin/openkvm-mode toggle

这样一台设备可以在官方模式和 OpenKVM 模式之间来回切换,方便对照和回滚。

SSH 加固

设备原厂 SSH 比较老,而且有额外端口。Codex 对最终 rootfs 做了 SSH 加固:保留 44022 管理入口,关闭不需要的 44033,强化 Dropbear 参数,移除 DSA host key,设置更强随机密码,并把密码保存到本地 ignored 文件中,避免提交到仓库。

真机测试

测试不是只跑单元测试。Codex 做了主机端和真机端两类验证:

  • 主机端:HID 协议、WebSocket 控制、认证、配置持久化、模式切换、ASan/UBSan。
  • 视频探针:SYS/VB、VI、VPSS、VENC 逐步初始化,并确认实际 H.264 帧。
  • 浏览器测试:真实 Chrome/Edge 登录、视频、键鼠、全屏、重连、MP4/MJPEG 降级。
  • HID 测试:键盘、鼠标、Ctrl+Alt+Delete、断线释放、ACK 压测。
  • 稳定性:按我要求把原计划 2 小时改成 10 分钟 soak;600 秒运行通过。
  • 模式切换:官方/OpenKVM 往返,确认同一时刻只有一套视频/HID 栈运行。
  • 端口检查:OpenKVM 模式只保留 Web 和 SSH 管理入口,原厂 30080 关闭。

HDMI out 物理显示器闪屏也调过:一开始怀疑 OpenKVM,后来切回官方也闪,说明不是 OpenKVM 独有问题。最后把 EDID/输出目标降到 1080p30,作为更保守的兼容方案。

刷机和回滚

最终刷机策略很保守:只把 rootfs squashfs 写入 /dev/mtd2。刷机脚本也只做这件事。

sh scripts/flash-a2.sh --yes admin@<device-ip> 44022 ./openkvm-a2-rootfs.squashfs

脚本会把镜像上传到 /tmp,在设备端校验大小和 SHA-256,然后执行:

flashcp -v /tmp/openkvm-a2-rootfs.squashfs /dev/mtd2
sync
reboot

回滚同样是人工刷回原厂 mtd2,或者使用 USB 恢复镜像。启动脚本不会自动写 Flash。

GitHub 开源和 Release

Codex 最后把项目整理成公开仓库,处理了许可证、NOTICE、README 双语、刷机教程、GitHub Actions、secret guard 和 Release 资产。仓库地址是:

https://github.com/glzjin/openkvm-a2

首个实验固件 Release 是:

https://github.com/glzjin/openkvm-a2/releases/tag/v0.1.0

Release 里放了 rootfs、rootfs SHA-256、OpenKVM recovery USB 镜像、校验文件和初始密码包。没有上传 SSH 密码、私钥、live-check 抓包、factory-rootfs 或原厂备份。

仍然保留的边界

  • 首版只支持 OrayKVM A2,不支持 A2-300/Pro。
  • 不包含音频、ATX、虚拟介质、VNC/IPMI、云中继或完整 kvmd API。
  • 二进制固件是实验性质,刷机前必须确认自己有可用 SSH 和恢复方式。
  • 公网访问不建议直接暴露设备端口,应该走 VPN 或 HTTPS 反向代理。
  • HiSilicon MPP 和原厂固件存在闭源边界,源码开源不等于这些闭源二进制可自由再分发。

总结

这次项目最有意思的地方,不是“写了一个 Web 页面”,而是 Codex 把一个真实嵌入式设备从备份、逆向、协议、视频、HID、系统服务、rootfs、刷机、回滚、开源发布完整跑通了。中间没有跳过安全边界:能不写 Flash 就不写,能只写 mtd2 就不碰其它分区,能保留官方模式就不一刀切删除。

从结果上看,OpenKVM-A2 已经把向日葵控控 A2 变成了一台可以本地访问、可以开源构建、可以一键刷入、可以回滚官方模式的轻量 KVM。这个过程全部由 Codex 完成,我只负责提出目标、提供设备和做必要的现场配合。


文章来源: https://www.zhaoj.in/read-9189.html
如有侵权请联系:admin#unsafe.sh