Debian Port已经可以提供risc-v体系结构的软件包集合[https://wiki.debian.org/RISC-V]。
以下记录基于qemu模拟risc-v平台环境并运行debian的过程。
宿主机环境
宿主机ubuntu18.04.1 LTS(x86_64),安装自带gcc编译器和riscv64交叉编译器。
apt install gcc-riscv64-linux-gnu gcc binutils
qemu
从官网下载并编译riscv64模拟器
git clone https://git.qemu.org/git/qemu.git --depth 1
./configure --target-list=riscv64-softmmu
make
编译后生成模拟器riscv64-softmmu/qemu-system-riscv64。
qemu包含一个称为virt的虚拟平台,通过参数-machine virt(或-M virt)指定使用该类型board以模拟riscv64平台。
注:不必执行make install安装,后面直接在qemu源码根目录下运行,以便于跟踪调试qemu代码。
risc-v opensbi
开源项目opensbi实现符合RISC-V SBI规范的固件firmware,以该firmware(64位)作为引导的第一级。
git clone https://github.com/riscv/opensbi.git --depth 1
make PLATFORM=generic CROSS_COMPILE=riscv64-linux-gnu- PLATFORM_RISCV_XLEN=64
用opensbi自带的测试payload验证qemu和opensbi有效性。
在qemu源码根目录下执行测试脚本:
./riscv64-softmmu/qemu-system-riscv64 -M virt -m 256M -nographic \
-kernel /root/gitQemu/opensbi/build/platform/generic/firmware/fw_jump.elf \
-device loader,file=/root/gitQemu/opensbi/build/platform/generic/firmware/payloads/test.bin,addr=0x80200000
结果显示OpenSBI的启动画面,最后一行是测试payload(test.bin)的显示信息”Test payload running”。
u-boot
编译u-boot,作为引导的第二级。
注意:为了让u-boot运行在supervisor mode,选择配置qemu-riscv64_smode_defconfig
git clone https://gitlab.denx.de/u-boot/u-boot.git --depth 1
make qemu-riscv64_smode_defconfig CROSS_COMPILE=riscv64-linux-gnu-
make CROSS_COMPILE=riscv64-linux-gnu-
生成u-boot.bin。现在再次执行如下测试,验证u-boot是否可以被正常启动。
./riscv64-softmmu/qemu-system-riscv64 -machine virt -m 256M -nographic \
-kernel /root/gitQemu/opensbi/build/platform/generic/firmware/fw_jump.elf \
-device loader,file=/root/gitQemu/u-boot/u-boot.bin,addr=0x80200000 &
相对于OpenSBI自带的测试,只是更改了-device loader,file=指定的路径。
执行成功将会显示u-boot的启动信息,同时由于没有指定根文件系统,最后会报告找不到启动设备或网络。
debian
从[https://people.debian.org/~gio/dqib/]找到Images for riscv64-virt,下载debian预编译的镜像。
解开压缩包,包括三个文件image.qcow2,initrd和kernel:
其中image.qcow2是完整的debian根文件系统镜像,initrd和kernel是镜像中临时启动盘和内核的拷贝。
通过guestmount挂载该镜像并查看其内容。需要安装libguestfs-tools。
apt install libguestfs-tools
通过guestmount挂载该镜像到/mnt目录,可以查看或修改根文件系统内容,然后用guestunmount解除挂载。
guestmount -a image.qcow2 -m /dev/sda1 /mnt/
ls /mnt
guestunmount /mnt
导出FDT
下步启动内核时需要FDT,从qemu导出。
执行如下脚本:
./riscv64-softmmu/qemu-system-riscv64 -nographic -machine virt,dumpdtb=qemu-virt.dtb -m 1G \
-kernel /root/gitQemu/opensbi/build/platform/generic/firmware/fw_jump.elf \
-device loader,file=/root/gitQemu/u-boot/u-boot.bin,addr=0x80200000 \
-object rng-random,filename=/dev/urandom,id=rng0 -device virtio-rng-device,rng=rng0 \
-append "console=ttyS0 rw root=/dev/vda1" \
-device virtio-blk-device,drive=hd0 -drive file=/root/gitQemu/images/image.qcow2,format=qcow2,id=hd0 \
-device virtio-net-device,netdev=brnet0,mac=00:16:3e:09:3d:58 -netdev tap,id=brnet0,vhost=on,vnet_hdr=on &
其中起作用的是-machine virt,dumpdtb=qemu-virt.dtb
这样就可以得到qemu自定义的board类型virt的二进制fdt文件qemu-virt.dtb。
构造FIT Image
用u-boot的命令行工具mkimage构造FIT Image并替换debian镜像中的原内核文件vmlinux。
1. 编辑kernel_fdt.its
从u-boot/doc/uImage.FIT/kernel_fdt.its拷贝一份进行修改。
修改内容包括kernel的路径、压缩格式加载地址和入口地址,以及dtb的路径。
修改后内容:
/*
* Simple U-Boot uImage source file containing a single kernel and FDT blob
*/
/dts-v1/;
/ {
description = "Simple image with single Linux kernel and FDT blob";
#address-cells = ;
images {
kernel {
description = "Linux kernel";
data = /incbin/("./kernel");
type = "kernel";
arch = "riscv";
os = "linux";
compression = "none";
load = ;
entry = ;
hash-1 {
algo = "crc32";
};
hash-2 {
algo = "sha1";
};
};
fdt-1 {
description = "Flattened Device Tree blob";
data = /incbin/("./qemu-virt.dtb");
type = "flat_dt";
arch = "riscv";
compression = "none";
hash-1 {
algo = "crc32";
};
hash-2 {
algo = "sha1";
};
};
};
configurations {
default = "conf-1";
conf-1 {
description = "Boot Linux kernel with FDT blob";
kernel = "kernel";
fdt = "fdt-1";
};
};
};
注意:文件中”./kernel”是从前述debian压缩包中解压得到的kernel文件路径,”./qemu-virt.dtb”是上一步得到的FDT。另外,load和entry也是关键,分别指定了内核加载地址和执行入口地址,这里都是0x81a00000。
执行如下脚本制作FIT Image并替换镜像中的vmlinux:
guestmount -a image.qcow2 -m /dev/sda1 /mnt/
# make sure that the vmlinux and qemu-virt.dtb are all in local directory
../u-boot/tools/mkimage -f ./kernel_fdt.its ./vmlinux-5.5.0-1-riscv64
# override old vmlinux-5.5.0-1-riscv64 in 'image.qcow2'
cp ./vmlinux-5.5.0-1-riscv64 /mnt/boot/vmlinux-5.5.0-1-riscv64
guestunmount /mnt
正式启动debian linux
执行如下脚本,启动qemu模拟riscv64平台,运行debian:
./riscv64-softmmu/qemu-system-riscv64 -nographic -machine virt -m 1G \
-kernel /root/gitQemu/opensbi/build/platform/generic/firmware/fw_jump.elf \
-device loader,file=/root/gitQemu/u-boot/u-boot.bin,addr=0x80200000 \
-object rng-random,filename=/dev/urandom,id=rng0 -device virtio-rng-device,rng=rng0 \
-append "console=ttyS0 rw root=/dev/vda1" \
-device virtio-blk-device,drive=hd0 -drive file=/root/gitQemu/images/image.qcow2,format=qcow2,id=hd0 \
-device virtio-net-device,netdev=net0,mac=52:54:00:12:34:58 -netdev user,id=net0
与上次执行命令行的区别仅仅是”-machine virt”后面没有指定dumpdtb。
Debian启动之后,用root登录,口令为root。
由于网络类型为user mode,ICMP被禁止,所以无法用ping命令。
直接执行apt测试网络:
apt update
注意:默认的sources.list使用域名deb.debian.org,如果不通,可以更换为镜像ftp.de.debian.org或ftp.kr.debian.org。