ETJava Beta | Java    注册   登录
  • 搜索:
  • 树莓派CM4(四):树莓派镜像替换内核

    发表于      阅读(1)     博客类别:Crawler     转自:https://www.cnblogs.com/zhijun1996/p/18382643
    如有侵权 请联系我们删除  (页面底部联系我们)  

    树莓派镜像替换内核

    1. 为什么要替换内核

    • 树莓派官方提供的镜像中,自带的内核版本为6.6.31

    • 然而github上提供的内核源码为6.6.40,有些微差别

    • 此外,后续很有可能进行内核裁剪定制,替换内核是一个无法绕开的工作

    2. 获取内核源码

    • github地址:

      https://github.com/raspberrypi/linux

    • 选择使用6.6.y版本的内核

    • 将其拷贝到ubuntu

    • 解压

      $ unzip linux-rpi-6.6.y.zip
      
    • 进入内核源码目录

      $ cd linux-rpi-6.6.y
      

    3. 获取交叉编译工具链

    4. 内核编译

    • 修改顶层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)
      

    5. 挂载树莓派镜像到Ubuntu

    • 解压,得到*.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
      

    6. 安装新内核

    • 进入内核源码目录

    • 安装内核模块到根文件系统

      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
      

    7. 解决内核模块无法加载的问题

    • 进入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 &
      

    8. 选择内核

    • 修改boot分区下的config.txt,选择使用新的内核
      $ sudo vi ./boot/config.txt
      
    • config.txt末尾添加如下内容
      kernel=kernel8.img
      

    9. 取消镜像挂载

    • 取消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
      

    10. 镜像烧录

    11. 查看内核是否替换成功

    • 开机,首次开机时系统会自动重启两次,属正常现象
    • 进入系统后查看内核版本,内核版本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