699 lines
16 KiB
Bash
699 lines
16 KiB
Bash
#!/bin/bash
|
|
UPDATED="2024-04-19"
|
|
|
|
DISABLE=1 # disable some options
|
|
ENABLE=1 # enable some options
|
|
SECURED=1 # enable/disable security
|
|
PATCHES=1 # enable/disable patch apply
|
|
UARCH=1 # apply more uarch patch
|
|
CLANG=1 # use Clang compiler (if not, use GCC)
|
|
O3=1 # use -O3 vs -O2 (optimisation)
|
|
ARCH="x86-64-v4" # target architecture (uarch patch)
|
|
CONFIGCLOUD=1 # enable cloud 'from' config
|
|
CONFIGOLD=1 # enable old def config
|
|
CONFIGMOD=0 # enable all mod config
|
|
SCRATCH=0 # perform from scratch (remove preexisting content)
|
|
UNCOMPRESS=1 # perform uncompress if already exist
|
|
CLEANUP=1 # perform folder cleanup
|
|
TESTING=0 # add testing options
|
|
|
|
#
|
|
# Sources:
|
|
# https://github.com/sn99/Optimizing-linux#compiling-your-kernel
|
|
# https://wiki.gentoo.org/wiki/Kernel/Optimization
|
|
#
|
|
|
|
# config-cloud-amd64:
|
|
# https://packages.debian.org/source/sid/linux
|
|
# linux-image-6.7.9-cloud-amd64-unsigned
|
|
# Go down to download section, select amd64 and download deb.
|
|
# Open .deb with archiver, browse to boot folder and grab 'config-6.7.9-cloud-amd64'.
|
|
#
|
|
|
|
# more-uarches-for-kernel.patch:
|
|
# https://github.com/graysky2/kernel_compiler_patch
|
|
# more-uarches-for-kernel.patch : more-uarches-for-kernel-6.8-rc4+.patch
|
|
#
|
|
|
|
#
|
|
# Prerequisites:
|
|
# sudo apt install build-essential fakeroot dpkg-dev perl libssl-dev bc gnupg dirmngr libncurses-dev libelf-dev flex bison lsb-release rsync dwarves clang llvm lld debhelper
|
|
#
|
|
|
|
#
|
|
# In case of usage of uninstall.sh, you must reinstall 'linux-libc-dev' with the version of used kernel
|
|
#
|
|
|
|
#
|
|
# To make a diff of different .config file:
|
|
# diff --side-by-side --suppress-common-lines --ignore-tab-expansion --ignore-trailing-space --ignore-space-change --ignore-blank-lines --text CONFIG1 CONFIG2
|
|
#
|
|
|
|
doBuildSystem() {
|
|
echo "v$UPDATED"
|
|
}
|
|
|
|
# Display introduction
|
|
doIntro() {
|
|
echo
|
|
if [ $TESTING == 1 ]; then
|
|
echo "Debian Kernel Builder: $HOSTNAME [TEST]"
|
|
else
|
|
echo "Debian Kernel Builder: $HOSTNAME"
|
|
fi
|
|
doBuildSystem
|
|
echo
|
|
}
|
|
|
|
# Show date/time header
|
|
doHeader() {
|
|
NOW=$(date +"%Y/%m/%d %H:%M:%S")
|
|
echo "- $NOW"
|
|
echo ""
|
|
}
|
|
|
|
if [ "$(id -u)" != "0" ]; then
|
|
doIntro
|
|
doHeader
|
|
echo
|
|
echo "This script must be run as root" 1>&2
|
|
echo
|
|
exit 1
|
|
fi
|
|
|
|
LOGNAME=kernel
|
|
LOGEXT=log
|
|
LOGFILE=""
|
|
NPROC=$(nproc)
|
|
HOSTNAME=$(hostname)
|
|
SELF=$(realpath $0)
|
|
SCRIPT=$(basename $SELF)
|
|
CWD=$(dirname $SELF)
|
|
CURRENT=$CWD
|
|
CONFIGS=$CURRENT/configs
|
|
PATCHES=$CURRENT/patches
|
|
OPTIONS=$CURRENT/options
|
|
|
|
BRANCH=$1
|
|
BRANCH="${BRANCH:=help}"
|
|
VERSION=$2
|
|
VERSION="${VERSION:=help}"
|
|
STEPS=$3
|
|
STEPS="${STEPS:=help}"
|
|
WORKDIR=""
|
|
|
|
cd $CURRENT
|
|
|
|
# Force sync & flush
|
|
doSync() {
|
|
sync
|
|
echo 3 >/proc/sys/vm/drop_caches
|
|
}
|
|
|
|
# Display header infos
|
|
doHead() {
|
|
doIntro
|
|
doHeader
|
|
}
|
|
|
|
# Display help
|
|
doHelp() {
|
|
doIntro
|
|
doHeader
|
|
|
|
if [ $BRANCH != "help" ]; then
|
|
echo ">>> Unspecified, unknown or invalid option specified!"
|
|
echo
|
|
fi
|
|
echo "Usage: $SCRIPT 'branch' 'version'"
|
|
echo
|
|
echo "branch : Main branch (eg. 6.x)"
|
|
echo "version: Full version tag (eg. 6.6.1)"
|
|
echo
|
|
}
|
|
|
|
# Display step infos
|
|
doEchoStep() {
|
|
NOW=$(date +"%Y/%m/%d %H:%M:%S")
|
|
echo "### $NOW - $1"
|
|
}
|
|
|
|
# Scratch
|
|
doScratch() {
|
|
if [ $SCRATCH == 1 ]; then
|
|
if [ -d $WORKDIR ]; then
|
|
doEchoStep "Scratch: remove existing content"
|
|
rm -rf $WORKDIR
|
|
else
|
|
doEchoStep "Scratch: existing previous content not found"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# Download
|
|
doDownload() {
|
|
if [[ -d $WORKDIR && -f $WORKDIR/linux-$VERSION.tar.xz ]]; then
|
|
doEchoStep "$BRANCH/$VERSION already present (don't download)"
|
|
else
|
|
mkdir -p $WORKDIR
|
|
cd $WORKDIR
|
|
|
|
doEchoStep "Download branch '$BRANCH' version '$VERSION'"
|
|
wget --compression=auto --show-progress --no-verbose --inet4-only https://cdn.kernel.org/pub/linux/kernel/v$BRANCH/linux-$VERSION.tar.sign
|
|
wget --compression=auto --show-progress --no-verbose --inet4-only https://cdn.kernel.org/pub/linux/kernel/v$BRANCH/linux-$VERSION.tar.xz
|
|
doSync
|
|
|
|
result=$?
|
|
if [ ! result==0 ]; then
|
|
echo ">>> Error in download!"
|
|
exit 1
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# Uncompress
|
|
doPerformUncompress() {
|
|
cd $WORKDIR
|
|
doEchoStep "Uncompress"
|
|
|
|
rm -rf linux-$VERSION
|
|
tar -xaf linux-$VERSION.tar.xz
|
|
|
|
result=$?
|
|
if [ ! result==0 ]; then
|
|
echo ">>> Error in uncompress!"
|
|
exit 1
|
|
fi
|
|
}
|
|
doUncompress() {
|
|
if [ -d $WORKDIR ]; then
|
|
if [ $UNCOMPRESS == 1 ]; then
|
|
doPerformUncompress
|
|
else
|
|
doEchoStep "$BRANCH/$VERSION already present (don't uncompress)"
|
|
fi
|
|
else
|
|
doPerformUncompress
|
|
fi
|
|
|
|
doSync
|
|
}
|
|
|
|
# Clean folder
|
|
doCleanup() {
|
|
if [ $CLEANUP == 1 ]; then
|
|
cd $WORKDIR
|
|
doEchoStep "Cleanup"
|
|
|
|
if [ "$CLANG" == "1" ]; then
|
|
make -j${NPROC} LLVM=1 CC="ccache clang" distclean
|
|
else
|
|
make -j${NPROC} CC="ccache gcc" distclean
|
|
fi
|
|
|
|
result=$?
|
|
if [ ! result==0 ]; then
|
|
echo ">>> Error in cleanup!"
|
|
exit 1
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# Copy .config from cloud kernel
|
|
doConfigCloud() {
|
|
if [ $CONFIGCLOUD == 1 ]; then
|
|
cd $WORKDIR
|
|
doEchoStep "Copy cloud kernel .config"
|
|
|
|
if [ -f .config ]; then
|
|
cp .config .config.cloud.before
|
|
fi
|
|
cp $CONFIGS/cloud-amd64 .config
|
|
|
|
result=$?
|
|
if [ ! result==0 ]; then
|
|
echo ">>> Error in cloud kernel .config copy!"
|
|
exit 1
|
|
fi
|
|
|
|
cp .config .config.cloud.after
|
|
fi
|
|
}
|
|
|
|
# Generate .config from old kernel
|
|
doOldOne() {
|
|
if [ $CONFIGOLD == 1 ]; then
|
|
cd $WORKDIR
|
|
doEchoStep "Generate config from old kernel .config"
|
|
|
|
if [ -f .config ]; then
|
|
cp .config .config.old.before
|
|
fi
|
|
if [ "$CLANG" == "1" ]; then
|
|
make -j${NPROC} LLVM=1 CC="ccache clang" olddefconfig
|
|
else
|
|
make -j${NPROC} CC="ccache gcc" olddefconfig
|
|
fi
|
|
|
|
result=$?
|
|
if [ ! result==0 ]; then
|
|
echo ">>> Error in generate .config!"
|
|
exit 1
|
|
fi
|
|
|
|
cp .config .config.old.after
|
|
fi
|
|
}
|
|
|
|
# Define all modules not included in kernel
|
|
doAllMods() {
|
|
if [ $CONFIGMOD == 1 ]; then
|
|
cd $WORKDIR
|
|
doEchoStep "Set all modules to be 'module'"
|
|
|
|
if [ -f .config ]; then
|
|
cp .config .config.mod.before
|
|
fi
|
|
if [ "$CLANG" == "1" ]; then
|
|
make -j${NPROC} LLVM=1 CC="ccache clang" allmodconfig
|
|
else
|
|
make -j${NPROC} CC="ccache gcc" allmodconfig
|
|
fi
|
|
|
|
result=$?
|
|
if [ ! result==0 ]; then
|
|
echo ">>> Error in set all modules not in kernel!"
|
|
exit 1
|
|
fi
|
|
|
|
cp .config .config.mod.after
|
|
fi
|
|
}
|
|
|
|
# Define permissions (user/group) to first user created (default 1000)
|
|
doPermissions() {
|
|
cd $WORKDIR
|
|
doEchoStep "Define user/group"
|
|
|
|
chown -R 1000:1000 $CURRENT/build/$BRANCH/$VERSION/.
|
|
|
|
result=$?
|
|
if [ ! result==0 ]; then
|
|
echo ">>> Error in chown!"
|
|
exit 1
|
|
fi
|
|
|
|
doSync
|
|
}
|
|
|
|
# Strip signature
|
|
doStripSig() {
|
|
cd $WORKDIR
|
|
doEchoStep "Remove signature/keys"
|
|
|
|
if [ -f .config ]; then
|
|
cp .config .config.stripsig.before
|
|
fi
|
|
|
|
./scripts/config --disable MODULE_SIG_ALL
|
|
./scripts/config --set-str CONFIG_MODULE_SIG_KEY ""
|
|
./scripts/config --set-str CONFIG_SYSTEM_TRUSTED_KEY ""
|
|
./scripts/config --set-str CONFIG_SYSTEM_REVOCATION_KEYS ""
|
|
|
|
result=$?
|
|
if [ ! result==0 ]; then
|
|
echo ">>> Error in chown!"
|
|
exit 1
|
|
fi
|
|
|
|
cp .config .config.stripsig.after
|
|
}
|
|
|
|
# Strip debug informations
|
|
doStripDebug() {
|
|
cd $WORKDIR
|
|
doEchoStep "Remove debug informations"
|
|
|
|
if [ -f .config ]; then
|
|
cp .config .config.stripdebug.before
|
|
fi
|
|
|
|
./scripts/config --disable DEBUG_INFO
|
|
./scripts/config --enable DEBUG_INFO_NONE
|
|
|
|
result=$?
|
|
if [ ! result==0 ]; then
|
|
echo ">>> Error in chown!"
|
|
exit 1
|
|
fi
|
|
|
|
cp .config .config.stripdebug.after
|
|
}
|
|
|
|
# Apply more patchs
|
|
doApplyPatches() {
|
|
if [ $PATCHES == 1 ]; then
|
|
|
|
if [ $UARCH == 1 ] && [ -f $PATCHES/more-uarches.patch ]; then
|
|
cd $WORKDIR
|
|
doEchoStep "Apply 'uarches' patch"
|
|
|
|
if [ -f .config ]; then
|
|
cp .config .config.uarches.before
|
|
fi
|
|
patch -p1 <$PATCHES/more-uarches.patch
|
|
|
|
result=$?
|
|
if [ ! result==0 ]; then
|
|
echo ">>> Error in 'uarches'!"
|
|
exit 1
|
|
fi
|
|
|
|
cp .config .config.uarches.after
|
|
fi
|
|
|
|
fi
|
|
}
|
|
|
|
# Exexcute './scripts/config' from file input
|
|
doScriptsConfigFile() {
|
|
SWITCH=$1
|
|
FILE=$2
|
|
|
|
while read -r option; do
|
|
./scripts/config --${SWITCH} $option
|
|
done <"$FILE"
|
|
}
|
|
|
|
# Generate defaults options for this kernel
|
|
doDefaultsDisable() {
|
|
if [ $DISABLE == 1 ]; then
|
|
doEchoStep "Options: disable"
|
|
|
|
if [ -f .config ]; then
|
|
cp .config .config.disable.before
|
|
fi
|
|
doScriptsConfigFile disable $OPTIONS/disable.txt
|
|
|
|
cp .config .config.disable.after
|
|
fi
|
|
}
|
|
doDefaultsEnable() {
|
|
if [ $ENABLE == 1 ]; then
|
|
doEchoStep "Options: enable"
|
|
|
|
if [ -f .config ]; then
|
|
cp .config .config.enable.before
|
|
fi
|
|
if [ "$CLANG" == "1" ]; then
|
|
doScriptsConfigFile enable $OPTIONS/clang.txt
|
|
fi
|
|
doScriptsConfigFile enable $OPTIONS/enable.txt
|
|
|
|
case ${ARCH} in
|
|
"x86-64-v2")
|
|
./scripts/config --enable CONFIG_GENERIC_CPU2
|
|
;;
|
|
"x86-64-v3")
|
|
./scripts/config --enable CONFIG_GENERIC_CPU3
|
|
;;
|
|
"x86-64-v4")
|
|
./scripts/config --enable CONFIG_GENERIC_CPU4
|
|
;;
|
|
esac
|
|
|
|
cp .config .config.enable.after
|
|
fi
|
|
}
|
|
doDefaultMitigations() {
|
|
if [ -f .config ]; then
|
|
cp .config .config.mitigations.before
|
|
fi
|
|
|
|
if [ $SECURED == 0 ]; then
|
|
doEchoStep "Options: secured OFF"
|
|
doScriptsConfigFile disable $OPTIONS/unsecured.txt
|
|
else
|
|
doEchoStep "Options: secured ON"
|
|
doScriptsConfigFile enable $OPTIONS/secured.txt
|
|
fi
|
|
|
|
cp .config .config.mitigations.after
|
|
}
|
|
doDefaultsTesting() {
|
|
if [ $TESTING == 1 ]; then
|
|
doEchoStep "Options: testings activated..."
|
|
|
|
if [ -f .config ]; then
|
|
cp .config .config.testing.before
|
|
fi
|
|
./scripts/config --set-str CONFIG_LOCALVERSION '-test'
|
|
|
|
cp .config .config.testing.after
|
|
fi
|
|
}
|
|
doDefaults() {
|
|
cd $WORKDIR
|
|
|
|
if [ -f .config ]; then
|
|
cp .config .config.default.before
|
|
fi
|
|
|
|
doApplyPatches
|
|
|
|
doEchoStep "Define options"
|
|
if [ "$CLANG" == "1" ]; then
|
|
./scripts/config --set-str CONFIG_LOCALVERSION '-clang'
|
|
else
|
|
./scripts/config --set-str CONFIG_LOCALVERSION '-gcc'
|
|
fi
|
|
|
|
doDefaultsDisable
|
|
doDefaultsEnable
|
|
doDefaultMitigations
|
|
doDefaultsTesting
|
|
|
|
cp .config .config.default.after
|
|
}
|
|
|
|
# Edit .config
|
|
doEditSettings() {
|
|
cd $WORKDIR
|
|
doEchoStep "Settings tuning!"
|
|
|
|
if [ -f .config ]; then
|
|
cp .config .config.edit.before
|
|
fi
|
|
if [ "$CLANG" == "1" ]; then
|
|
make -j${NPROC} LLVM=1 CC="ccache clang" menuconfig
|
|
else
|
|
make -j${NPROC} CC="ccache gcc" menuconfig
|
|
fi
|
|
|
|
result=$?
|
|
if [ ! result==0 ]; then
|
|
echo ">>> Error in settings edit!"
|
|
exit 1
|
|
fi
|
|
|
|
cp .config .config.edit.after
|
|
}
|
|
|
|
doGenerateUninstall() {
|
|
# remove old files
|
|
READY=$CURRENT/build/$BRANCH/$VERSION/ready
|
|
mkdir -p $READY
|
|
rm -rf $READY/*.*
|
|
|
|
if ls $WORKDIR/../*.deb 1>/dev/null 2>&1; then
|
|
|
|
# find .deb packages and generate
|
|
# uninstall commands
|
|
# package name
|
|
PACKAGES=
|
|
TAG="_$VERSION_amd64.deb"
|
|
search_dir=$WORKDIR/../
|
|
|
|
for entry in "$search_dir"/*.deb; do
|
|
name="${entry##*/}"
|
|
pname=${name//$TAG/}
|
|
|
|
if [ ! "$pname" == "linux-libc-dev" ]; then
|
|
PACKAGES="$PACKAGES $pname"
|
|
fi
|
|
|
|
echo "$name" >>$READY/packages.log
|
|
done
|
|
|
|
# move files to destination folder
|
|
mv -f $WORKDIR/../*.deb $READY/
|
|
|
|
# prepare uninstall script
|
|
cat <<-EOF >${READY}/uninstall.sh
|
|
#!/bin/bash
|
|
# ${UPDATED}
|
|
apt remove --purge ${PACKAGES}
|
|
sudo sync
|
|
exit 0
|
|
EOF
|
|
|
|
# generate install script
|
|
cat <<-EOF >${READY}/install.sh
|
|
#!/bin/bash
|
|
# ${UPDATED}
|
|
echo 'blacklist pcspkr' > /etc/modprobe.d/pcspkr.conf
|
|
sudo dpkg -i *.deb
|
|
sudo sync
|
|
exit 0
|
|
EOF
|
|
|
|
# Set execution attribute
|
|
chmod +x $READY/*.sh
|
|
|
|
else
|
|
echo ">>> No packages have been created!"
|
|
exit 1
|
|
fi
|
|
|
|
# setup execution rights on packages
|
|
chown -R root:root $READY/.
|
|
}
|
|
|
|
# Print compilation end informations
|
|
doEnding() {
|
|
clear
|
|
doHead
|
|
|
|
doEchoStep "Generated packages :"
|
|
echo
|
|
cat $CURRENT/build/$BRANCH/$VERSION/ready/packages.log
|
|
echo
|
|
echo "In folder: $CURRENT/build/$BRANCH/$VERSION/ready"
|
|
|
|
doSync
|
|
}
|
|
|
|
# Perform effective compilation
|
|
doCompile() {
|
|
cd $WORKDIR
|
|
|
|
doStripSig
|
|
doStripDebug
|
|
|
|
if [ $O3 == 1 ]; then
|
|
GCCO="3"
|
|
else
|
|
GCCO="2"
|
|
fi
|
|
|
|
doEchoStep "Compilation time... Be patient!"
|
|
|
|
if [ "$CLANG" == "1" ]; then
|
|
doEchoStep "Compiler: CLANG"
|
|
else
|
|
doEchoStep "Compiler: GCC"
|
|
fi
|
|
|
|
export MAKEFLAGS="-j$((NPROC + 1)) -l${NPROC} -Wno-error"
|
|
export CFLAGS="-march=${ARCH} -O${GCCO} -flto -pipe -msse -msse2 -msse3 -mmmx"
|
|
export CXXFLAGS="${CFLAGS}"
|
|
export KCFLAGS="-march=${ARCH} -O${GCCO}"
|
|
export KCPPFLAGS="${KCFLAGS}"
|
|
|
|
set CONFIG_SITE=/etc/dpkg-cross/cross-config.amd64
|
|
set DEB_BUILD_OPTIONS=nocheck
|
|
|
|
doEchoStep "MAKEFLAGS: $MAKEFLAGS"
|
|
doEchoStep "CFLAGS: $CFLAGS"
|
|
doEchoStep "CXXFLAGS: $CXXFLAGS"
|
|
doEchoStep "KCFLAGS: $KCFLAGS"
|
|
doEchoStep "KCPPFLAGS: $KCPPFLAGS"
|
|
|
|
doEchoStep "make bindeb-pkg"
|
|
|
|
if [ "$CLANG" == "1" ]; then
|
|
make \
|
|
-j${NPROC} \
|
|
LLVM=1 LLVM_IAS=1 \
|
|
CC='ccache clang' \
|
|
HOSTCC='ccache clang' \
|
|
bindeb-pkg \
|
|
LOCALVERSION=-"$(dpkg --print-architecture)" \
|
|
KDEB_PKGVERSION="$(make kernelversion)"
|
|
else
|
|
make \
|
|
-j${NPROC} \
|
|
CC='ccache gcc' \
|
|
bindeb-pkg \
|
|
LOCALVERSION=-"$(dpkg --print-architecture)" \
|
|
KDEB_PKGVERSION="$(make kernelversion)"
|
|
fi
|
|
|
|
result=$?
|
|
doEchoStep "make bindeb-pkg: $result"
|
|
if [ ! result==0 ]; then
|
|
echo ">>> Error in 'make bindeb-pkg'!"
|
|
exit 1
|
|
fi
|
|
|
|
doGenerateUninstall
|
|
doEnding
|
|
|
|
doSync
|
|
}
|
|
|
|
# Proceed for Kernel build
|
|
doKernel() {
|
|
WORKDIR=$CURRENT/build/$BRANCH/$VERSION
|
|
|
|
doScratch
|
|
if [ ! -d $WORKDIR ]; then
|
|
mkdir -p $WORKDIR
|
|
fi
|
|
|
|
LOGFILE=$WORKDIR/$LOGNAME.$LOGEXT
|
|
if [ -f $LOGFILE ]; then
|
|
rm -rf $LOGFILE
|
|
fi
|
|
touch $LOGFILE
|
|
|
|
if [ "$STEPS" != "compile" ]; then
|
|
doDownload > >(tee -a $LOGFILE) 2>&1
|
|
doUncompress > >(tee -a $LOGFILE) 2>&1
|
|
fi
|
|
|
|
WORKDIR=$WORKDIR/linux-$VERSION
|
|
|
|
doCleanup > >(tee -a $LOGFILE) 2>&1
|
|
doConfigCloud > >(tee -a $LOGFILE) 2>&1
|
|
doOldOne > >(tee -a $LOGFILE) 2>&1
|
|
doAllMods > >(tee -a $LOGFILE) 2>&1
|
|
doDefaults > >(tee -a $LOGFILE) 2>&1
|
|
doPermissions > >(tee -a $LOGFILE) 2>&1
|
|
|
|
doEditSettings
|
|
while true; do
|
|
read -p "Do you wish to run compile? " yn
|
|
case $yn in
|
|
[Yy]*)
|
|
doCompile > >(tee -a $LOGFILE) 2>&1
|
|
break
|
|
;;
|
|
[Nn]*) exit ;;
|
|
*) echo "Please answer yes or no." ;;
|
|
esac
|
|
done
|
|
}
|
|
|
|
# Entrypoint of operations
|
|
if [[ -z $BRANCH || "$BRANCH" == "help" || -z $VERSION || "$VERSION" == "help" ]]; then
|
|
doHelp
|
|
exit 1
|
|
else
|
|
clear
|
|
doHead
|
|
doKernel
|
|
fi
|
|
|
|
exit 0
|