linux2021
這篇文是從我研究過程中雜亂的筆記所整理出來,過程中需要安裝的套件或是步驟可能會有錯誤或是缺漏(畢竟前前後後找問題裝了不少東西)。
如有疏漏,請大家不吝指教,謝謝大家!
比較常見可以跑在 Raspberry Pi 4 的 Linux kernel 大致上分成 Mainline Kernel(本文撰寫時 5.14 剛剛推出), Raspbian (5.10, 32-bit), 跟 Ubuntu (5.4, 32/64-bit) 這幾種。其中,Raspbian 目前還是以 32-bit 的 kernel 為主(所有 user space 的應用程式都是 32-bit,雖然你可以把 kernel 換成 64-bit 的)。
由於我自己的實驗所需(對 kernel 進行 patching),下面在 Raspberry Pi 上面進行編譯的段落,是基於 Ubuntu Server for Raspberry Pi 64-bit 版本的 kernel 所撰寫,畢竟我需要的是 64-bit 的環境。
Raspbian 的編譯方式官方文件就已經寫得很清楚了,所以本文著墨的主要是在 Ubuntu Server for Raspberry Pi (64-bit) 版本的 kernel 跟 Mainline Kernel 的部分。
Kernel 可以直接在 host 環境上編譯,也可以使用 cross compile 的技巧來進行。通常嵌入式系統的 CPU 運算能力都比較差,所以使用 cross compile 的技巧可以省很多時間。
這一段都是基於假設你使用的是 Ubuntu for Raspberry Pi 64-bit 版本的 kernel 所撰寫。
sudo apt update
sudo apt build-dep linux linux-image-$(uname -r)
sudo apt install build-essential libncurses-dev linux-tools-common fakeroot
經驗上來說,完整的編譯一次大概要 2~3 小時(如果有裝風扇且開 performance mode 的情況下)。
sudo apt update
sudo apt build-dep linux
sudo apt install build-essential libncurses-dev linux-tools-common fakeroot
兩種方法都可以,就只是要注意一下 compiler 的名稱有一點點差異。
apt
安裝sudo apt install crossbuild-essential-arm64
sudo apt install gcc-aarch64-linux-gnu
sudo apt install git-lfs
安裝 git lfs
git clone https://github.com/DLTcollab/toolchain-arm
tar -xvJf [filename]
aarch64-none-linux-gnu
系列的 toolchain~/.bashrc
裡(或是你對應的 shell config file 中),加入剛剛解壓縮的 compiler 的 bin
路徑
export PATH=$PATH:/home/ubuntu/toolchain-arm/gcc-arm-10.2-2020.11-x86_64-aarch64-none-linux-gnu/bin
我自己是使用 i5-1135g7
(4C8T) ,跑 virtual box 配給 4 個 virtual CPU,半小時內可以完成編譯。
網路上有好心人把 cross compile 的環境打包成了 docker image。我自己沒實際使用過,但是看 dockerfile 跟 run script 都滿清晰,也跟我自己的編譯步驟是相同的。
分成 Ubuntu 版本 跟 mainline kernel 兩個進行討論。
debian/rules
官方文件 雖然有點舊,但是仍然是正確的(也可以參考這篇文的 all-in-one 整理)。
Ubuntu 是使用 Debian 的 fakeroot debian/rules
toolchain 系列,滿好使用的。
.deb
會被放在執行編譯指令的上一層目錄中)
mkdir ~/kbuild
cd ~/kbuild
git clone --depth=1 git://git.launchpad.net/~ubuntu-kernel/ubuntu/+source/linux-raspi/+git/focal
export CC=aarch64-linux-gnu-gcc
export $(dpkg-architecture -aarm64)
export CROSS_COMPILE=aarch64-linux-gnu-
uname
(可以略過這一步驟)
fakeroot debian/rules editconfigs
來進行修改是無效的(因為 append LOCALVERSION 的選項已經被強制關閉 - module 編譯的問題)debian.raspi/changelog
在第一行的版本號那裡加字串
+CFS
fakeroot debian/rules clean
fakeroot debian/rules binary-headers binary binary-perarch
.deb
會被放在執行編譯指令的上一層目錄中)
mkdir ~/kbuild
cd ~/kbuild
wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.14.tar.xz
tar -xvJf linux-5.14.tar.xz
make distclean
make ARCH=arm64 CROSS_COMPILE=aarch64-none-linux-gnu- defconfig
sed -i 's/CONFIG_LOCALVERSION_AUTO=y/CONFIG_LOCALVERSION_AUTO=n/' .config
make ARCH=arm64 CROSS_COMPILE=aarch64-none-linux-gnu- LOCALVERSION="-cfs-raspi" -j$(nproc) deb-pkg
make distclean
git reset
或是 git checkout
等命令)make ARCH=arm64 CROSS_COMPILE=aarch64-none-linux-gnu- defconfig
ARCH
跟 CROSS_COMPILE
的設定是不是正確的
defconfig
會造成編譯出來的 deb
裡頭的 dts
包含很多用不到的 driver -> 也許可以從 raspbian 的 arch/arm64/config/bcm2711_defconfig
進行調整(這只是個發想)sed -i 's/CONFIG_LOCALVERSION_AUTO=y/CONFIG_LOCALVERSION_AUTO=n/' .config
dpkg -i
來自動進行 kernel 置換),這個就很重要了。
make ARCH=arm64 CROSS_COMPILE=aarch64-none-linux-gnu- LOCALVERSION="-cfs-raspi" -j$(nproc) deb-pkg
ARCH
跟 CROSS_COMPILE
的設定
LOCALVERSION
uname
的步驟-
開頭,才不會把版本號直接跟你的字串串接了-raspi
當結尾,理由請看上一段-cfs-raspi
-cfs-test1-raspi
bindeb-pkg
sudo dpkg -i *.deb
uname
正確的話,u-boot 會自動地被置換。sync; sudo reboot
重新開機apt list --installed | grep "linux-image*raspi"
看一下目前有安裝的 kernelsudo apt autoremove --purge [kernel image name]
來進行移除
uname
正確的話,u-boot 會自動地被置換。