Introduction
Pour construire le kernel, vous aurez juste besoin de ce fichier :
- build.sh
- toolchain.sh
Fichiers requis
build.sh
[Fichier]
#/bin/bash
# 2022-10-15
clear
OUTFOLDER=/opt/build/toolchain/raspberrypi/arm64/kernel
KERNEL_MAIN=$1
KERNEL_PATCH=$2
KERNEL_RT=$3
# overrides
KERNEL_MAIN=6.0
KERNEL_PATCH=/opt/scripts/toolchain/arm64/patchs/kernel_config_patch_6.0.0.patch
KERNEL_RT=
bash toolchain.sh $OUTFOLDER $KERNEL_MAIN $KERNEL_PATCH $KERNEL_RT
exit 0
toolchain.sh
[Fichier]
#!/bin/bash
# 2022-10-15
KERNEL_DEFAULT=6.0
OUTFOLDER=$1
KERNEL_MAIN=$2
KERNEL_PATCH=$3
KERNEL_RT=$4
PATCH_FILE=
KERNEL=
FINAL_FOLDER=$OUTFOLDER
BASE_FOLDER=$FINAL_FOLDER
SKIP_PACMAN=1
SKIP_TOOLCHAIN_CREATION=1
SKIP_ADD_FOLDER=0
SKIP_GRAB_KERNEL=0
SKIP_KERNEL_RT=1
SKIP_BUILD_KERNEL=0
SKIP_BUILD_FINAL=0
#
# https://www.raspberrypi.com/documentation/computers/linux_kernel.html#cross-compiling-the-kernel
# https://wiki.archlinux.org/title/Cross-compiling_tools_package_guidelines
# https://ilyas-hamadouche.medium.com/creating-a-cross-platform-toolchain-for-raspberry-pi-4-5c626d908b9d
#
function header() {
clear
echo ">>> Toolchain Archlinux / RPi 4 ARM64 / Kernel"
echo "--------------------------------------------------"
echo ">> DATE : $CURRENT"
echo ">> OUTFOLDER: $OUTFOLDER"
echo ">> BRANCH : $BRANCH"
echo ">> PATCH : $PATCH_FILE"
echo ">> RT PATCH : $KERNEL_RT"
echo ">> VERSION : $VERSION"
echo ">> KERNEL : $KERNEL"
echo "--------------------------------------------------"
echo ""
}
function wait() {
read -p "> [Press enter to continue] "
}
header
echo "> Prepare things"
# if kernel branch is not given, use default
if [ -z "$KERNEL_MAIN" ]; then
KERNEL_MAIN=$KERNEL_DEFAULT
fi
# if patch is given but file doesn't exist, remove it
if [ ! -z "$KERNEL_PATCH" ]; then
if [ ! -f "$KERNEL_PATCH" ]; then
KERNEL_PATCH=
else
PATCH_FILE=$(basename $KERNEL_PATCH)
fi
fi
# kernel branch/version
MAIN=$KERNEL_MAIN
BRANCH=rpi-$MAIN.y
# use current date as base kernel folder
CURRENT=$(date '+%Y-%m-%d')
# folders
OUTFOLDER=$BASE_FOLDER/$CURRENT
header
echo "> Create working folders"
if [ ! -d "~/src" ]; then
mkdir -p ~/src
fi
if [ ! -d "$OUTFOLDER" ]; then
mkdir -p $OUTFOLDER
fi
cd $OUTFOLDER
if [ ! -d "ctng" ]; then
mkdir ctng
fi
cd $OUTFOLDER
if [ ! -z "$PATCH_FILE" ]; then
cp $KERNEL_PATCH $OUTFOLDER/$PATCH_FILE
fi
if [ "$SKIP_PACMAN" == "0" ]; then
header
echo "> Install crosstool-ng"
wait
sudo pacman -S --needed crosstool-ng
fi
if [ "$SKIP_TOOLCHAIN_CREATION" == "0" ]; then
header
echo "> Create toolchain for RPi 4"
echo ">> Set 'Render the toolchain read-only' to false (uncheck)"
wait
ulimit -n 4096 now
#
# Make 1 changes:
# 1. Allow extending the toolchain after it is created (by default, it is created as read-only):
# Paths and misc options -> Render the toolchain read-only ->false
#
cd ctng
ct-ng -j$(nproc) aarch64-rpi4-linux-gnu
ct-ng -j$(nproc) menuconfig
header
# (path: ${HOME}/x-tools/aarch64-rpi4-linux-gnu)
echo "> Build the toolchain"
ct-ng -j$(nproc) build
fi
header
echo "> Add toolchain path"
cd $OUTFOLDER
PATH=$PATH:~/x-tools/aarch64-rpi4-linux-gnu/bin
if [ "$SKIP_ADD_FOLDER" == "0" ]; then
header
echo "> Add folders"
wait
sudo rm -rf build
mkdir -p build/mnt/fat32/overlays
mkdir -p build/mnt/ext4/opt/build/kernel/$CURRENT/$BRANCH
fi
if [ ! -z "$PATCH_FILE" ]; then
cp $OUTFOLDER/$PATCH_FILE build/mnt/$PATCH_FILE
fi
if [ "$SKIP_GRAB_KERNEL" == "0" ]; then
header
echo "> Get kernel sources"
rm -rf linux
rm -rf $BRANCH
git clone --branch $BRANCH --depth=1 https://github.com/raspberrypi/linux
mv linux $BRANCH
fi
cd $BRANCH
header
echo "> Get exact kernel version"
FILE=Makefile
KVERSION=VERSION
KPATCHLEVEL=PATCHLEVEL
KSUBLEVEL=SUBLEVEL
KEXTRAVERSION=EXTRAVERSION
GET\_VAR=\$KVERSION && KVERSION=\$\(grep --color=never -Po \"^\${GET\_VAR}\ =\ \K.\*\" \"\${FILE}\" \|| true)
GET\_VAR=\$KPATCHLEVEL && KPATCHLEVEL=\$\(grep --color=never -Po \"^\${GET\_VAR}\ =\ \K.\*\" \"\${FILE}\" \|| true)
GET\_VAR=\$KSUBLEVEL && KSUBLEVEL=\$\(grep --color=never -Po \"^\${GET\_VAR}\ =\ \K.\*\" \"\${FILE}\" \|| true)
GET\_VAR=\$KEXTRAVERSION && KEXTRAVERSION=\$\(grep --color=never -Po \"^\${GET\_VAR}\ =\ \K.\*\" \"\${FILE}\" \|| true)
VERSION=$KVERSION.$KPATCHLEVEL.$KSUBLEVEL
if [ "$SKIP_BUILD_KERNEL" == "0" ]; then
header
if [ "$SKIP_KERNEL_RT" == "0" ]; then
echo "> Apply RT patchs"
wget https://mirrors.edge.kernel.org/pub/linux/kernel/projects/rt/$MAIN/patch-$MAIN-$KERNEL_RT.patch.gz
if [ ! -f patch-$MAIN-$KERNEL_RT.patch.gz ]; then
echo ">> No Kernel RT patch found... Not appying !"
wait
else
gzip -cd patch-\$MAIN-\$KERNEL\_RT.patch.gz | patch -p1 --verbose
fi
fi
header
echo "> Generate default config"
KERNEL=kernel8
env PATH=$PATH make -j$(nproc) ARCH=arm64 CROSS_COMPILE=aarch64-rpi4-linux-gnu- bcm2711_defconfig
header
echo "> Disable Debug Infos"
env PATH=$PATH scripts/config --disable DEBUG_INFO
header
echo "> Backup config"
cp -f .config .config.original
if [ ! -z "$PATCH_FILE" ]; then
header
echo "> Apply config patch"
cp $OUTFOLDER/$PATCH_FILE $PATCH_FILE
patch < $OUTFOLDER/$PATCH_FILE
fi
# setup kernel config and generate diff patch from original
# or patch default config with defined patch
header
echo "> Generate config"
echo ">> If you specified patch, you may save/exit only"
echo ">> Feel free to adjust settings too..."
wait
env PATH=$PATH make -j$(nproc) ARCH=arm64 CROSS_COMPILE=aarch64-rpi4-linux-gnu- menuconfig
if [ ! -f ".config" ]; then
header
echo "> !!! No .config (menuconfig) found!"
echo "> !!! Abort!"
exit 1
fi
header
echo "> Create config patch from original for current version"
diff -u .config.original .config > $OUTFOLDER/kernel_config_patch_$VERSION.patch
header
echo "> Disable Debug Info"
wait
env PATH=$PATH scripts/config --disable DEBUG_INFO
header
echo "> Compile kernel"
wait
env PATH=$PATH make -j$(nproc) ARCH=arm64 CROSS_COMPILE=aarch64-rpi4-linux-gnu- Image modules dtbs
header
echo "> Install modules"
env PATH=$PATH make -j$(nproc) ARCH=arm64 CROSS_COMPILE=aarch64-rpi4-linux-gnu- INSTALL_MOD_PATH=../build/mnt/ext4 modules_install
else
KERNEL=kernel8
fi
KERNEL=$KERNEL-$VERSION-v8+
header
echo "> Copy files"
wait
sudo cp arch/arm64/boot/Image ../build/mnt/fat32/$KERNEL.img
sudo cp arch/arm64/boot/dts/broadcom/*.dtb ../build/mnt/fat32/
sudo cp arch/arm64/boot/dts/overlays/*.dtb* ../build/mnt/fat32/overlays/
sudo cp arch/arm64/boot/dts/overlays/README ../build/mnt/fat32/overlays/
header
echo "> Adjust permissions"
wait
cd $OUTFOLDER
sudo chmod -R 0755 build/mnt/fat32/
header
echo "> Copy kernel source"
cd $OUTFOLDER
sudo mkdir -p build/mnt/ext4/opt/build/kernel/$CURRENT/$BRANCH
sudo cp -r $BRANCH build/mnt/ext4/opt/build/kernel/$CURRENT/
header
echo "> Remove symlinks..."
wait
cd $OUTFOLDER
cd build/mnt/ext4/lib/modules/$VERSION-v8+/
sudo rm build
sudo rm source
header
echo "> Create post-install script..."
cd $OUTFOLDER
sudo chown -R 1000:1000 build
cd build/mnt/
rm -f install.sh
touch install.sh
tee -a install.sh <<EOF
#!/bin/bash
clear
echo ">>> Installation of kernel [$KERNEL]"
echo "> Setup permissions (fat32)"
chmod -R 0755 fat32/
echo "> Setup owner (root)"
chown -R root:root fat32/
chown -R root:root ext4/
echo "> Copy files (fat32, ext4)"
cp -rf fat32/. /boot/
cp -rf ext4/lib/. /lib/
cp -rf ext4/opt/. /opt/
echo "> Symlink kernel source to modules ($VERSION-v8+)"
rm -f /lib/modules/$VERSION-v8+/build
rm -f /lib/modules/$VERSION-v8+/source
ln -s /opt/build/kernel/$CURRENT/$BRANCH /lib/modules/$VERSION-v8+/build
ln -s /opt/build/kernel/$CURRENT/$BRANCH /lib/modules/$VERSION-v8+/source
echo "> Add kernel line (as disabled) to config.txt"
echo '#kernel=$KERNEL.img' >> /boot/config.txt
echo "> Done!"
EOF
chmod +x install.sh
header
echo "> Adjust rights"
wait
cd $OUTFOLDER
sudo chown -R root:root build
if [ "$SKIP_BUILD_FINAL" == "0" ]; then
header
echo "> Build archive"
cd $OUTFOLDER/build/mnt/
sudo tar -cf $OUTFOLDER/rpi_kernel_arm64_$VERSION.tar .
sudo chown 1000:1000 $OUTFOLDER/rpi_kernel_arm64_$VERSION.tar
header
echo "> Compress archive"
cd $OUTFOLDER
sudo pigz --force --best rpi_kernel_arm64_$VERSION.tar
sudo chown 1000:1000 rpi_kernel_arm64_$VERSION.tar.gz
fi
header
echo "> Create install script"
rm -f install.sh
touch install.sh
tee -a install.sh <<EOF
#!/bin/bash
clear
echo ">>> Extraction of kernel [$KERNEL]"
echo "> Unzip archive"
pigz -d rpi_kernel_arm64_$VERSION.tar.gz
chown root:root rpi_kernel_arm64_$VERSION.tar
echo "> Untar archive"
tar -xf rpi_kernel_arm64_$VERSION.tar
echo "> Set install script as root/executable"
chown root:root install.sh
chmod +x install.sh
echo "> Proceed to install kernel with: [bash install.sh]"
echo "> Done!"
EOF
chmod +x install.sh
header
echo "> Done!"
exit 0
Procédure
Pour lancer la construction du kernel, il suffit de copier le script dans le répertoire /opt/script/toolchain puis de le lancer :
sudo chmod +x build.sh && sudo chmod +x toolchain.sh && sudo bash build.sh
NB: Dans cette version, cela compilera le dernier kernel en version 6.0 disponible.Pour compiler une autre version, il convient d’éditer le script pour remplacer la valeur MAIN par une autre version… Par exemple 7.0.
Et après ?
Il suffit de copier les fichiers suivant sur votre Pi :
- install.sh
- rpi_kernel_arm64_6.0.0.tar.gz
Vous lancez une première fois install.sh qui va décompresser et préparer dans le répertoire courant les fichiers pour l’installation.
Ensuite, vous relancez install.sh qui là va installer (copier) tous les fichiers nécessaires au kernel au bon endroit.
Pour activer le kernel il vous faut éditer manuellement le fichier /boot/config.txt et ne conserver en non commenté que la ligne kernel= correspondant à la version que vous venez de préparer.
Ensuite… et bien reboot !
Conclusion
Au bout d’un petit moment, dépendant de la puissance de votre machine, vous aurez une archive contenant tout le kernel ARM64 pour un Raspbery Pi 4.