效果展示与过程讲解
【RISC-V】在开发板上使用 UEFI 启动 NixOS ISO
开源仓库与镜像下载
开源仓库: github.com/YooLc/nixos-spacemit
在仓库根目录下使用 “nix build .” 就可以直接构建 iso 镜像
也可以使用我预构建的文件:
risc.v64.zip/nixos-minimal-25.05.20250811.dc50f20-riscv64-linux.iso
制作过程 (文字版)
要在 MUSE Pi Pro 上进行 UEFI 启动,我们需要做哪些工作呢?
图中展示的是 RISC-V UEFI 启动流程。其中 OpenSBI 和 EDK II 已经由厂商提供,烧写在板子的 SPI nor 介质上。EDK II 可以提供一个标准的 UEFI 环境,因此我们不需要定制这一部分。
而后面的 GRUB 2 Linux 内核以及用户态程序,则需要包含在 ISO 镜像或者 emmc 镜像中
传统的 uboot 启动模式下,制作一个镜像,往往要把 uboot 和 OpenSBI 等 bootloader 全部放到镜像里,导致镜像只能适配单独一个开发板,失去了灵活性
而 UEFI 可以让一块启动盘兼容多款产品,因为它只需要标准的 EFI 程序来启动内核,体现出了 UEFI 的好处(不过这里我们还没有讨论设备树的问题,之后会提到)
而 NixOS 的特点在于它对于系统构建流程的描述方式清晰且统一(且可复现),我们只需要编写几个 Nix 文件便可以生成完整的系统。
同时 NixOS 官方还提供了 ISO minimal installer 的 Nix 模块,让我们可以直接调用。这样,我们无需考虑打包一个 ISO 的过程,便可以精细地控制生成的 ISO 中包含哪些内容,以及系统需要携带的软件包,这就是我此次选择适配 NixOS 的原因
那么如果要给 Muse Pi Pro 适配一个新的发行版,又需要做什么呢
官方在 Bianbu Linux 的文档里给出了一个简单的描述。其中 OpenSBI 和 uboot 我们无需准备,因为是 UEFI 启动。
而剩下的部分总结下来就是三个要素:Linux 内核、设备树,还有 initramfs。接下来我们分别展开来看。
Linux 内核
对于 Linux 内核来说,官方目前还没有把设备树和驱动提交到主线。因此我们还是只能使用厂商定制内核。官方在 gitee 开源了自己的内核源码,我们选用 Linux 6.6 的源码来编译。
不过在尝试的时候还是遇到了一些问题:一个是进迭的 kernel 包含了一些树外的设备驱动,比如 rtl8852bs 无线模块的驱动,这些驱动代码质量不如主线源码,似乎不尊重 make flags。而 nixpkgs 的 buildLinux 函数编译内核时,会先创建一个 build 文件夹,然后再把所有编译产物都生成到 build 文件夹下,这样编译会找不到头文件
我也不想一个一个去改树外内核模块,所以选择了把 Nix 的 buildLinux 函数进行 overlay,让它不再创建一个 build 文件夹,最终编译出了可以使用的内核。
设备树
至于设备树,解包 Bianbu Linux 的系统镜像里可以看到,是 GRUB 读取了 UEFI 变量,获得了product_name这个变量的值。然后将其拼接成需要加载的设备树名称,这样就可以根据版型自动选择设备树,实现同一镜像的兼容
不过我在制作 GRUB 镜像的时候没找到如何让 GRUB 支持读取 UEFI 变量
进迭的镜像里使用的 efienv 指令也没有文档描述,不太清楚是怎么做的
因此我目前还是硬编码的 MUSE Pi Pro的设备树,不过 Bianbu Linux 的镜像告诉我们是可以实现兼容的
顺便一提,GRUB 镜像目前我还是在 Bianbu Linux 上使用 grub-mkimage 指令生成的。因为 nixpkgs 中的 GRUB 在 RISC-V 设备上会遇到 relocation error 的问题,我还不太清楚怎么解决
initramfs
最后就是 initramfs 了(对应 NixOS Stage 1),我们需要打入必要的内核模块和固件
首先是 iso9660 和 squashfs,没有他们内核就没办法识别 ISO 的内容
然后还有 esos.elf 也是必要的,没有它系统就无法正常启动
后面我还添加了无线模块和显卡的内核模块与固件,效果是无线可以正常工作,显卡可以识别出型号和信息
但是目前因为 mesa 包移植的问题(从 Bianbu Linux 移植到 NixOS,因为 NixOS 不遵循 FHS,需要对进迭的 mesa 包做修补),还不能做到显卡渲染。如果有比较了解的小伙伴可以尝试研究一下,感谢![]()



