之前那版写得太短了,这里重新整理成完整复盘。这个项目是一次把向日葵控控 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 功能。
第一步不是写代码,而是备份。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 部分通过 /dev/ttyAMA1 和 STM32 MCU 通信。Codex 没有直接复制原厂客户端代码,而是根据观测到的串口帧、ACK 行为和社区按键表重新实现。
HID 调试里也遇到过“刚开始能用,过一会儿没反应”的现象。Codex 加了 MCU 回包排空、ACK 统计和状态暴露,最后确认服务端持续发包和读取正常;后续某次 status=1 更像是目标机 USB HID 枚举侧没有就绪,现场重插 USB 后恢复。这类问题也被写进了排障文档。
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 比较老,而且有额外端口。Codex 对最终 rootfs 做了 SSH 加固:保留 44022 管理入口,关闭不需要的 44033,强化 Dropbear 参数,移除 DSA host key,设置更强随机密码,并把密码保存到本地 ignored 文件中,避免提交到仓库。
测试不是只跑单元测试。Codex 做了主机端和真机端两类验证:
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。
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 或原厂备份。
这次项目最有意思的地方,不是“写了一个 Web 页面”,而是 Codex 把一个真实嵌入式设备从备份、逆向、协议、视频、HID、系统服务、rootfs、刷机、回滚、开源发布完整跑通了。中间没有跳过安全边界:能不写 Flash 就不写,能只写 mtd2 就不碰其它分区,能保留官方模式就不一刀切删除。
从结果上看,OpenKVM-A2 已经把向日葵控控 A2 变成了一台可以本地访问、可以开源构建、可以一键刷入、可以回滚官方模式的轻量 KVM。这个过程全部由 Codex 完成,我只负责提出目标、提供设备和做必要的现场配合。