摘要 这篇博客讲述了作者在Orangepi R1 Plus LTS上安装Arch Linux的过程。尽管该板卡原本计划用于软路由,但由于缺少Wi-Fi蓝牙模块,作者放弃了软路由方案,转而尝试安装Arch Linux。作者详细描述了U-Boot配置、ARM Trusted Firmware编译以及U-Boot和设备树的编译和安装过程。最终,作者成功在Orangepi R1 Plus LTS上安装并启动了Arch Linux系统。作者还提到了官方推荐的Debian脚本编译U-Boot的方法,但由于使用Arch Linux,未进一步测试。

前情提要

最近突然想起来手头有一个之前白嫖的Orangepi R1 Plus LTS(后称R1+LTS)已经吃灰好久。本来打算弄软路由,但是这个板子本身并不内置Wi-Fi蓝牙模块导致如果想变成路由器我得再买一个USB网卡,否则就只能当旁路由。这么看性价比其实并不是很高,想了想软路由不是刚需就没折腾了。

既然不用来装Openwrt,总觉得应该装点什么东西。然而目前这个开发板被官方或者非官方支持发行版却只有寥寥无几(Ubuntu,Debian,Openwrt,Android和Armbian)。不过也正常,这个板子除了当软路由之外毫无性价比可言,能有这么多发行版我觉得已经超出我的想象了。不过思来想去还是想装个Arch Linux玩玩。

Arch Linux Arm (后称Alarm)官方并没有支持特别多的开发板(反而隔壁Manjaro Arm支持的更好),但好像大部分芯片至少都能找到一个对应的开发板被支持。R1+LTS的芯片是Rockchip 3328,Alarm对这个芯片仅支持了Rock64开发板。看了一下官方安装说明,使用的是Generic镜像配合上Rock64的U-Boot的安装方式。这看起来很有戏,技术思路就是重新编译一下R1+LTS的U-Boot固件,然后仿照官方说明安装即可。同时还惊喜的发现在两周前官方新增了对R1+LTS的支持

安装过程

这里快速的过一下正确安装过程,踩的雷放在下一章讲。

不想手动编译的可以直接移动到安装Arch Linux,本文提供以编译好的文件。

配置 U-Boot

以下内容可配合U-Boot官方文档阅读。

  1. 找到一个可以编译U-Boot的环境,我这里选用的是一个装有Arch Linux的amd64设备。
  2. 从官网获取U-Boot
  3. 安装交叉编译依赖,文档中并没给Arch系的依赖,所以我只装了 gcc-aarch64-linux-开头的几个必要的编译工具,剩下的等 make的时候报错再递归的安装。
  4. 找到需要的开发板的配置文件,对于R1+LTS而言,配置文件在 configs/orangepi-r1-plus-lts-rk3328_defconfig。运行配置:
make orangepi-r1-plus-lts-rk3328_defconfig

此处先不进行U-Boot的编译,编译了会报错:

Image 'simple-bin' is missing external blobs and is non-functional: atf-bl31

/binman/simple-bin/fit/images/@atf-SEQ/atf-bl31 (bl31.elf):
   See the documentation for your board. You may need to build ARM Trusted
   Firmware and build with BL31=/path/to/bl31.bin

表示需要ARM Trusted Firmware,所以还需要去编译一个ATF。

编译 ARM Trusted Firmware

以下内容可配合ATF官方文档阅读。

  1. 使用与上节一样的编译环境。
  2. 获取ATF仓库,这里我直接去GitHub镜像下载了。
  3. 在路径 docs/plat/rockchip.rst中找到了型号和教程。我这里运行的编译命令如下:
make CROSS_COMPILE=aarch64-linux-gnu- PLAT=rk3328
  1. 编译完之后路径 build/rk3328/release/bl31/bl31.elf下可以找到所需要的文件。复制到U-Boot的目录下:
cp build/rk3328/release/bl31/bl31.elf ../u-boot/

编译 U-Boot

回到 u-boot目录。

  1. 按照错误提示进行编译
CROSS_COMPILE=aarch64-linux-gnu- BL31=bl31.elf make
  1. 编译后当前目录下有两个文件是我们需要的:idbloader.imgu-boot.itb。同时我们还需要找到一个文件,后面会用 arch/arm/dts/rk3328-orangepi-r1-plus-lts.dtb,这是R1+LTS的设备树。

安装 Arch Linux

刚刚我们获取了三个文件idbloader.imgu-boot.itbrk3328-orangepi-r1-plus-lts.dtb。下文还将生成一个boot.scr,点击链接可以直接下载编译好的文件。

请同步参照Alarm官方文档。 这里只讲差异点。

  1. 这里需要一个U-Boot的boot.scr脚本,对于Rock64有现成的,这里我们需要自制一个。
touch boot.cmd # 创建boot.cmd文件
vim boot.cmd # 写入boot.cmd文件,具体内容在下方
mkimage -A arm64 -O linux -T script -C none -a 0 -e 0 -d boot.cmd boot.scr # 创建U-Boot引导脚本的二进制文件
cp boot.scr root/boot/ # 放入boot文件夹内

下面是 boot.cmd的内容

part uuid ${devtype} ${devnum}:${bootpart} uuid
setenv bootargs console=${console} root=PARTUUID=${uuid} rw rootwait
setenv fdtfile rockchip/rk3328-orangepi-r1-plus-lts.dtb

if load ${devtype} ${devnum}:${bootpart} ${kernel_addr_r} /boot/Image; then
	if load ${devtype} ${devnum}:${bootpart} ${fdt_addr_r} /boot/dtbs/${fdtfile}; then
		fdt addr ${fdt_addr_r}
		fdt resize
		if load ${devtype} ${devnum}:${bootpart} ${ramdisk_addr_r} /boot/initramfs-linux.img; then
			booti ${kernel_addr_r} ${ramdisk_addr_r}:${filesize} ${fdt_addr_r};
		else
			booti ${kernel_addr_r} - ${fdt_addr_r};
		fi;
	fi;
fi
  1. umount之前,我们需要将之前的存的设备树放于 root/boot/dtbs/rk3328-orangepi-r1-plus-lts.dtb,因为Arch所提供的镜像中并没有R1+LTS的设备树。然后再Unmount:
umount root
  1. 这里使用我们之前编译好的两个文件 idbloader.imgu-boot.itb。假设都已经放入 u-boot目录下。
dd if=idbloader.img of=/dev/sdX seek=64 conv=notrunc
dd if=u-boot.itb of=/dev/sdX seek=16384 conv=notrunc

[P.S.]最后不需要进行 Install the U-Boot package操作,因为官方源并没有提供R1+LTS的U-Boot包,贸然删了 boot.scr可能就启动不了了。

Arch 启动!

                   -`                    leachim@alarm
                  .o+`                   -------------
                 `ooo/                   OS: Arch Linux ARM aarch64
                `+oooo:                  Host: Xunlong Orange Pi R1 Plus LTS
               `+oooooo:                 Kernel: 6.2.1-1-aarch64-ARCH
               -+oooooo+:                Uptime: 2 hours, 14 mins
             `/:-:++oooo+:               Packages: 156 (pacman)
            `/++++/+++++++:              Shell: bash 5.1.16
           `/++++++++++++++:             Terminal: /dev/pts/0
          `/+++ooooooooooooo/`           CPU: (4) @ 1.296GHz
         ./ooosssso++osssssso+`          Memory: 75MiB / 967MiB
        .oossssso-````/ossssss+`
       -osssssso.      :ssssssso.
      :osssssss/        osssso+++.
     /ossssssss/        +ssssooo/-
   `/ossssso+/:-        -:/+osssso+-
  `+sso+:-`                 `.-/+oso:
 `++:.                           `-/+/
 .`                                 `/

写在最后

其实Orangepi是提供了R1+LTS的U-Boot适配代码的。在Branch v2020.10-rockchip64里提供了R1+LTS的配置。但不知道为啥我编译不出来:

drivers/ram/rockchip/sdram_rk3328.c: In function 'rk3328_dmc_init':
drivers/ram/rockchip/sdram_rk3328.c:526:55: error: 'struct dtd_rockchip_rk3328_dmc' has no member named 'rockchip_sdram_params'
  526 |                                         (void *)dtplat->rockchip_sdram_params;
      |                                                       ^~
make[4]: *** [scripts/Makefile.build:265: tpl/drivers/ram/rockchip/sdram_rk3328.o] Error 1
make[3]: *** [scripts/Makefile.build:419: tpl/drivers/ram/rockchip] Error 2
make[2]: *** [scripts/Makefile.build:419: tpl/drivers/ram] Error 2

官方其实推荐的是在Debian系下使用官方脚本来编译U-Boot,奈何手头上是Arch Linux就没有进行进一步测试了。