RV64 板子更换 rootfs 指南
XieJiSS, revision 3
本文可能不会及时更新,请以RV64 板子更换 rootfs 指南 - archriscv-packages Wiki为准
0x00 警告
请确保你或你的同伴可以在物理上(通过串口)访问到板子。否则,你的板子将在 0x02 的第 6 步重新启动时失联。
0x01 准备工作
首先,以 root 身份回到根目录:
1
2sudo su
cd /下载 rootfs tarball(确保安装了
wget
):1
2
3
4mkdir new && cd new
wget curl -O https://archriscv.felixc.at/images/archriscv-20220727.tar.zst
tar -xf archriscv-20220727.tar.zst
cd ..在根目录创建
old
文件夹:1
mkdir old
看一下
fstab
:1
cat /etc/fstab
最好拍照或截图备查。
获取当前的 Linux 内核版本:
首先,初始化用于从
vmlinuz
提取内核版本的脚本。vmlinuz
一般位于/boot
目录下,需要 root 权限才能访问。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17kver_generic() {
# For unknown architectures, we can try to grep the uncompressed or gzipped
# image for the boot banner.
# This should work at least for ARM when run on /boot/Image, or RISC-V on
# gzipped /boot/vmlinuz-linuz. On other architectures it may be worth trying
# rather than bailing, and inform the user if none was found.
# Loosely grep for `linux_banner`:
# https://elixir.bootlin.com/linux/v5.7.2/source/init/version.c#L46
local kver= reader=cat
[[ $(file -b --mime-type "$1") == 'application/gzip' ]] && reader=zcat
read _ _ kver _ < <($reader "$1" | grep -m1 -aoE 'Linux version .(\.[-[:alnum:]]+)+')
printf '%s' "$kver"
}执行
kver_generic /boot/vmlinuz
,记住 Linux 内核版本。可以将其赋值给一个临时的 shell 变量,也可以继续拍照记录:1
linux_kver=$(kver_generic /boot/vmlinuz)
注意,如果你当前的系统没有开启内核压缩,那么可能需要将
vmlinuz
修改为vmlinux
。看一下
ip addr
和 router 的地址:1
2
3这里 eth0 可能需要按实际情况修改,ip addr show 可以查看全部 device
一般 ip addr show 的第二个 device 就是我们需要的 device(第一个是 lo 本地回环)
ip addr show dev eth0记录
inet
行的 IP,这是你本机当前的 IP 地址。之后会用到,建议拍照或截图留存。(包括 IP 后面的/24
,如果显示的不是/24
那么之后步骤中也要对应修改成此时显示的后缀)其实理论上这步不需要的,用 dhcp 即可。但似乎 PLCT 南京内网的端口转发本质上基于静态 IP,依赖了 dhcp 客户端重启后服务端优先发放此前释放的 IP 的特征,并不稳定。建议还是在 0x02 的第七步里配成静态 IP。
1
ip route show dev eth0
记录
default via
后面的 IP 地址,这个就是你的板子所在局域网的 router 的地址。建议拍照或截图留存。如果目标板子不在 PLCT 南京内网,并且你并不理解上述命令的用途:建议在此停下,先和 mentor 讨论清楚网络拓扑再继续。
0x02 开始更换 rootfs
记录几个关键路径(不用真的记,反正这里有):
1
2/new/lib/ # 后面步骤中会设置为 LD_LIBRARY_PATH
/new/lib/ld-linux-riscv64-lp64d.so.1在新的 rootfs 并非 Arch Linux 时,可能需要将
/lib
替换为/usr/lib
。原因详见:The /lib directory becomes a symlink - Arch Linux News移动文件夹
1
2mv etc home media mnt opt root srv var old/ # 这里保留 /boot
mv new/etc new/home new/mnt new/opt new/root new/srv new/var ./继续移动文件夹
1
2
3
4LD_LIBRARY_PATH=/new/lib/ /new/lib/ld-linux-riscv64-lp64d.so.1 /new/bin/mv bin sbin usr lib old/
LD_LIBRARY_PATH=/new/lib/ /new/lib/ld-linux-riscv64-lp64d.so.1 /new/bin/mv new/bin new/sbin new/usr new/lib ./
mv old/lib/firmware ./lib//lib/firmware
是 Ubuntu on Unmatched 的 firmware 路径,可能需要按实际情况修改。把 kernel modules 移动回来
1
mv old/usr/lib/modules/$linux_kver ./lib/modules/
这里的
$linux_kver
是前面「获取当前的 Linux 内核版本」步骤中设置的。dtbs、vmlinuz 等均位于
/boot
下,此前并未覆盖/boot
因此在这一步不用操心它们。备注:一般来讲,新 rootfs 的 tar 文件里面并不会包含 dtbs 和 vmlinuz 等文件,它们一般会出现在.img
或.iso
内,这超出了 rootfs 的范畴,故本文不做详细解释。修改
fstab
1
2echo "LABEL=cloudimg-rootfs / ext4 discard,errors=remount-ro 0 1" >> /etc/fstab
echo "LABEL=timesyncd-clock /var/lib/systemd/timesync/ tmpfs size=1K,rw,nodev,nosuid,noexec,noatime 0 1" >> /etc/fstab注意这里可能需要根据之前看的
fstab
内容来酌情修改第一行,例如原本是vfat
的盘你肯定不会希望它被设置成按照ext4
格式读取。第二行的 tmpfs 是因为我们稍后要启用
systemd-timesyncd
,但是不希望它太过影响硬盘寿命。如果你不在乎,可以丢掉这行。重启机器。
重启后已经是 Arch Linux 了。开始配网络和
fstab
:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20echo test > test.txt # 测试 / 是否被 mount 为 rw
mount -o remount,rw / # 如果上一行报错,则执行这一行,然后停下并联系你的 mentor
rm test.txt
ip addr add 之前记录下的内网IPv4地址/24 dev eth0
ip link set eth0 up
ip route add default via 之前记录下的router地址 dev eth0
114.114.114.114 是国内常用的 dns 递归服务器
echo 'nameserver 114.114.114.114' > /etc/resolv.conf
systemctl start systemd-timesyncd
pacman -Syu --noconfirm
pacman -Syy vim openssh dhcpcd
systemctl start sshd.service
systemctl enable sshd.service
touch .ssh/authorized_keys # 受信任的 ssh 公钥,可以使用 vim 编辑
vim /etc/dhcpcd.conf # 配置样例如下。这里受限于南京内网拓扑,提供的是静态 IP 的配置方案1
2
3
4
5
6# /etc/dhcpcd.conf
interface eth0
static ip_address=之前记录下的内网IPv4地址/24
static routers=之前记录下的router地址
static domain_name_servers=114.114.114.114更新 pacman 软件源,随后再次重启。
1
2pacman -Syu --noconfirm
reboot -f,对于 Unmatched 板子可能还需要按 reset 按钮跑完 Syu 如果不重启,可能会遇到很多「升级升了一半」导致的问题,例如找不到 kernel module、找不到各种符号等等。