Nixos on OrangePi R1 Plus LTS
2024-01-06
前言
前几天买了个OrangePi R1 Plus LTS打算当作软路由,虽然网上已经有编译好的各种镜像,不过大多数是OpenWrt,并且固件比较旧。 偶然搜到这篇Arch Linux on Orangepi R1 Plus LTS,那么既然Arch都能装,那为什么不试试NixOS呢。
Github: ri-char/nixos-orangepi-r1-plus-lts
启动原理
rock-chips文档中有这么一幅图,很详细的描述了启动镜像的布局。
+--------+----------------+----------+-------------+---------+
| Boot | Terminology #1 | Actual | Rockchip | Image |
| stage | | program | Image | Location|
| number | | name | Name | (sector)|
+--------+----------------+----------+-------------+---------+
| 1 | Primary | ROM code | BootRom | |
| | Program | | | |
| | Loader | | | |
| | | | | |
| 2 | Secondary | U-Boot |idbloader.img| 0x40 | pre-loader
| | Program | TPL/SPL | | |
| | Loader (SPL) | | | |
| | | | | |
| 3 | - | U-Boot | u-boot.itb | 0x4000 | including u-boot and atf
| | | | uboot.img | | only used with miniloader
| | | | | |
| | | ATF/TEE | trust.img | 0x6000 | only used with miniloader
| | | | | |
| 4 | - | kernel | boot.img | 0x8000 |
| | | | | |
| 5 | - | rootfs | rootfs.img | 0x40000 |
+--------+----------------+----------+-------------+---------+
最前面0x40
字节是MBR分区信息。我们所需要关注的是第2、3阶段。第2、3阶段所需要的文件idbloader.img
和u-boot.itb
是由U-Boot编译生成的。因此只需要编译好后按照上图所示的布局排列好,刷入TF卡中即可。
详细配置
编译U-Boot
U-Boot在2023年7月加入的Orange Pi R1 Plus LTS的设备树(见9bd954ab),因此需要使用较新的U-Boot源码,nixpkgs中默认使用的U-Boot源码较旧,所以需要手动指定U-Boot的src。编译配置如下
pkgs.buildUBoot {
defconfig = "orangepi-r1-plus-lts-rk3328_defconfig";
extraMeta = {
platforms = ["aarch64-linux"];
};
src = pkgs.fetchgit {
url = "https://source.denx.de/u-boot/u-boot.git";
rev = "v2024.01-rc6";
sha256 = "sha256-fdgN6gVf2BPFnqvrdcT0WnkaB1r2s5K9gabdn+a4Djo=";
};
makeFlags = [
"CROSS_COMPILE=${pkgs.stdenv.cc.targetPrefix}"
];
version = "v2024.01-rc6";
patches = [];
enableParallelBuilding = true;
BL31 = "${pkgs.armTrustedFirmwareRK3328}/bl31.elf";
filesToInstall = ["u-boot.itb" "idbloader.img"];
}
制作SD卡镜像
SD卡镜像制作主要参考了ryan4yin/nixos-rk3588以及gytis-ivaskevicius/orangepi-r1-plus-nixos-image,只需要把固件按照rock-chips文档中的布局排布即可。由于完整代码过长,下面列出几个关键命令。
# 将创建文件$img,并指定文件大小$imageSizeBytes
truncate -s $imageSizeBytes $img
# 创建主分区
sfdisk $img <<EOF
label: dos
start=$rootPartitionOffsetBlocks, type=linux, bootable
EOF
# 获取$img的第一个分区的起始位置和大小
eval $(partx $img -o START,SECTORS --nr 1 --pairs)
# 将rootfs.img写入第一个分区
dd conv=notrunc if=./root-fs.img of=$img seek=$START count=$SECTORS
# 写入idbloader.img
dd if=idbloader.img of=$img seek=64 conv=notrunc
# 写入u-boot.itb
dd if=u-boot.itb of=$img seek=16384 conv=notrunc
启动
编译好后,使用dd命令将镜像写TF卡中,就可以启动了。