树莓派官方提供的镜像中,自带的内核版本为6.6.31
然而github
上提供的内核源码为6.6.40
,有些微差别
此外,后续很有可能进行内核裁剪定制,替换内核是一个无法绕开的工作
github
地址:
选择使用6.6.y
版本的内核
将其拷贝到ubuntu
中
解压
$ unzip linux-rpi-6.6.y.zip
进入内核源码目录
$ cd linux-rpi-6.6.y
我所选用树莓派镜像中的gcc
版本为12.2.0
为了避免出现glibc
版本不一致的问题,同样使用12.2.0
版本的交叉编译工具链
下载地址:
https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads
修改顶层Makefile
,指定目标平台ARCH
和交叉编译工具链CROSS_COMPILE
树莓派CM4使用的时博通BCM2711的方案,因此使用bcm2711_defconfig
生成默认配置文件
linux-rpi-6.6.y$ make bcm2711_defconfig
menuconfig
配置
linux-rpi-6.6.y$ make menuconfig
在这里我需要将LAN78XX
驱动直接编译进内核,不作为外部模块
开始编译,内核镜像/驱动模块/设备树都需要编译,使用-j$(nproc)
全核编译,加快编译速度
linux-rpi-6.6.y$ make Image modules dtbs -j$(nproc)
Raspberry Pi OS Lite
,镜像下载地址
解压,得到*.img
的镜像文件
挂载镜像到Ubuntu
# .img镜像
jun@ubuntu:$ ls
2024-07-04-raspios-bookworm-arm64-lite.img
# 查看第一个未使用的回环设备
jun@ubuntu:$ losetup -f
/dev/loop0
# 将.img镜像关联到回环设备
jun@ubuntu:$ sudo losetup /dev/loop0 2024-07-04-raspios-bookworm-arm64-lite.img
[sudo] password for jun:
# 查看分区,检测到两个区,其中较小的是系统分区,较大的是根文件系统
jun@ubuntu:$ sudo kpartx -av /dev/loop0
add map loop0p1 (253:0): 0 1048576 linear 7:0 8192
add map loop0p2 (253:1): 0 4481024 linear 7:0 1056768
# 创建系统分区挂载目录
jun@ubuntu:$ mkdir boot
# 创建根文件系统挂载目录
jun@ubuntu:$ mkdir rootfs
# 挂载系统分区
jun@ubuntu:$ sudo mount /dev/mapper/loop0p1 ./boot/
# 挂载根文件系统
jun@ubuntu:$ sudo mount /dev/mapper/loop0p2 ./rootfs/
# 查看系统分区
jun@ubuntu:$ ls ./boot/
bcm2710-rpi-2-b.dtb bcm2710-rpi-zero-2-w.dtb bcm2711-rpi-cm4s.dtb bootcode.bin fixup4db.dat fixup_x.dat kernel8.img start4.elf start_x.elf
bcm2710-rpi-3-b.dtb bcm2711-rpi-400.dtb bcm2712d0-rpi-5-b.dtb cmdline.txt fixup4x.dat initramfs_2712 LICENCE.broadcom start4x.elf
bcm2710-rpi-3-b-plus.dtb bcm2711-rpi-4-b.dtb bcm2712-rpi-5-b.dtb config.txt fixup_cd.dat initramfs8 overlays start_cd.elf
bcm2710-rpi-cm3.dtb bcm2711-rpi-cm4.dtb bcm2712-rpi-cm5-cm4io.dtb fixup4cd.dat fixup.dat issue.txt start4cd.elf start_db.elf
bcm2710-rpi-zero-2.dtb bcm2711-rpi-cm4-io.dtb bcm2712-rpi-cm5-cm5io.dtb fixup4.dat fixup_db.dat kernel_2712.img start4db.elf start.elf
# 查看根文件系统
jun@ubuntu:$ ls ./rootfs/
bin boot dev etc home lib lost+found media mnt opt proc root run sbin srv sys tmp usr var
进入内核源码目录
安装内核模块到根文件系统
linux-rpi-6.6.y$ sudo env PATH=$PATH make INSTALL_MOD_PATH=../rootfs modules_install
安装头文件到根文件系统的usr
目录
linux-rpi-6.6.y$ sudo make headers_install INSTALL_HDR_PATH=../rootfs/usr/
安装Image
到挂载的boot
分区
linux-rpi-6.6.y$ sudo cp arch/arm64/boot/Image ../boot/kernel8.img
安装设备树文件
linux-rpi-6.6.y$ sudo cp arch/arm64/boot/dts/broadcom/*.dtb ../boot/
linux-rpi-6.6.y$ sudo cp arch/arm64/boot/dts/overlays/*.dtb* ../boot/overlays/
替换version.h
linux-rpi-6.6.y$ sudo cp include/generated/uapi/linux/version.h ../rootfs/usr/include/linux/version.h
进入rootfs
根文件系统中的驱动存放目录
linux-rpi-6.6.y$ cd ./rootfs/lib/modules/6.6.40-v8/
查找.ko文件,发现没有任何内核模块
6.6.40-v8$ find . -name *ko
检查发现,该目录下有很多.ko.xz
文件,原因是make module_install
命令执行时,自动将.ko文件进行了压缩,但是这样会导致内核启动时无法加载模块,需要将压缩的.ko文件进行解压
编写脚本modules_install.sh
用来在系统第一次开机时生成modules.dep
文件,将该脚本存放在rootfs/lib/modules/6.6.40-v8/
目录下,脚本内容如下
#!/bin/bash
# modules path
MODULES_PATH=/lib/modules/$(uname -r)
# 解压*.ko.xz文件
module_decompress()
{
MODULES_XZ_FILES=`find ${MODULES_PATH} -name *ko.xz`
for MODULE in ${MODULES_XZ_FILES}
do
set -x
xz -dk ${MODULE}
set +x
done
return 0
}
RET=$(cat ${MODULES_PATH}/modules.dep)
if [ -z "${RET}" ]; then
# modules decompress
module_decompress
# generate modules.dep
depmod
# make sure this script executed only once
SCRIPT_NAME=$(basename $0)
sed -i "/$SCRIPT_NAME/d" /etc/rc.local
# reboot
reboot
else
echo "modules already installed!"
fi
exit 0
给脚本以可执行权限
6.6.40-v8$ sudo chmod 777 modules_install.sh
在根文件系统下的etc/rc.local
中添加如下内容,使module_install.sh
脚本开机自启动
# modules_install
/bin/bash /lib/modules/$(uname -r)/modules_install.sh &
boot
分区下的config.txt
,选择使用新的内核$ sudo vi ./boot/config.txt
config.txt
末尾添加如下内容kernel=kernel8.img
5. 挂载树莓派镜像到Ubuntu
的镜像挂载jun@ubuntu:$ ls
2024-07-04-raspios-bookworm-arm64-lite.img boot rootfs
jun@ubuntu:$ sudo umount ./boot
jun@ubuntu:$ sudo umount ./rootfs
jun@ubuntu:$ sudo losetup -d /dev/loop0
6.6.40
,替换成功 # uname -a
Linux IG-210 6.6.40-v8 #2 SMP PREEMPT Tue Aug 27 14:04:24 CST 2024 aarch64 GNU/Linux