樹莓派(Raspberry Pi 4 Model B)編譯64位內核Kernel(64位系統)

樹莓派系統默認安裝的是ARM32位的系統,可是從樹莓派3開始是支持ARM64位系統的,官方既然不給64位系統, 那隻好咱們本身來編譯了。linux

網上其實有不少樹莓派3B的編譯64位內核,我都試了一遍,所有啓動不了,也不是說寫得不對,只不過好像不適用於我,搞了我三四天,很愁人;因此我下面的步驟也不保證每一個人均可以成功,由於每一個人的狀況都不同,形成的問題也不同,因此出現問題只能靠本身百度或者Google了。git

並且有不少筆記只是把內核編譯爲64位,可是文件系統仍是官方的32位,並不能稱爲真正的64位系統,因此我後面也把根文件系統也構建爲64位的了。github

筆記在記載的時候不免有遺漏的,若是有哪一個步驟不太對,歡迎留言,及時修改。bootstrap

若是不想這麼麻煩,想直接使用64位的系統,能夠下載已經開源的64位系統:Debian-Pi-Aarch64,這個是第三方的,不是樹莓派官方提供的。ubuntu

編譯環境

經過vm虛擬機安裝的虛擬環境Linux,如何安裝網上一搜就有了,按照步驟安裝便可。vim

編譯機:Ubuntu 18.04-desktop-amd64bash

想要編譯64位的內核,只能在64位的機器上來編譯。架構

交叉編譯器

經過交叉編譯器生成64位的內核(Kernel)app

定義:交叉編譯器(英語:Cross compiler)是指一個在某個系統平臺下能夠產生另外一個系統平臺的可執行文件的編譯器async

這句話個人理解形象一點解釋就是:

  • Ubuntu 18.04-amd64:定製服裝加工工廠(某個系統平臺)

  • 交叉編譯器:製做衣服的機器(編譯器)

  • linux源碼(kernel):服裝材料(可執行文件的源碼)

  • 樹莓派4B:人(另外一個平臺)

有了以上,如今我要給人作一件衣服,那麼我須要找一個專門給人作衣服的工廠,把服裝材料給工廠後,製做衣服的機器作出來的衣服,人就能夠穿了。

每一個人理解的都不同,只要記住上面專業的定義就行了,本身怎麼理解按本身的來就能夠了。

編譯內核(kernel)

就如上面定義的同樣,那四樣咱們都須要先獲取到才能夠製做;Ubuntu確定先要安裝好;樹莓派固然也要準備好。

能夠用普通用戶,儘可能不要用root用戶來執行,等須要用到root用戶時,再切換到root用戶來執行

編譯內核前準備

  • 獲取交叉編譯器並配置

Linaro Toolchain

下載上面連接中的 gcc-linaro-7.4.1-2019.02-x86_64_aarch64-linux-gnu.tar.xz,有可能更新了,日期和版本會變化。 或者用命令下載

$ sudo wget https://releases.linaro.org/components/toolchain/binaries/latest-7/aarch64-linux-gnu/gcc-linaro-7.4.1-2019.02-x86_64_aarch64-linux-gnu.tar.xz
複製代碼

建立一個工做目錄,後續的操做都在工做目錄中操做

$ mkdir ~/build && cd ~/build
$ sudo apt-get install lrzsz
# 把下載好的文件上傳並解壓
$ rz
$ sudo tar -xvf  gcc-linaro-7.4.1-2019.02-x86_64_aarch64-linux-gnu.tar.xz -C /usr/src/
$ cd /usr/src/ && sudo mv gcc-linaro-7.4.1-2019.02-x86_64_aarch64-linux-gnu aarch64-linux-gnu
$ sudo vi /etc/profile
or
$ sudo vi ~/.bashrc
# 末尾添加如下內容
export ARCH_HOME=/usr/src/aarch64-linux-gnu
export PATH=$PATH:$ARCH_HOME/bin
$ source /etc/profile
or
$ source ~/.bashrc
複製代碼

Note:若是是在普通用戶下,還須要切換到root下再配置一遍,普通用戶也須要配置

  • 獲取Raspberry Kernel源碼

raspberry如今默認的就是4.19版本,不過更高的版本也是有的,看本身下載哪一個更改一下版本就能夠了,Raspberry官方的github下載超級慢,我是把Raspberry Linux遷移到了國內碼雲上,這樣下載起來就很快了;有區別的就是官方更新,不會更新到個人碼雲的倉庫上,想要最新的代碼,能夠先把官方的fork到本身的github,再遷移到本身的碼雲,把連接更換成本身的就能夠了,下面的命令選擇一個下載就能夠了

$ cd ~/build
$ sudo apt-get install git
# 官方的github地址
$ git clone --depth=1 --branch rpi-4.19.y https://github.com/raspberrypi/linux
# 碼雲的地址
$ git clone --depth=1 --branch rpi-4.19.y https://gitee.com/nzwxl/linux
複製代碼
  • 安裝編譯環境所需的依賴
$ sudo apt-get install git bison flex libssl-dev zip libncurses-dev make
複製代碼

libncurses-dev依賴是支持後面menuconfig的

內核(kernel)編譯開始

# 若是源碼文件不叫linux,能夠mv 改爲linux或者你想要的的名字
$ cd linux
# 在編譯以前能夠先進行清除命令,以保證清潔的環境,若是在編譯的環節出錯或者操做失誤,能夠運行此命令從新開始。
$ make distclean
# 編譯.config,ARCH要配置成arm64,若是不配置則默認爲開發機的x86了,CROSS_COMPILE指定編譯器
# bcm2711_defconfig在 arch/arm64/configs/bcm2711_defconfig,它會本身根據Makefile本身去找這個文件
$ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- bcm2711_defconfig
# 在當前的.config基礎上開始裁剪內核,若是沒有要裁剪的按ESC兩次退出便可,主要是我也沒太瞭解,等我瞭解了再記
$ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- menuconfig
# 開始編譯內核, 參數-j5的意思是 使用多處理器同時編譯內核,數字最大爲:cpu的核數 × 1.5,可自行修改
$ make -j5 ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-
複製代碼

中間不報錯的話,大概會在1個小時左右,會在目錄 arch/arm64/boot 中生成 Image 二進制內核文件;若是製做的是32爲內核,會在 arch/arm/boot 生成zImage 二進制內核;同時會在linux目錄中生成最原始的內核文件vmlimux。

vmlinunx:最原始的linux內核文件。

zImage: 通過壓縮和去掉調試信息的可加載二進制內核文件。

Image:沒有通過壓縮的可加載二進制內核文件。

有關更多關於內核文件可Google。

安裝kernel modules

這個modules在後面的根文件系統(rootfs)中用的到,先安裝到 ~/build 工做目錄中,記得把 [user] 替換爲本身的用戶名

$ cd ~/build/linux
# 切換到root用戶下
$ su
$ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- INSTALL_MOD_PATH=/home/[user]/build/ modules_install
$ su [user]
複製代碼

樹梅派boot文件

由於樹莓派官方的 bootloader 是不開源的,可是提供了可使用的boot目錄下全部的東西,一樣的我由於網速的緣由下載太慢,遷移到了碼雲上。

$ cd ~/build
$ git clone --depth=1 https://github.com/raspberrypi/firmware/
or
$ git clone --depth=1 https://gitee.com/nzwxl/firmware/
# firmware/boot 下就是須要的文件了
$ ls firmware/boot
複製代碼

製做ARM64架構的rootfs

如何製做ARM64的rootfs我在另外一篇筆記中記錄了,到此步驟能夠繼續按照那篇筆記順序操做,等rootfs製做完,回到此筆記與下一個步驟銜接

kernel、uboot、rootfs打包進鏡像

製做鏡像文件

  • 建立一個大小爲 1000M 的根文件系統映像文件,而後對映像文件分區

經燒錄後顯示,1000M的話已經使用了90%,因此要是有許多要作的事情,或者上傳一些東西的話,最好建立個比較大一點的映像文件

$ cd ~/build
$ fallocate -l 1000M rootfs.img
# 分區
$ fdisk rootfs.img
    a.輸入o。這將清除映像文件上的任何分區。
    b.鍵入p以列出分區。應該沒有分區。
    c.鍵入n,而後p爲primary,1表示驅動器上的第一個分區,按ENTER接受默認的第一個扇區,而後爲最後一個扇區鍵入+ 100M。
    d.鍵入t,而後c將第一個分區設置爲鍵入W95 FAT32(LBA)。
    e.鍵入n,而後p表示主驅動器,2表示驅動器上的第二個分區,而後按兩次ENTER鍵接受默認的第一個和最後一個扇區。
    f.寫入分區表並鍵入w退出。
# 可經過命令查看設置好的分區
$ fdisk -l rootfs.img
複製代碼
  • 使用kpartx掛載鏡像到loopX

在linux中,若是映像文件(.img)含有分區表的話,使用mount是掛在不上的;可使用kpartx掛載; X是你顯示的數字,Y也是數字,每一個人不必定相同,第一個 loopXpY 是上面分區後的第一個分區,第二個就是第二個分區

$ sudo apt-get install kpartx
$ sudo kpartx -av rootfs.img
add map loopXpY (254:0): 0 204800 linear 7:0 2048
add map loopXpY (254:1): 0 407552 linear 7:0 206848
# 這兩個設備能夠在 /dev/mapper/ 目錄中看到
$ ls /dev/mapper/
複製代碼
  • 格式化分區並指定分區LABEL名字
$ sudo mkfs.vfat -n BOOT /dev/mapper/loop5p1
$ sudo mkfs.ext4 -F -L -O "^has_journal" ROOTFS /dev/mapper/loop5p2
# 第一個命令中的-n 參數就是指定LABEL,能夠經過 man mkfs.vfat 查看參數詳情
# 第二個命令的 -F 是強制的意思(理解的不對能夠糾正我),-L 指定LABEL 一樣能夠經過man mkfs.ext4 查看參數詳情
複製代碼
  • 建立掛載點並掛載

通過格式化分區後,如今咱們能夠掛載loopXpY設備到文件

$ sudo mkdir {/mnt/loopXp1,/mnt/loopXp2}
$ sudo mount /dev/mapper/loop5p1 /mnt/loopXp1
$ sudo mount /dev/mapper/loop5p2 /mnt/loopXp2
複製代碼

複製內核和boot所需文件

$ cd ~/build
# 複製boot所需文件
$ sudo cp -r firmware/boot/* /mnt/loopXp1/
$ sudo cp linux/arch/arm64/boot/dts/broadcom/*.dtb /mnt/loopXp1
$ sudo cp linux/arch/arm64/boot/dts/overlays/*.dtb* /mnt/loopXp1/overlays/
$ sudo cp linux/arch/arm64/boot/dts/overlays/README /mnt/loopXp1/overlays/
# 複製內核
$ sudo cp linux/arch/arm64/boot/Image /mnt/loopXp1/kernel8.img
複製代碼

編寫cmdline.txt和 config.txt

參考:RPi_cmdline.txt

編寫cmdline.txt

# 添加內容並保存退出
$ sudo vim /mnt/loopXp1/cmdline.txt
console=serial0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 rw rootwait fsck.repair=yes
複製代碼
  • console=serial0,115200:串口使用哪一個設備,以及傳輸速率
  • console=tty1:控制檯輸出使用tty1設備
  • root=/dev/mmcblk0p2:將內存卡第二分區設置爲根分區
  • rootfstype=ext4:根分區類型 f2fs應更換爲f2fs
  • rw:可寫掛載跟分區
  • rootwait:等待內核識別根分區設備後再掛載
  • sck.repair=yes:啓動時自動檢查修復文件系統錯誤

編寫config.txt

# 添加內容並保存退出
$ sudo vim /mnt/loopXp1/config.txt

# 以64位讀取內核
arm_64bit=1
# 想要以ARMV8的模式啓動,設置此選項
arm_control=0x200
# 內核的名字
kernel=kernel8.img

# u-boot進行引導kernel時延遲幾秒
boot_delay=1

# 關閉藍牙功能
# See /boot/overlays/README for all available options
dtoverlay=disable-bt
# 開啓音頻snd_bcm2835
dtparam=audio=on
複製代碼

同步rootfs進鏡像第二分區

$ sudo apt-get install rsync
$ cd ~/build/linux-rootfs/
# 開始同步
$ sudo rsync -HPavz -q ./ /mnt/loopXp2
複製代碼

rsync參數詳解: rsync命令

編寫fstab文件

若是想要第一分區中的boot目錄在系統啓動後顯示文件,須要在 /etc/fstab 中添加如下內容:

$ sudo vim /mnt/loopXp2/etc/fstab
<file system>   <mount point>    <type>   <options>  <dump> <pass>
LABEL=BOOT      /boot            vfat     defaults   0      1
複製代碼
  • file system: 能夠是實際分區名,也能夠是實際分區的卷標(Lable),卷標名上面已經規定過了
  • mount point: 是掛載點
  • type: 爲此分區的文件系統類型,vfat位fat32的類型應該是
  • options: 是掛載的選項,用於設置掛載的參數,常見的有如下參數
    • defaults: rw, suid, dev, exec, auto, nouser, and async.
    • auto: 系統自動掛載,fstab默認就是這個選項
    • noauto 開機不自動掛載
    • nouser 只有超級用戶能夠掛載
    • ro 按只讀權限掛載
    • rw 按可讀可寫權限掛載
    • user 任何用戶均可以掛載
  • dump: 是備份設置 當其值設置爲1時,將容許dump備份程序備份;設置爲0時,忽略備份操做;
  • pass: 是fsck磁盤檢查設置; 其值是一個順序。當其值爲0時,永遠不檢查;而 / 根目錄分區永遠都爲1。其它分區從2開始,數字越小越先檢查,若是兩個分區的數字相同,則同時檢查。

安裝內核模塊

由於在編譯kernel時已經把modules安裝到了工做目錄build中了,直接複製到第二分區中就能夠了,若是不放心,能夠用安裝modules的命令安裝到第二分區下,更改下路徑就能夠了。

$ cd ~/build
$ sudo cp -r lib/modules/ /mnt/loopXp2/lib/
複製代碼

卸載燒錄IMG文件到SD卡

$ cd ~/build
$ sync
$ sudo umount /mnt/loopXp1/
$ sudo umount /mnt/loopXp2/
$ sudo kpartx -dv rootfs.img
複製代碼

把 rootfs.img 下載到windowns下 燒錄到SD卡中,燒錄SD卡的方式可參考:

啓動Raspberry後經過命令查看內核版本爲64位

uname -a

參考

相關文章
相關標籤/搜索