在 Lenovo IdeaPad Duet 上运行 Ubuntu

Hacker News Top 新闻

摘要

作者描述了在 postmarketOS 出现问题后,在 Lenovo IdeaPad Duet Chromebook 上运行 Ubuntu 的过程,涉及固件破解并利用主线 Linux 内核驱动程序。

暂无内容
查看原文
查看缓存全文

缓存时间: 2026/09/17 18:14

# 在联想IdeaPad Duet上运行Ubuntu | Valentin Haudiquet 来源:https://vhaudiquet.fr/blog/duet-ubuntu/ 我拥有一台联想IdeaPad Duet Chromebook,这是一款运行ChromeOS的ARM64二合一平板。我曾使用ChromeOS,后来转投postmarketOS,但后者突然崩溃了。是时候尝试一些固件修改,让Ubuntu在这台设备上运行了! ## 联想IdeaPad Duet (https://vhaudiquet.fr/blog/duet-ubuntu/#lenovo-ideapad-duet) *联想IdeaPad Duet:一款10.1英寸平板,配备即插即用的可拆卸键盘、1920x1200分辨率屏幕、ARM64联发科MT8183 SoC和4 GiB内存*(图片来源:联想 https://www.lenovo.com/fr/fr/p/laptops/lenovo/chromebooks/lenovo-ct-x636/zziczctct1x) 我是在工程学院第一年期间购入这台设备的。它价格便宜(约100欧元),虽然是二手但成色很好。我喜欢10英寸笔记本的便携性,而且这款设备甚至支持手写笔操作,这种工作流程我曾想尝试(结果发现并不适合我)。 我也从未使用过ChromeOS,当时非常好奇。那时我正在开发Android应用,能够原生编码并在设备上运行应用听起来令人兴奋。结果却很失望,因为ChromeOS的性能并不理想,我不得不通过容器运行所有Linux应用,感觉很别扭。于是我悄悄停止了使用这台设备。 不久后,我发现postmarketOS (https://postmarketos.org/) 支持这款设备。这意味着可以运行真正的Linux发行版,基于Alpine Linux (https://alpinelinux.org/),支持任意桌面环境(GNOME、KDE等),并具备完整的Linux工具链和性能。我必须尝试一下。 安装postmarketOS非常简单,这要归功于他们在wiki (https://wiki.postmarketos.org/wiki/Lenovo_IdeaPad_Duet_Chromebook_(google-krane)) 和安装指南 (https://wiki.postmarketos.org/wiki/Category:ChromeOS) 上付出的努力。基本上就是:将设备设为“开发者模式”,下载镜像,写入U盘,然后通过“开发者模式”菜单从U盘启动。这样就能进入postmarketOS实时镜像,用于安装到eMMC存储。 *ChromeOS固件的“开发者模式”菜单,可在此选择启动介质——USB或内部存储。我的设备显示为法语界面。其中的“启动传统BIOS”功能在此无效;我怀疑这仅适用于x86架构Chromebook,他们只是沿用了相同的固件。* 到目前为止一切顺利:他们甚至提供了预装GNOME等桌面环境的镜像。我日常主力电脑使用GNOME,所以选择了这个。不幸的是,事实证明这是个错误。GNOME资源消耗较大,不适合这款设备较弱的CPU和4 GiB内存。运行起来有点卡顿,而且操作摩擦太大,实际使用体验不佳。我也发现GNOME不太适合“极简”工作流程——它倾向于功能全面展开。现在回想起来,对于这台设备,平铺窗口管理器配合以终端为中心的工作流程可能更合适。 但我偶尔还是会使用它。最终我升级到了postmarketOS 26.06,随后设备就无法重启了。 我设法启动了旧的25.12版本,但即使将26.06写入U盘启动也似乎无效。两个版本之间必然发生了某些变化,导致Duet静默启动失败。在调查过程中,我发现所有必要的驱动程序现在都已进入主线内核。同时,我现在在Canonical从事Ubuntu开发工作,负责RISC-V设备的移植支持 (https://vhaudiquet.fr/blog/joining-canonical-riscv/)。鉴于Duet的现状,进行Ubuntu移植看起来确实可行。那么...这个周末我有空,动手试试吧! ## 安装Ubuntu? (https://vhaudiquet.fr/blog/duet-ubuntu/#installing-ubuntu) 此时,我几乎不了解postmarketOS如何在该设备上启动、启动流程是怎样的,也不确定Ubuntu能否正常运行。获得“类Ubuntu系统”最简单的方法之一就是用Ubuntu rootfs替换postmarketOS 26.06的rootfs。于是我照做了。 我通过postmarketOS 25.12的U盘启动系统,首先检查了内部eMMC存储的状态: *在/dev/mmcblk0上运行fdisk,打印分区表* 好的。所以存在一个神秘的“ChromeOS Kernel”分区、一个`/boot`EFI分区,然后是rootfs分区。安装Ubuntu rootfs的简便方法就是直接替换后者。我正是以最简单粗暴的方式这样做的: 完成后,我准备通过`chroot`进入`/mnt`来使用新的Ubuntu系统。 *从postmarketOS 25.12 U盘chroot到/dev/mmcblk0p3上的新Ubuntu rootfs。我甚至安装了一些软件包,比如fastfetch!注意看6.12.87-mt81内核:这是来自U盘的postmarketOS内核。* 很好,这一切都很棒,但永远生活在chroot环境中,每次挂载内部存储都要从U盘启动,这种体验实在不好。是时候看看能否直接启动这个新rootfs了!我原以为会失败,因为假设是新版postmarketOS 26.06内核有问题,但令我惊讶的是它完美启动了。这意味着26.06的问题可能出在rootfs启动程序上,静默崩溃了某些组件。 *从内部存储启动到/dev/mmcblk0p3上的Ubuntu rootfs。注意新的6.18.44-mt81内核:这是来自26.06安装的postmarketOS内核,位于/dev/mmcblk0p1或p2启动分区。* 如你所见,设备现在自称`localhost`,因此需要完成一些配置设置;不过我之前在chroot中已经创建了用户账户。另一个问题是:新rootfs缺少postmarketOS内核所需的固件,所以Wi-Fi无法工作了。简单的解决方法是提取26.06镜像中的`/lib/firmware/6.18.../*`目录树并复制到rootfs中,即可恢复Wi-Fi功能。 但这样就要一直使用postmarketOS内核,无法更新。我不想要这样,我希望运行完整的Ubuntu,包括内核。 于是我做了最简单的事:从软件仓库安装了`linux-generic`软件包。它将`vmlinuz`和`initrd`复制到了`/boot`分区(/dev/mmcblk0p2)。我还将上游设备树文件复制到`/boot`分区,以便在需要时硬编码到内核命令行。我预期一切都会崩溃、无法工作,因为我不了解引导加载程序,且假设内核无法获得正确的设备树文件。然后我重启了设备。 令我惊讶的是,设备正常启动了。更棒的是:我再次运行`fastfetch`,发现**所有内容**完全相同,**包括内核版本**。 等等,什么?我刚刚才覆盖了`/boot`分区中的内核。那个分区根本没被使用吗? ## 使用Ubuntu内核 (https://vhaudiquet.fr/blog/duet-ubuntu/#using-the-ubuntu-kernel) ### 理解启动流程 (https://vhaudiquet.fr/blog/duet-ubuntu/#understanding-the-boot-flow) 显然,我需要退一步真正理解设备如何启动,因为随机尝试的方法不再奏效。于是我查阅了一些资料,并与Claude交流,提供URL并请求解释启动流程。 原来Chromebook的启动流程有点复杂。以下是Claude向我解释链式启动时生成的示意图。我觉得它们非常清晰。 Chromebook固件启动链。引导ROM包含FSBL,它加载Coreboot,后者对Duet已有上游支持 (https://github.com/coreboot/coreboot/blob/main/src/mainboard/google/kukui/panel_krane.c)。然后Coreboot加载ARM可信固件(与本分析无关),再加载Depthcharge (https://chromium.googlesource.com/chromiumos/platform/depthcharge/),这是ChromeOS设备的引导加载程序。 所以Depthcharge这个ChromeOS引导加载程序,也负责显示“开发者模式”菜单,让我在启动时选择USB或内部存储。这很有趣。那么下一步是什么?Depthcharge实际加载什么? Depthcharge启动内部存储。它只关心第一个神秘的“ChromeOS kernel”分区。该分区实际上包含FIT镜像 (https://fitspec.osfw.foundation/),这里基本是内核、initrd和设备树的打包文件。 这样就清楚了!`/boot`分区在启动时从未*实际*使用过,只被postmarketOS用来准备Depthcharge FIT镜像(使用`mkdepthcharge`工具)。所以仅仅安装新内核到那里还不够。我还需要重新生成Depthcharge镜像。 ### 需要EFI环境 (https://vhaudiquet.fr/blog/duet-ubuntu/#efi-environment-needed) 虽然这很容易实现,但不幸的是无法工作。注意,在此启动流程中,从未涉及支持EFI的固件。既未使用EDK2也未使用U-Boot:Depthcharge直接从FIT镜像加载并启动内核。这对postmarketOS内核有效,但对Ubuntu内核无效,因为Ubuntu内核是EFI可执行文件,需要EFI环境。**Ubuntu仅通过UEFI启动 (https://ubuntu.com/hardware/docs/image-cookbook/explanation/bootflow/)**。 因此,我们需要支持UEFI的固件。最容易实现的是U-Boot:EDK2可能更难处理,而U-Boot已对`mt8183` SoC提供支持。但该支持仅作为SoC参考开发板“Pumpkin”的配置存在,因此我们需要对U-Boot进行一些修改才能引导。我们的目标是通过Depthcharge链式加载U-Boot,以获得UEFI环境,然后由其启动Grub,最终引导我们的Ubuntu内核: *Depthcharge后的目标启动流程* 开始捣鼓U-Boot吧!等等,但我们知道如何向屏幕输出信息吗?该如何调试?我们不能指望没有任何板级驱动的U-Boot能直接打印调试日志...而且点亮屏幕也不容易。让我们仔细想想。 ## U-Boot (https://vhaudiquet.fr/blog/duet-ubuntu/#u-boot) ### 我们的目标 (https://vhaudiquet.fr/blog/duet-ubuntu/#our-target) 我们的目标是让U-Boot作为Depthcharge的有效载荷被链式加载,以便它能访问eMMC并加载其中的Grub。Grub随后将使用UEFI存储驱动(即通过EFI API暴露的U-Boot驱动)来加载内核和initrd。 U-Boot已对`mt8183`提供支持,因此无需编写驱动,这使这项工作成为可能。不幸的是,我们仍需针对联想IdeaPad Duet进行板级适配。我也会用其代号`kukui-krane`来指代它(`kukui`是基于`mt8183`的Chromebook的代号,`krane`特指联想IdeaPad Duet)。 实际上,我们需要某种形式的日志来调试U-Boot构建。两个选项: - 使用板上的串行输出。这实际上可行,可以通过称为SuzyQable (https://chromium.googlesource.com/chromiumos/third_party/hdctools/+/main/docs/ccd.md#suzyq-suzyqable) 的设备实现“CCD”(闭壳调试),在Chromebook上提供UART接口。不幸的是,我没有这样的线缆(已订购)。 - 直接使用屏幕。更难一些,因为我们需要为该特定面板或Coreboot初始化的特定帧缓冲编写驱动。这也是我们最终想要实现的:让设备获得完整的U-Boot支持。那么开始吧! Coreboot源码树中有个`krane_panel.c`文件包含部分面板初始化代码。我不太确定该如何处理它,但认为要么可以借鉴Coreboot/Depthcharge代码重写面板驱动,要么直接使用Coreboot已设置的帧缓冲。于是我将这个建议提给了Claude。 它立刻提出了一个绝妙的想法:与其直接尝试在U-Boot中实现,不如编写一个汇编存根,在屏幕上显示颜色。它还弄清了如何读取Coreboot的“LBIO”表以获取帧缓冲详情。我要求它提供一个代理实现该功能的详细提示,它便写了出来。 ### krane-fb-stub (https://vhaudiquet.fr/blog/duet-ubuntu/#krane-fb-stub) 我重启Duet,安装了OhMyPi (https://omp.sh/) 并连接到GLM-5.3-Flash (https://z.ai/blog/glm-5.3-flash)。然后我提供了Claude准备的提示,它开始实现存根并调查设备上所有可用的内核/固件日志。 > ## 任务:为联想IdeaPad Duet(MT8183/Krane)构建并测试最小化的ARM64“帧缓冲hello”存根 > ## 目标 > 生成尽可能小的独立ARM64二进制文件,使其能被Depthcharge(ChromeOS固件引导加载程序)当作Linux内核加载,该文件仅用于定位已初始化的启动画面帧缓冲并在不同检查点填充纯色。这将在实际U-Boot移植工作开始前验证完整的Depthcharge→自定义有效载荷流程。目前不涉及U-Boot——这是从零开始的独立二进制文件,尽可能小且无依赖。 *输入给我本地OhMyPi + GLM-5.3-Flash代理的提示摘录* 代理愉快地开始编写ARM汇编作为入口点,然后是C代码实现实际的“颜色显示”功能,即解析Coreboot表和设备树、查找帧缓冲以及显示颜色的工具代码。 流程如下:代理构建项目,然后打包成Depthcharge镜像并刷入内部存储。接着我重启设备查看效果并反馈给代理。我们总共尝试了10次才获得完全工作的存根。 *OhMyPi在QEMU中测试帧缓冲存根,实现过程中(顺便说明,这**不是**提示的一部分)* 出现了一些小问题,比如寄存器布局错误,需要回头对比Coreboot和Depthcharge代码树。调试起初很困难,因为“黑屏、无背光”可能意味着任何问题,从完全没有有效载荷到显示驱动的任何部分出错。 最终它找出了真正问题:Depthcharge实际上在清空屏幕、关闭背光并禁用显示。这是个真实问题,代理选择通过添加*恢复*步骤来规避:在交接后立即撤销Depthcharge所做的操作。 之后调试变得更容易了:我开始看到背光模式(闪烁),可以向代理描述作为反馈。很快,屏幕上出现了颜色。 最终,存根完成,显示了Claude设想的颜色序列:红色(早期初始化)、黄色(DTB解析完成)、绿色(LBIO解析完成)、蓝色(一切正常)。这实际上是代理伪造的,因为早期初始化、DTB和LBIO都是查找帧缓冲所必需的,所以它只是解析全部并按顺序显示所有颜色。无论如何,现在可以向帧缓冲绘制内容了! *最终存根在Duet上启动的效果* ### U-Boot使用帧缓冲 (https://vhaudiquet.fr/blog/duet-ubuntu/#u-boot-using-the-framebuffer) 这种帧缓冲恢复技巧有点粗糙;但我仍然没有串行线缆,真的很想在屏幕上查看U-Boot日志,现在我们有了屏幕输出能力,所以就这么办吧。 存根完成后,我让代理为新会话准备提示,以使U-Boot在板上工作,包括复用存根工作的图形输出功能。 > ## 任务:在联想IdeaPad Duet(google, krane sku176, MT8183)上移植主线U-Boot > 你接管了一个刚通过首个里程碑的移植工作:一个最小裸机有效载荷("krane-fb-stub")通过Depthcharge启动并能在面板上绘制内容。你的任务是将其替换为主线U-Boot作为有效载荷,实现可工作的帧缓冲控制台,形式需便于后续上游合并到主线U-Boot。 > ## 当前状态 > (h

相似文章

将ThinkPad X61移植到Coreboot

Hacker News Top

一篇博客文章,详细介绍了使用Claude Opus 4.6进行AI辅助逆向工程,将ThinkPad X61移植到coreboot开源固件的过程。

将 ThinkPad T480 用作手机

Lobsters Hottest

一篇博客文章描述了如何将 ThinkPad T480 改造成功能完整的手机,使用 Libreboot、Quectel EG25-G 调制解调器和自定义固件,实现通话、短信和移动数据功能。

老旧硬件上的Linux:全面复活指南

Hacker News Top

一份利用Linux复活老旧硬件的全面指南,涵盖发行版选择、硬件评估、内存调优、SSD升级和浏览器优化,并推荐2026年轻量级发行版如antiX、BunsenLabs、Xubuntu和Linux Lite。