占个坑,预计在这边编辑完之后会同步到我博客,这样可以获取一些早期反馈
目标
将你的 LoongArch 电脑从以下技术状态:
- UEFI 固件为旧世界(虚拟地址)固件,
- 引导器为 grub2 的早期移植(不认识 PE 格式的 Linux EFI stub,只能引导 ELF 格式的 Linux 内核),
- 内核为使用 BPI 引导协议的新世界内核(目前版本号都大于 4.19 小于 5.19,即一个类似 5.1x 的版本),
迁移至以下技术状态:
- UEFI 固件为新世界(物理地址)固件,
- 引导器为 grub2 的后期移植(只能引导 PE 格式的 Linux EFI stub,不认识 ELF 格式的 Linux 内核),
- 内核为使用 EFI stub 引导协议的新世界内核(目前版本号都至少为 v5.19-rc1),
且不影响系统的任何其他状态(如已安装软件、个人数据等)。
如果你目前在使用旧世界发行版(Loongnix/UOS/Kylin 等;内核版本为 4.19.x),不能直接升级,必须先重装系统,变为新世界发行版(Archlinux、Gentoo、CLFS 等),才能操作。因为旧世界发行版至今(2022.06)无一跟进新世界固件、引导协议等内容,因此升级固件后不可能正常工作。
背景知识
旧世界、新世界
最早只有一个世界。龙芯转向 LoongArch 之前,MIPS 的最底层生态已经成熟稳定,也就没有这档子事。但自从龙芯决定要搞自己单独一套架构,完全没有生态,那生态从哪来?龙芯一开始觉得 MIPS 是好的,于是把现有底层组件的 MIPS
字样就批量替换成 LOONGARCH
,除了汇编、反汇编这种涉及机器语言的地方才真正重写,人们都觉得这样做没什么问题,你看这程序不是跑起来了吗?商业上时间不等人,为了抢占先机,龙芯把这个世界跑通之后直接就给下游厂商了。这个世界的底层逻辑就由此固化,很难撼动。是为“旧世界”,一个除了名字不一样,别的都跟 MIPS 一样的世界。
这些事情都做完之后,像是一个步骤结束了开始下一个步骤,龙芯才开始大举向上游开源社区推送 LoongArch 适配补丁。上游的同学们看了这些补丁,大跌眼镜,这不就是 MIPS 代码复制粘贴吗?接下来的事情很多人已经知道了——除了少数一些不关注平台移植细节和审美,甚至看都不看闭眼合并的上游之外,这些复制粘贴的补丁基本都折戟沉沙。龙芯的员工们也渐渐意识到,闭眼抄 MIPS 不行——毕竟是两个不一样的架构嘛!自己都说了做个新架构摆脱 MIPS 历史包袱,结果实际上是把历史包袱一个不差都复制过来,这样着实不好。很多人似乎也是被上游提醒了才知道,世界上不只 MIPS 一个架构,当做事情方法不一样的时候,MIPS 往往是特立独行的那个,而不是别人,因而跟 MIPS 无脑保持一致反倒增加了其他人的负担。
于是乎,后期的龙芯员工们停下了无脑推送,开始老老实实按正常方式移植、适配软件,写出了一些基本摆脱 MIPS 影响的东西,这些就能够顺利进入上游了。这些全新写作的代码基本没有历史包袱,互相之间也能正常配合,但正是由于摆脱了历史包袱,这个世界就总是与“旧世界”存在这里那里的不同,因而不能互相兼容;是为“新世界”。
旧世界固件、新世界固件
在一部分龙芯员工的描述中,旧世界固件也叫“虚拟地址固件”,新世界固件也叫“物理地址固件”。此命名的依据是该两种固件向软件开发者暴露接口的最大区别:旧世界固件提供的各种表格、指针地址都是 0x9000_xxxx_xxxx_xxxx
格式的,不是物理地址,而是透过预先配置的对整个物理地址空间的 1:1 可缓存映射窗口(与 Linux 内核对 CSR DMWIN1 的初始配置一致)访问内存的“虚拟地址”。这也是同一内核(目前)不能兼容新旧世界固件的主要原因之一。
除以上区别之外,该两种固件还有其他区别。下表列出了新旧世界固件所有存在差异的维度。由于该论坛的软件不支持 Markdown 表格,以下内容换成列表形式展现。
- 指针性质
- 旧世界固件:可缓存映射(虚拟)地址
- 新世界固件:物理地址
- 默认引导文件搜索路径
- 旧世界固件:
\EFI\BOOT\BOOTLOONGARCH.EFI
或与新世界一致
- 新世界固件:
\EFI\BOOT\BOOTLOONGARCH64.EFI
- ACPI 6.5 规范
旧世界的 ACPI 表结构不同,是至今(2022.06)为止的新世界发行版都必须使用 initrd 覆盖固件 ACPI 表,才能正常启动的原因。具体而言,内核预期的 ACPI MADT 结构与旧世界不同,新世界内核直接看到旧世界 ACPI MADT 则会认为系统有 0 个 CPU,因而初始化失败。
可能存在一些旧世界固件,其默认引导文件也叫 BOOTLOONGARCH64.EFI
。具体以你电脑上 EFI 分区的现状为准。但所有新世界固件都仅支持 BOOTLOONGARCH64.EFI
一个文件名。
BPI
新旧世界的固件对引导器、内核都仅仅提供相当标准的 UEFI 编程接口。但在 Linux/LoongArch 一侧,接受固件、引导器参数的具体方式,即“引导协议”(boot protocol)却存在历史包袱。即便早期的新世界内核(2022.06 之前),也不能从固件直接接受参数,而需要特制的 grub 为其转换一道,将标准的 UEFI 引导协议适配为龙芯公司特有的 BPI 引导协议。目前该问题已经解决,以 Linux v5.19-rc1 接受了 LoongArch 不带引导支持的补丁为分水岭,之后的新世界内核将以通用的 EFI stub 方式被 grub 或固件直接引导。
请注意,新旧世界的区分存在许多维度。从上面的描述也可看出,确实有一个历史时期,即便一个内核在用户态 ABI 层面被认为是新世界,它也可能仅支持旧世界引导协议,从而需要搭配旧世界固件使用。
BPI 是笔者对《龙芯CPU开发系统固件与内核接口规范》的简称,因为该规范本身没有简称,但早期 LoongArch Linux 移植中使用的 struct bootparamsinterface
与该规范一脉相承。(在 Linux/LoongArch 最初上游工作的中后期,使用该接口规范的版本 v6 v7 v8 v9 已经把结构体名字改成和 MIPS 时代一致的 struct boot_params
了,但在 LoongArch 推出以来的大部分时间这个结构体都叫 BPI,因此仍然保留这个名字。龙芯开发人员从 v10 开始,接受了上游提议,删除了所有 BPI 残余,看起来这些 MIPS 包袱他们自己也不喜欢 😏)
《龙芯CPU开发系统固件与内核接口规范》是龙芯公司的企业标准,从 MIPS 时代(该规范初版发布于 2014 年 4 月 1 日)就已存在。为了不要让 LoongArch 架构从一开始就与龙芯公司的具体硬件、固件、参考系统产生不必要的耦合,以及为了尽量减少架构相关的独特内容以便降低维护负担,上游 Linux 社区一直不建议以该规范引导 Linux/LoongArch。由于龙芯最终接受了上游建议,该规范的 LoongArch 版已经不会正式发布了(即使发布也会删除所有 BPI 相关内容),所有 BPI 相关的实现细节都只能参考先前版本的 Linux/LoongArch 补丁。
前置条件
- 一台运行旧世界固件、新世界用户态的 LoongArch 电脑
- 一个空白 U 盘(或其他固件支持从中引导的介质)
- (强烈建议)另外一台运行 Linux 的电脑
- (强烈建议)一个烧录器(推荐使用 CH341A 方案的,大路货,被 flashrom 原生支持,我用了好用。或你手头证实可用的其他型号)
- (可选,适用于 A2101 主板用户)一片 Zbit ZB25VQ64ASIG 或与该芯片尺寸、引脚兼容的其他型号
- (如果使用 flashrom 操作编程器,强烈建议)编译最新版的 flashrom 以支持新型号的 SPI flash 芯片。A2101 用户将别无选择,因为目前最新的正式版本 v1.2 没有带上这个提交所以无法操作 ZB25VQ64ASIG 芯片。
准备工作
- 下载一个可引导的搭配新固件使用的新世界系统镜像,将你的 U 盘制作为 LiveUSB
- 如有烧录器,备份你当前的固件芯片完整内容,以便救砖
- 备份你的
/boot
与 EFI 分区内容,以便救砖
- 确认你的备用电脑可用(flashrom 正常工作,可正确制作 LiveUSB,等等)
- 将 LoongArch 电脑上制作的备份传输到该电脑,并确认数据未损坏(可用
sha256sum
等工具)
操作步骤
待完善 ;-)