制作一个简洁的树莓派系统 - 母鸡下蛋篇(本地编译篇)

发布时间 2023-09-22 01:15:54作者: XYZ59C

“在一个有系统的树莓派上构建另一个全新的树莓派系统,就像是母鸡下蛋孵小鸡一样!”

开始之前

编译设备需要具有网络连接以及3GB的空闲磁盘空间
因为整个过程将不生成镜像文件,直接把系统写入磁盘,所以需要一张额外的空白MicroSD储存卡(推荐至少8GB),以及相应的读卡器
为了节省时间,除/boot外,/home/proc等都将直接包含在/下,不额外进行分区

磁盘分区

将准备好的sd卡放入读卡器,插入编译设备的USB口让系统进行识别,准备开始分区工作
如果没有接入其他的储存设备,那么新的设备将在/dev/sda
执行以下命令开始磁盘分区:sudo /sbin/fdisk /dev/sda
成功进入fdisk后,首先输入p并回车,让fdisk打印磁盘信息,记录Disk identifier的值(如:0x180be195),这在之后会用到
fdisk打印信息

观察Disklabel type的值,如果不是dos则输入o并回车,将磁盘的分区表修改为DOS,之后便可进行分区

  • 输入n并回车,创建第一个分区(启动分区)
    Partition typePartition number以及First sector保持默认选项,无需输入任何数值,直接回车
    Last sector选项输入526335,回车完成分区创建,此时将回到fdisk主菜单
    回到主菜单后,输入t并回车
    fdisk将自动跳转到Hex code or alias选项,输入b,回车修改分区类型为W95 FAT32
    完成分区类型更改后,将再次回到fdisk主菜单
    输入a并回车,fidks将自动为分区添加“可启动”标识
  • 输入n并回车,创建第二个分区(系统分区)
    Partition typePartition number以及First sector依旧保持默认选项
    Last sector选项时,如不使用交换分区,则直接回车,完成分区工作;如需使用交换分区,则输入结束扇区并回车结束第二分区分区工作
  • 【可跳过】输入n并回车,创建第三个分区(交换分区)
    所有选项全部保持默认,一路回车完成创建工作并回到fdisk主菜单
    回到主菜单后,输入t并回车
    Partition number选项输入3,回车
    Hex code or alias选项输入82,回车完成分区工作

执行完上述操作后,输入w并回车,让fdisk将更改写入磁盘,写入完成后,fdisk将自动退出

最后使用mkfs系列命令进行分区格式化

  • 格式化启动分区:sudo /sbin/mkfs.vfat /dev/sda1
  • 格式化系统分区:sudo /sbin/mkfs.ext4 /dev/sda2

新接入的储存设备(非空白)

构建内核

首先执行sudo apt install git bc bison flex libssl-dev make获取构建内核所需要的依赖
当命令执行完成后,执行git clone --depth=1 https://github.com/raspberrypi/linux下载内核源码

如果需要获取不同版本的源码,请参考该命令:
git clone --depth=1 --branch <branch> https://github.com/raspberrypi/linux
Github的版本列表中一众以rpi-开头的分支才是内核源码
Github版本列表

源码下载完成后,对于不同的设备,接下来的操作也会有些许不同

  • 如果正在为Raspberry Pi 1Raspberry Pi ZeroRaspberry Pi Zero WRaspberry Pi Compute Module 1构建32位操作系统,请执行以下命令:
    cd linux
    KERNEL=kernel
    make bcmrpi_defconfig
    
  • 如果正在为Raspberry Pi 2Raspberry Pi 3Raspberry Pi 3+Raspberry Pi Zero 2 WRaspberry Pi Compute Modules 3Raspberry Pi Compute Modules 3+构建32位操作系统,请执行以下命令:
    cd linux
    KERNEL=kernel7
    make bcm2709_defconfig
    
  • 如果正在为Raspberry Pi 4Raspberry Pi 400Raspberry Pi Compute Module 4构建32位操作系统,请执行以下命令
    cd linux
    KERNEL=kernel7l
    make bcm2711_defconfig
    
  • 如果正在为Raspberry Pi 3Raspberry Pi 3+Raspberry Pi 4Raspberry Pi 400Raspberry Pi Zero 2 WRaspberry Pi Compute Modules 3Raspberry Pi Compute Modules 3+Raspberry Pi Compute Modules 4构建64位操作系统,请执行以下命令:
    cd linux
    KERNEL=kernel8
    make bcm2711_defconfig
    

在正式构建前,可以使用menuconfig修改内核的配置

注意,该步骤并不是必要的,有时候保持默认配置并不是一个坏的选择

开始使用menuconfig前,请执行sudo apt install libncurses5-dev以确保必要依赖
命令执行完成后,即可使用make menuconfig修改内核配置
menuconfig界面

(以下内容为树莓派官方文档中对menuconfig的介绍,原文英文,由机器翻译)
menuconfig实用程序具有简单的键盘导航功能。经过简短的编译后,您将看到一个子菜单列表,其中包含您可以配置的所有选项;有很多,所以花点时间仔细阅读并熟悉一下。
使用箭头键进行导航,使用Enter键进入子菜单(由--->指示),使用Escape两次进入上一级或退出,使用空格键循环选项的状态。有些选项有多个选项,在这种情况下,它们将显示为子菜单,并按Enter键选择一个选项。您可以在大多数条目上按h来获取有关特定选项或菜单的帮助。
在你的第一次尝试中,要抵制启用或禁用很多东西的诱惑;破坏配置相对容易,所以从小处着手,熟悉配置和构建过程。

完成内核配置后,即可开始进行编译工作

  • 对于32位内核,请执行以下命令:
    make -j4 zImage modules dtbs
    
  • 对于64位内核,请执行以下命令:
    make -j4 Image.gz modules dtbs
    

内核的编译将耗费大量的时间以及CPU资源,请保持编译设备拥有充足的电源以及良好的散热

制作rootfs

在内核编译完成后,使用cd ../回到上一级目录
在开始前请先执行sudo apt install debootstrap安装所需依赖
安装完成后,创建sdcard文件夹并cd进入,并在其中创建rootfs文件夹,用于挂载sd卡
执行sudo mount /dev/sda2 rootfs/挂载已格式化的文件系统
接着使用debootstrap构建基础系统

命令参考:
debootstrap --arch [体系结构] [发行版本代号] [目录] [下载源]

[下载源]参数如不填则将使用默认的下载站点
下方链接中包含了所有可用的下载源,替换默认源时请使用离自己最近的站点:
https://www.debian.org/mirror/list

debootstrap在安装后存在于/sbin下,并且需要root权限
这里以构建arm64体系结构,版本为bullseye的基础系统作为示例参考:

sudo /sbin/debootstrap --arch=arm64 bullseye rootfs/

正在运行中的debootstrap

在基础系统构建完成后,下载ch-mount.sh到文件夹中,用以进入制作好的rootfs

wget https://raw.githubusercontent.com/psachin/bash_scripts/master/ch-mount.sh

使用chmod +x ./ch-mount.sh赋予脚本执行权限,再使用./ch-mount.sh -m rootfs/生成临时文件系统并进入rootfs

脚本执行时会请求root权限,但不要以root身份执行脚本
进入rootfs后,可能会出现I have no name!字样,为正常现象
接下来如无特殊说明,本节内的所有操作均在rootfs内的系统中完成

成功执行的ch-mount.sh

进入rootfs后,需先执行apt install ca-certificates为rootfs内的系统安装CA证书
证书安装完毕后,便可以打开/etc/apt/source.list文件更换镜像源
更换镜像源后,执行apt update更新软件列表,完成后继续安装必要程序

apt install dhcpcd5 locales sudo wget

执行useradd添加用户,例如:useradd nolen
修改新用户的密码,例如:passwd nolen
打开/etc/sudoers文件,在# User privilege specification下方新增一行,允许用户使用sudo命令:

nolen   ALL=(ALL:ALL) ALL

允许新用户使用sudo

在修改sudoer文件时,可能遭遇W10: Warning: Changing a readonly file警告
这时只需退出编辑器,使用chmod 640 /etc/sudoers修改sudoers文件的权限即可
不要忘记修改回去:chmod 440 /etc/sudoers

打开/etc/fstab文件,修改其中内容,让内核能够正常挂载文件系统,例如:

# UNCONFIGURED FSTAB FOR BASE SYSTEM
proc /proc proc defaults 0 0
PARTUUID=180be195-01 /boot vfat defaults 0 2
PARTUUID=180be195-02 / ext4 defaults,noatime 0 1
PARTUUID=180be195-03 swap swap defaults 0 0

在示例中
180be195是之前分区时获取到的磁盘id:0x180be195
后方的-01-02代表着磁盘的第一个分区(启动分区)、第二个分区(系统分区)
180be195-03是交换分区

格式参考:
<file system> <mount point> <type> <options> <dump> <pass>
<file system> - 为要挂载的分区或存储设备,即相应的UUID
<mount point> - 为挂载点
<type> - 为文件系统类型
<options> - 为挂载时使用的参数
<dump> - 为是否做备份
<pass> - 为需要检查的文件系统的检查顺序

fstab文件内容

最后可以修改/etc/hostname修改主机名称,例如:echo 'my-rpi' > /etc/hostname
以及在/etc/hosts中新增127.0.0.1 my-rpi以防止sudo命令出现警告信息

完成后即可输入exit退出rootfs,然后使用./ch-mount -u rootfs/卸载掉临时文件系统

安装内核以及驱动

执行sudo mount /dev/sda1 boot/挂载已格式化的文件系统
使用cd ../linux切换到内核源码目录,为rootfs中的系统安装必要模块

  • 对于32位系统,请执行以下命令:
    sudo make ARCH=arm INSTALL_MOD_PATH=../sdcard/rootfs modules_install
    
  • 对于64位系统,请执行以下命令:
    sudo make ARCH=arm64 INSTALL_MOD_PATH=../sdcard/rootfs modules_install
    

在系统模块安装完成后,即可将内核以及驱动放入启动分区

  • 对于32位系统,请执行以下命令:
    sudo cp arch/arm/boot/dts/*.dtb ../sdcard/boot/
    sudo cp arch/arm/boot/dts/overlays/*.dtb* ../sdcard/boot/overlays/
    sudo cp arch/arm/boot/dts/overlays/README ../sdcard/boot/overlays/
    sudo cp arch/arm/boot/zImage ../sdcard/boot/$KERNEL.img
    
  • 对于64位系统,请执行以下命令:
    sudo cp arch/arm64/boot/dts/broadcom/*.dtb ../sdcard/boot/
    sudo cp arch/arm64/boot/dts/overlays/*.dtb* ../sdcard/boot/overlays/
    sudo cp arch/arm64/boot/dts/overlays/README ../sdcard/boot/overlays/
    sudo cp arch/arm64/boot/Image.gz ../sdcard/boot/$KERNEL.img
    

虽然内核以及驱动都以安装完成,但缺少启动必要文件
cd ../回到上一级,执行git clone --depth=1 https://github.com/raspberrypi/firmware获取文件
当文件拉取完成后,执行以下命令将文件放入启动分区:

sudo cp firmware/boot/*.dat sdcard/boot/
sudo cp firmware/boot/*.elf sdcard/boot/

文件复制完成后,使用cd命令切换到已挂载的启动分区内,创建启动配置文件cmdline.txt以及内核配置文件config.txt

cd sdcard/boot/
sudo touch cmdline.txt
sudo touch config.txt

制作完成的启动分区

打开并修改cmdline.txt文件内容:

dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=PARTUUID=180be195-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait quiet splash plymouth.ignore-serial-consoles psi=1

cmdline.txtroot=PARTUUID=选项的值指向的是磁盘系统分区,注意替换

打开并修改config.txt文件内容:

  • 对于32位系统:
    [all]
    arm_64bit=0
    framebuffer_width=1280
    framebuffer_height=720
    disable_overscan=1
    dtparam=audio=on
    
  • 对于64位系统
    [all]
    arm_64bit=1
    framebuffer_width=1280
    framebuffer_height=720
    disable_overscan=1
    dtparam=audio=on
    

完成后回到上一级目录,卸载各文件系统

cd ../
sudo umount boot/
sudo umount rootfs/