将ThinkPad X61移植到Coreboot
介绍我的IBM/联想ThinkPad成瘾经历 十多年前,我得到了我的第一台ThinkPad x60。通过阅读GNU Emacs编辑器中的GNU页面,我对自由软件产生了兴趣。那时的自由软件,当然现在也是,相对易用,通常没有太多的闭源软件。自由软件的一个缺失领域是固件,这让我想尝试在这台ThinkPad x60上使用libreboot。几年后,我成为了一名coreboot贡献者,并因此在9elements找到了工作。在这段旅程中,我积累了一大堆ThinkPad收藏。我想要更快的64位机器,于是购买了一台ThinkPad x200,使用了几年。几年后,我又买了一台ThinkPad x220,因为Sandy Bridge芯片的速度远远超过x200中的Core 2 Duo。为了移植或改进现有的coreboot移植,我又收到了ThinkPad x201和R500。几年前,有人找出了绕过Intel Skylake/Kabylake上的Boot Guard(deguard)的方法,因此我购入了ThinkPad t480,并对此非常满意。有人知道适合这种成瘾的康复中心吗?在这条ThinkPad囤积的道路上,有一个世代的机器缺失:ThinkPad x61。它有一个GM965北桥和一个ICH8南桥。北桥与GM45(在ThinkPad x200上受支持)有些相似,但仅支持DDR2,而ICH8南桥与已经支持的ICH9相似。关于这个平台没有泄露的文档,因此逆向工程将是唯一的解决方案。一些人过去尝试使用像SerialICE这样的工具来运行QEMU中的固件,并将IO和MMIO转发给实际硬件,但他们未能产生一个可用的coreboot移植。所以我的梦想是最终能成功移植它。 AI辅助逆向工程 在三月份,我开始尝试在我的工作流程中更多地使用大型语言模型(LLM)技术。对于快速原型设计,这种方法效果相当不错,但我想知道它在逆向工程中的表现如何。请注意,我当时使用的是Anthropic的Claude Opus 4.6,这是当时最先进的技术。结果证明,它们在加速过程中非常有效。通常情况下,逆向工程需要相当大的投入。对于整个平台(x61的gm965/ich8)的移植,花费3-6个月也是很有可能的。这段时间,对于我来说,显然不够。 TL;DR 我在下载的厂商BIOS上进行了尝试,结果看起来很不错。之后我购买了设备并让其正常工作。接下来将解释这个过程是如何进行的。 从厂商BIOS中传统提取信息 在尝试了解厂商固件的功能之前,我首先想从一个工作系统中尽可能多地提取信息。当某个功能未按预期工作时,已知的良好值非常有价值:当DRAM没有训练或USB突然停止工作时,拥有可以比较的参考非常有用。它也能为平台的某些部分提供良好的提示,比如EC设置、ACPI表、PCI配置、GPIO引脚配置和HDA动词表。为此,我使用了常规的coreboot工具。inteltool提供了PCI配置空间的良好概述以及几乎所有北桥和南桥寄存器的视图。lspci仍然是一个快速检查Linux如何看待机器的有用工具。对于ACPI,我使用acpidump提取了表,使用acpixtract拆分它们,并用iasl -d反编译。这提供了一种可读的视图,展示了厂商固件是如何向操作系统描述设备、电源管理和EC方法的。ectool对查看EC RAM和行为非常有用,因为ThinkPad往往在这里隐藏了许多特定于主板的细节。我还保存了CPU信息和HDA编码器信息,因为在盯着固件代码时,这些容易被遗忘。 设置AI代理工具以及一些固件发现 x61使用Phoenix BIOS,所以第一步是使用bios_extract将映像拆分成单独的模块。之后,我为AI代理提供了一些可以直接使用的工具。其中最有用的是ghidra-cli,结合其SKILL.md,因此它可以在我不需要不停控制GUI的情况下向Ghidra询问问题。我还使用了radare2技能,因为radare2对于老旧的16位实模式固件部分相当愉快。这种区分很重要,因为大多数固件是16位实模式代码,但raminit本身是一个PE32模块,看起来像是来自Intel MRC(内存参考代码)。在这部分,ghidra-cli效果更好,因为原始代码可能是C语言,反编译的输出实际是有用的。对于周围的胶水代码,radare2通常是AI代理成功的更好选择。一件让我惊讶的事情是,在映像中发现了至少3个版本的raminit。我的猜测是这是一种A/B布局,带有只读的恢复副本。只读副本跳过了正常的raminit流程,可能只用于将机器恢复到足够重新写入其余部分的状态。
本站免费、广告极少。如果觉得有帮助,可以请我们喝杯咖啡 —— 任何金额都对持续运营有实际帮助。
☕请我喝杯咖啡