为R4S软路由安装系统,测试了一下不同的发行版的根文件系统,尝试了一下内核编译和引导
R4S系统安装小记录
准备编译环境
安装交叉编译工具链,对应archlinux安装以下包即可
1
2
3
4
5
aarch64-linux-gnu-binutils
aarch64-linux-gnu-gcc
aarch64-linux-gnu-gdb
aarch64-linux-gnu-glibc
aarch64-linux-gnu-linux-api-headers
准备tf卡
准备空sd卡,插入电脑,将tf卡格式化,sdX为tf卡根盘符
1
dd if=/dev/zero of=/dev/sdX bs=1M count=32
使用fdisk创建分区
1
2
3
4
5
6
7
8
9
10
fdisk /dev/sdX
# 依次输入以下命令
o #创建新的msdos格式分区
n #创建新分区
p #p选择主分区
1 #分区第一个分区
32768 #配置分区偏移,分区的首个(块)扇区设置为32768
#这里配置分区结尾,或者直接回车默认最大值
w #保存分区表
格式化分区,此处由于采用单系统盘,不再另建boot分区, 格式化时务必选择uboot及kernel均支持的文件系统,如ext4,btrfs等
1
mkfs.btrfs -f -L "rootfs" /dev/sdX1
至此tf卡准备完成
uboot制作
编译ATF(Arm trust firmware)
ATF 主要负责在启动 U-Boot 之前把 CPU 从安全的 EL3 切换到 EL2,然后跳转到 U-Boot,并且在内核启动后负责启动其他的 CPU 下载arm-trusted-firmware
1
git clone https://github.com/ARM-software/arm-trusted-firmware.git
编译
1
make CROSS_COMPILE=aarch64-linux-gnu- PLAT=rk3399
注:如果遇到 ‘.pmusram’ will not fit in region ‘PMUSRAM’ 相关错误,请更换使用其他版本工具链编译编译,此问题可能与工具链版本有关
编译uboot
下载uboot
1
git clone https://gitlab.denx.de/u-boot/u-boot.git
将编译好的ATF文件拷贝至uboot根目录
1
cp arm-trusted-firmware/build/rk3399/release/bl31/bl31.elf u-boot/
编译uboot
1
2
3
4
5
6
7
8
# 默认配置
make ARCH=arm CROSS_COMPILE=aarch64-linux-gnu- CFLAGS="-O2 -pipe -march=armv8-a -mfloat-abi=hard" nanopi-r4s-rk3399_defconfig
# 手动配置,此处记得打开对应的文件系统支持,以支持文件读写,务必打开启动脚步所在分区的文件系统
make ARCH=arm CROSS_COMPILE=aarch64-linux-gnu- CFLAGS="-O2 -pipe -march=armv8-a -mfloat-abi=hard" menuconfig
# 编译
export BL31=bl31.elf && make ARCH=arm CROSS_COMPILE=aarch64-linux-gnu- CFLAGS="-O2 -pipe -march=armv8-a -mfloat-abi=hard"
注:可能提示dtc等命令找不到的问题,需要安装dtc等依赖包,各个系统预装不同,此处无法一一列出
烧录
将编译好的idbloader.img,u-boot.itb文件烧录至sd卡 注意:将idbloader.img的偏移配置为64,将u-boot.itb的偏移配置为16384
1
2
3
cd 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
至此,uboot烧录完成,可以将tf卡插入设备,连接调试串口(波特率为1500000),尝试启动 正常情况下,可以在串口看到uboot启动信息:
1
2
3
4
5
6
SoC: Rockchip rk3399
Reset cause: POR
Model: FriendlyElec NanoPi R4S
DRAM: 3.9 GiB
PMIC: RK808
Core: 259 devices22 uclassesdevicetree: separate
并可以通过串口输入,执行uboot内置的指令
kernel制作
内核编译
官网下载linux kernel源码,使用以下命令编译安装
1
2
3
4
5
6
7
8
9
10
# 默认配置
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- CFLAGS="-O2 -pipe -march=armv8-a -mfloat-abi=hard" -j64 defconfig
# 手动配置,注意开启相关文件系统支持,以支持前面格式化时使用的文件系统,
# 如果启动后提示文件系统不支持,则需要将文件系统直接编译进内核,而不是编译为模块
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- CFLAGS="-O2 -pipe -march=armv8-a -mfloat-abi=hard" -j64 menuconfig
# kernel编译
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- CFLAGS="-O2 -pipe -march=armv8-a -mfloat-abi=hard" -j64
内核安装
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 分区挂载
mount /dev/sdX /mnt
# 安装kernel
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- CFLAGS="-O2 -pipe -march=armv8-a -mfloat-abi=hard" -j64 INSTALL_PATH="/mnt/boot/" install
# 安装dtb,注意要安装到boot下的dtb目录而不是dtbs目录,uboot默认读取位置为dtb,否则需要修改uboot变量以支持其他目录
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- CFLAGS="-O2 -pipe -march=armv8-a -mfloat-abi=hard" -j64 INSTALL_DTBS_PATH="/mnt/boot/dtbs" dtbs_install
# 安装modules
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- CFLAGS="-O2 -pipe -march=armv8-a -mfloat-abi=hard" -j64 INSTALL_MOD_PATH="/mnt" modules_install
# 输入sync指令,确保数据均从缓存已写入磁盘
sync
创建boot.scr引导文件
创建boot.cmd文件,将以下内容写入文件,注意将/boot/dtbs改为我们的安装目录/boot/dtb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# MAC address (use spaces instead of colons)
setenv macaddr da 19 c8 7a 6d f4
part uuid ${devtype} ${devnum}:${bootpart} uuid
setenv bootargs console=ttyS2,1500000 root=PARTUUID=${uuid} rw rootwait earlycon=uart8250,mmio32,0xff1a0000
setenv fdtfile rockchip/rk3399-nanopi-r4s.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
fdt set /ethernet@fe300000 local-mac-address "[${macaddr}]"
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
编译boot.scr
需要安装mkimage工具,archlinux下为uboot-tools
1
mkimage -A arm64 -O linux -T script -C none -a 0 -e 0 -n "R4S boot script" -d boot.cmd /mnt/boot/boot.scr
查看是否在tf卡的boot目录下生成了boot.scr文件
1
2
3
4
5
6
7
ls /mnt
# 使用sync写入磁盘
sync
# 磁盘卸载
umount /dev/sdX1
至此,kernel安装完成,可以将tf卡插入设备,连接调试串口(波特率为1500000),尝试启动
正常情况下,可以在串口看到uboot启动信息,并看到boot.src载入信息:Found U-Boot script /boot/boot.scr
以及 内核启动信息:[ 0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd034]
制作根文件系统
目前,设备已可以进入uboot,并启动内核,但还缺少可用的系统环境,根文件系统可以使用各个linux开发版提供的aarch64系统,或使用开发工具自己制作, 如基于busybox的根文件系统,或使用yocto项目来制作,或使用发行版提供的工具如crossdev等来制作,或参考lfs自行交叉编译
基于archlinuxarm的根文件系统
archlinuxarm提供了aarch64的根文件系统,直接下载,并解压至tf卡即可,注意内核文件可能会被覆盖,解压根文件系统后,需要重新执行内核安装步骤
1
2
3
4
wget http://os.archlinuxarm.org/os/ArchLinuxARM-aarch64-latest.tar.gz
bsdtar -xpf ArchLinuxARM-aarch64-latest.tar.gz -C /mnt
# 重新安装内核
完成安装后即可启动archlinux系统了,默认用户alarm,密码alarm,root用户root,密码root
记得首次启动后初始化一下pacman的密钥链
1
2
pacman-key --init
pacman-key --populate archlinuxarm
基于void-linux的根文件系统
void-linux也为aarch64提供了基础的rootfs根文件系统,可以使用此包
1
2
3
wget https://alpha.de.repo.voidlinux.org/live/current/void-aarch64-ROOTFS-20210930.tar.xz
# 为防止内核文件覆盖,系统解压后建议重新执行内核安装步骤
安装qemu虚拟环境以支持chroot进行后续配置,可能需要的包如下:
1
2
3
qemu-user-static
binfmt-qemu-static
qemu-arch-extra
将可能用到的命令复制到rootfs环境
1
2
cp /usr/bin/qemu-arm-static /mnt/usr/bin/
cp /usr/bin/qemu-aarch64-static usr/bin/
重启binfmt
1
systemctl restart systemd-binfmt.service
使用chroot或systemd-nspawn进入虚拟环境
1
systemd-nspawn -D /mnt
根据void指导手册安装需要的包,并进行必要的系统配置 可以参考installation guides
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 安装基础系统
xbps-install -Su xbps
xbps-install -u
xbps-install base-system
xbps-remove base-voidstrap
# 安装配置
# 配置主机名
vi /etc/hostname
# 配置启动设置
vi /etc/rc.conf
# 配置locales
vi /etc/default/libc-locales
# 运行以下命令更新locales
xbps-reconfigure -f glibc-locales
# 配置root密码
passwd root
# 配置fstab
vi /etc/fstab
# 刷新包配置
xbps-reconfigure -fa
# 退出chroot环境,使用ctrl+]]],按三次]键
至此系统基础配置完成,可以将tf卡插入设备,尝试启动系统,但是无法串口登陆,后续有时间再研究吧 可以参考此文档说明添加串口登陆配置 启用相关服务
基于Alpine Linux的根文件系统
下载文件 GENERIC ARM MINI ROOT FILESYSTEM
为防止内核文件覆盖,系统解压后建议重新执行内核安装步骤
使用同样的步骤进入chroot环境配置
安装qemu虚拟环境以支持chroot进行后续配置,可能需要的包如下:
1
2
3
qemu-user-static
binfmt-qemu-static
qemu-arch-extra
将可能用到的命令复制到rootfs环境
1
2
cp /usr/bin/qemu-arm-static /mnt/usr/bin/
cp /usr/bin/qemu-aarch64-static usr/bin/
重启binfmt
1
systemctl restart systemd-binfmt.service
使用chroot或systemd-nspawn进入虚拟环境
1
systemd-nspawn -D /mnt
基础系统配置
修改国内源
1
vi /etc/apk/repositories
将地址改为阿里云镜像:
1
2
https://mirrors.aliyun.com/alpine/v3.15/main
https://mirrors.aliyun.com/alpine/v3.15/community
软件包更新
1
2
apk update
apk upgrade
安装基础启动包alpine-base,这个包中包含了openrc,alpine-conf,busybox-initscripts等启动及配置用软件
1
2
apk add alpine-base
配置root密码
1
passwd root
为设备增加串行控制台: 参考官方wiki在启动时启用串行控制台
1
2
3
4
5
6
7
# 在boot启动参数中增加console=选项
# 此参数已在boot.scr中添加
# 在系统中添加串口参数
vi /etc/inittab
# 添加以下内容,或打开注释修改对应行
ttyS2::respawn:/sbin/getty -L ttyS2 1500000 vt100
由于alpine默认禁止root用户登陆调试串口,此时可以修改配置,或新增一个普通用户 新增普通用户的步骤可以参考官方wikiSetting up a new user
后续步骤可以迁移至tf卡启动后再配置,配置方式可以参考Post installation
退出chroot环境,使用ctrl+]]],按三次]键
基于Fedora的根文件系统
下载fedora aarch64 minimal根文件系统包 Fedora-Minimal-35-1.2.aarch64.raw.xz
内核配置,fedora默认开启zram,需要打开内核ZRAM配置,否则会提示找不到/dev/zram0设备 可能需要开启ZSMALLOC后才能选择ZRAM选项,然后重新安装内核
修改etc/fstab为安装设备的真实目录
1
vi etc/fstab
强制卸载软件包
1
rpm -e 本机已经安装的冲突版本包名 --nodeps