樹莓派CM4(四):樹莓派映象替換核心

zhijun發表於2024-08-27

樹莓派映象替換核心

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. 獲取交叉編譯工具鏈

  • 我所選用樹莓派映象中的gcc版本為12.2.0

  • 為了避免出現glibc版本不一致的問題,同樣使用12.2.0版本的交叉編譯工具鏈

  • 下載地址:

    https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads

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

  • 選擇使用使用樹莓派最新的映象Raspberry Pi OS Lite,映象下載地址

    https://downloads.raspberrypi.com/raspios_lite_arm64/images/raspios_lite_arm64-2024-07-04/2024-07-04-raspios-bookworm-arm64-lite.img.xz

  • 解壓,得到*.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. 映象燒錄

  • 參考之前的文章:樹莓派CM4(一):映象燒錄

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

相關文章