之前看到一位大佬的博客,一下子激起了我为自己树莓派构建系统的兴趣,本文教程基于他的博客进行扩充
本文系统基于Ubuntu Server 20.04.1 LTS
(基于Windows 10的VMWare虚拟机),x64架构
CPU进行交叉构建。
考虑到有些萌新还没有使用过VMWare虚拟机,本文也将教授虚拟机配置过程。
一、前期准备
1 VMWare Workstation Pro 安装以及虚拟机配置
1.1 安装VMWare Workstation
伸手党福利!官方链接点此即可,点击“立即下载”。安装完后输入许可证密钥(如果没钱激活的话可以自行百度,当然不激活影响不大,只要不被判定为商业用途即可)。
1.2 配置虚拟机
- 左上角
文件
-新建虚拟机
- 不要典型!选择
自定义
!! - 两次下一步之后选择
稍后安装操作系统
!不要直接选择映像文件! - 客户机操作系统选择
Linux-Ubuntu
- 名称自定,其他选项根据自身情况配置,下一步即可
1.3 安装系统
- 点击此处下载官方Ubuntu映像,建议使用下载工具(IDM等等)
- 右键虚拟机-编辑虚拟机设置
- 点击
CD/DVD
,勾选启动时连接
,并点击使用ISO映像文件
,选择你刚刚下好的映像 - 关闭窗口,开启虚拟机
PS. 由于我这里已经安装好系统,此处不再演示
2 安装依赖
# 获取root权限,便于后续操作
sudo su
2.1 换源,系统更新
个人习惯使用nano编辑文件,不喜欢也可使用vim等等
mv /etc/apt/sources.list /etc/apt/sources.list.bak
nano /etc/apt/sources.list
这边采用清华大院开源镜像站TUNA的源,文档来自Ubuntu 镜像使用帮助
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-updates main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-backports main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-security main restricted universe multiverse
Ctrl+O
,Ctrl+X
保存并退出。
更新系统
apt update
apt upgrade
2.2 安装应用依赖以及下载文件
一揽子全部安装,省的后面再弄,麻烦。
apt install kpartx build-essential gcc-aarch64-linux-gnu bc bison flex libssl-dev make libc6-dev libncurses5-dev git debootstrap qemu-user-static
下载内核文件准备编译
wget https://cdn.jsdelivr.net/gh/yuzh0816/tools@0.1/firmware.tar.xz
# 此处可能会非常慢,因为文件来自Github
wget -O rpi-firmware.tar.gz https://github.com/Hexxeh/rpi-firmware/tarball/master
二、开始构建
如果想要在工作目录中构建,可以创建文件夹
mkdir debian
cd debian
1 创建镜像
注意,此处设置镜像文件大小为3G,实际情况可以根据自身情况调整
# 创建buster.img空镜像文件
dd if=/dev/zero of=buster.img bs=3G count=0 seek=1
使用cfdisk
命令进行GUI模式镜像分区
cfdisk buster.img
创建两个分区,一个是FAT32的boot
分区,一个是rootfs
分区。

挂载镜像文件并查看挂载的设备名称
losetup -f --show buster.img

此时loop设备在/dev/loop8
下挂载,我们用kpartx把它两个分区挂载到/dev/mapper
下
kpartx -va /dev/loop8

可以看到挂载成功。
这时第一个分区在/dev/mapper/loop8p1
,第二个是在/dev/mapper/loop8p2
下。
现在格式化这两个分区(记得把下面的目录改成上面显示的loop-p-,警告不用管)。
#格式化boot分区
mkfs.fat -F 32 -n "boot" /dev/mapper/loop8p1
#格式化rootfs,设置label
mkfs.ext4 -L rootfs /dev/mapper/loop8p2

然后,在工作目录下新建两个分区的目录,并挂载。
mkdir boot rootfs
mount /dev/mapper/loop8p1 boot/
mount /dev/mapper/loop8p2 rootfs/
此时,空镜像文件已经制作完成,执行lsblk
命令看挂载情况。

第一步完成。
三、RootFS构建
1 初步构建阶段
这里可以选择你想要构建的系统,此处选择为图方便选择Debian。
镜像可以选择的有很多(必须为Debian系统),列举两个清华大学TUNA镜像地址:
经过亲自测试可行的有Debian、UOS和Ubuntu。
# --foreign表示异构系统构建,即在不同CPU架构下进行构建
debootstrap --arch=arm64 --no-merged-usr --foreign buster rootfs/ https://mirrors.tuna.tsinghua.edu.cn/debian/
等待数分钟,执行后rootfs目录结构如下

解压之前下好的压缩包(驱动文件以及固件)
tar -Jxvf firmware.tar.xz -C rootfs/lib/
mkdir rpi-firmware
tar -zxvf rpi-firmware.tar.gz -C rpi-firmware --strip-components 1
cp -r rpi-firmware/vc/hardfp/opt/vc rootfs/opt/
cp -r rpi-firmware/vc/sdk/opt/vc rootfs/opt/
编辑文件系统信息
#此处依然要将loop后的数字进行更改
blkid /dev/mapper/loop8*

复制两串PARTUUID,粘贴到rootfs/etc/fstab
中。
nano rootfs/etc/fstab

然后换源
nano rootfs/etc/apt/sources.list
deb http://mirrors.tuna.tsinghua.edu.cn/debian/ buster main non-free contrib
deb http://mirrors.tuna.tsinghua.edu.cn/debian-security buster/updates main
deb http://mirrors.tuna.tsinghua.edu.cn/debian/ buster-updates main non-free contrib
deb http://mirrors.tuna.tsinghua.edu.cn/debian/ buster-backports main non-free contrib
2 第二构建阶段
开始构建
chroot rootfs/ debootstrap/debootstrap --second-stage
cp /usr/bin/qemu-aarch64-static rootfs/usr/bin/


chroot进入系统根目录
chroot rootfs/ /usr/bin/qemu-aarch64-static /bin/bash

开始进行系统内配置:
1. 更新软件
dpkg --add-architecture armhf
apt update
apt upgrade

2. 安装基本软件以及运行库
apt install libc6:armhf
apt install locales rng-tools wpasupplicant dhcpcd5 sudo parted
apt install net-tools avahi-daemon dphys-swapfile ssh openssh-server
apt install htop bash-completion wget curl vim nano
3. 添加vc-userland支持
echo "/opt/vc/lib/" >/etc/ld.so.conf.d/vc-userland.conf
cd /usr/bin/ ; for i in /opt/vc/bin/* ; do ln -sf $i ./ ; done ; cd /
4. 设置内核参数
echo -e "kernel.printk = 3 4 1 3\nvm.min_free_kbytes = 16384" > /etc/sysctl.d/98-rpi.conf
echo -e "net.core.default_qdisc=fq\nnet.ipv4.tcp_congestion_control=bbr" >> /etc/sysctl.conf
5. 设置时区(中国大陆选择上海)
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
6. 配置wpa_supplicant,并链接到boot目录下的wpa_supplicant.conf
ln -sf /usr/share/dhcpcd/hooks/10-wpa_supplicant /lib/dhcpcd/dhcpcd-hooks/10-wpa_supplicant
ln -sf /boot/wpa_supplicant.conf /etc/wpa_supplicant/wpa_supplicant.conf
7. 配置主机名称(引号内“yuzhpi”内容更改为主机名称,可在局域网内显示、连接)
echo "yuzhpi" > /etc/hostname
echo -e "127.0.0.1\yuzhpi" >> /etc/hosts
8. 重新设置软件包区域、语言(经本人尝试,Ubuntu似乎不可行 || 英语好的可以跳过,这步其实没啥必要)
dpkg-reconfigure locales
用空格键
选择en_US.UTF-8
和zh_CN.UTF-8
。Tab
键选择Ok
。


选择zh_CN.UTF-8
,Tab
选定。

9. 添加用户(最好为pi)
useradd -m -s /bin/bash pi
passwd pi #输入密码x2
echo "pi ALL=(ALL:ALL) NOPASSWD: ALL" > /etc/sudoers.d/00_pi
10. 安装常用软件
此处自便,根据需求安装即可。
退出chroot。
sync
exit
echo > rootfs/root/.bash_history #清除bash记录
sync
四、Boot分区(启动分区)配置
基本启动配置
复制Bootloader启动驱动文件
cp rpi-firmware/bootcode.bin rpi-firmware/fixup* rpi-firmware/start* boot/
然后同上文blikd
命令,执行下面那句命令,将8改为最早弄的那个数字,保存PARTUUID
(其实前面已经执行过了,就是之前让你们保存的那串PARTUUID)
blkid /dev/mapper/loop8p2
编辑cmdline.txt
:
nano boot/cmdline.txt
粘贴,把UUID覆盖此处UUID。
dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=PARTUUID=ca013eb7-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait
编辑config.txt
:
nano boot/config.txt
文件内容如下
arm_64bit=1
dtparam=audio=on
[pi4]
dtoverlay=vc4-fkms-v3d
max_framebuffers=2
[all]
无线网络配置
touch boot/wpa_supplicant.conf
如无需配置无线,仅需执行上面那行命令即可。
nano boot/wpa_supplicant.conf
替换提示文本为网络配置。
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
country=CN
network={
ssid="wifi名称"
psk="wifi密码"
key_mgmt=WPA-PSK
priority=1
}
四、内核构建
Git Clone官方内核
git clone --depth=1 https://github.com.cnpmjs.org/raspberrypi/linux

可以通过修改linux/Makefile
第五行EXTRAVERSION
自定义版本号
e.g: EXTRAVERSION = -yuzh
,则显示[版本号]-yuzh

开始编译
这步需要好久。好久。好久。。
cd linux
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- bcm2711_defconfig
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-#可以添加' -j2'实现多核编译,jn即为n核编译
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- INSTALL_MOD_PATH=../rootfs modules_install

编译期间分配的CPU负载跑满

复制编译好的文件到Boot分区。
cp arch/arm64/boot/Image ../boot/kernel8.img
cp arch/arm64/boot/dts/broadcom/*.dtb ../boot/
cp -r arch/arm64/boot/dts/overlays/ ../boot/
五、大功告成
同步并卸载镜像。
cd ../
sync
umount boot/
umount rootfs/
取消挂载(你也可以选择关闭虚拟机),依然需要更改数字。
kpartx -d /dev/loop8
losetup -d /dev/loop8
把镜像从虚拟机复制出来,即可刷入板子。目前兼容3B
、3B+
、4B
。
六、总结
踩过的坑:
- 有许多软件不兼容chroot内部进行,需要在板子上实操才行。
- 本以为编译速度很快,没想到速度这么慢。。
- 构建镜像中途不小心退出,且没有sync,需全部重头来过
快捷工具:
- Github Zip下载器,曲线救国