Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save meberlein/98eb41f2acf1f25688a2ca03a4c6fad8 to your computer and use it in GitHub Desktop.
Save meberlein/98eb41f2acf1f25688a2ca03a4c6fad8 to your computer and use it in GitHub Desktop.
Download, patch, compile and install the newest stable Linux kernel with the ACS override patch (Ubuntu / Debian)
#!/bin/bash
function install_dependencies() {
echo "Installing dependencies..."
sudo apt -qq update
sudo apt -qq install -y curl git wget
sudo apt -qq install -y bison flex kernel-package libelf-dev libssl-dev
}
function init() {
echo "Get the newest version of the script here: https://gist.github.com/mdPlusPlus/031ec2dac2295c9aaf1fc0b0e808e21a"
echo "Initializing..."
kernel_config=$(ls /boot/config-* | grep generic | sort -Vr | head -n 1)
grub_config="/etc/default/grub"
current_dir=$(pwd)
working_dir=$(mktemp -d)
cd "${working_dir}" || exit
install_dependencies
}
function get_newest_versions() {
echo "Retrieving newest version information..."
stable_releases_3x_url="https://mirrors.edge.kernel.org/pub/linux/kernel/v3.x/"
stable_releases_4x_url="https://mirrors.edge.kernel.org/pub/linux/kernel/v4.x/"
stable_releases_5x_url="https://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/"
stable_releases_3x_html=$(curl -s "${stable_releases_3x_url}")
stable_releases_4x_html=$(curl -s "${stable_releases_4x_url}")
stable_releases_5x_html=$(curl -s "${stable_releases_5x_url}")
stable_releases_combined_html="${stable_releases_3x_html}${stable_releases_4x_html}${stable_releases_5x_html}"
stable_version=$(echo "${stable_releases_combined_html}" | grep -E -o 'linux-([0-9]{1,}\.)+[0-9]{1,}' | sort -Vru | head -n 1 | cut -d '-' -f 2)
mainline_link=$(curl -s https://www.kernel.org/ | grep https://git.kernel.org/torvalds/t/linux- | grep -Po '(?<=href=")[^"]*')
if ! [ -z "${mainline_link}" ]
then
mainline_version=$(echo "${mainline_link}" | cut -d '-' -f 2,3 | cut -d '.' -f 1,2)
else
mainline_version="unavailable"
fi
repo_pkg=$(apt search 'linux-source-' | grep 'linux-source' | cut -d '/' -f 1 | awk -F- 'NF<=3' | sort -Vr | head -n 1)
#repo_version=$(echo "${repo_pkg}" | cut -d '-' -f 3)
repo_version=$(apt search 'linux-source-' | grep 'linux-source' | sort -Vr | head -n 1 | cut -d ' ' -f 2)
}
function stable_or_mainline_or_repo() {
get_newest_versions
echo "Newest stable version is: ${stable_version}"
echo "Mainline version is: ${mainline_version}"
echo "Repository version is: ${repo_version}"
echo -n "Do you want to get a [s]table, the newest [m]ainline release candidate or the newest kernel from your [r]epositories? [S/m/r] "
read -r s_or_m_or_r
echo -n "Do you want to apply the acs override patch? Kernels below 4.10 are not supported. [Y/n] "
read -r acso
echo -n "Do you want to apply the experimental AMD AGESA patch to fix VFIO setups on AGESA 0.0.7.2 and newer? [y/N] "
read -r agesa
echo -n "Do you want to apply the experimental AMD Vega PCI reset patch? [y/N] "
read -r vega
echo -n "Do you want to install the kernel and its headers after compilation? [Y/n] "
read -r install
if [[ -z "${install}" || "${install}" == "y" || "${install}" == "Y" ]]
then
echo -n "Do you want to make this kernel the new default? [Y/n] "
read -r default
fi
if [[ -z "${s_or_m_or_r}" || "${s_or_m_or_r}" == "s" || "${s_or_m_or_r}" == "S" ]]
then
stable_preparations
else
if [[ "${s_or_m_or_r}" == "m" || "${s_or_m_or_r}" == "M" ]]
then
if [ "${mainline_version}" == "unavailable" ]
then
echo "Mainline version currently unavailable. Exiting."
exit
else
mainline_preparations
fi
else
if [[ "${s_or_m_or_r}" == "r" || "${s_or_m_or_r}" == "R" ]]
then
repo_preparations
else
echo "Not a valid option. Exiting."
exit
fi
fi
fi
}
function try_acso_patch() {
acso_patch_5_6_12="https://gitlab.com/Queuecumber/linux-acs-override/raw/master/workspaces/5.6.12/acso.patch"
acso_patch_5_4="https://gitlab.com/Queuecumber/linux-acs-override/raw/master/workspaces/5.4/acso.patch"
acso_patch_4_18="https://gitlab.com/Queuecumber/linux-acs-override/raw/master/workspaces/4.18/acso.patch"
acso_patch_4_17="https://gitlab.com/Queuecumber/linux-acs-override/raw/master/workspaces/4.17/acso.patch"
acso_patch_4_14="https://gitlab.com/Queuecumber/linux-acs-override/raw/master/workspaces/4.14/acso.patch"
acso_patch_4_10="https://gitlab.com/Queuecumber/linux-acs-override/raw/master/workspaces/4.10/acso.patch"
acso_patch_4_18_ubuntu="https://gist.github.com/mdPlusPlus/bb3df6248ffc7c6b3772ae0901659966/raw/acso_4_18_ubuntu.patch"
echo "Trying to apply acs override patch for 5.6.12+."
wget -O ../acso_5_6_12.patch "${acso_patch_5_6_12}"
if $(git apply --check ../acso_5_6_12.patch)
then
echo "Applying acs override patch for 5.6_12+."
git apply ../acso_5_6_12.patch
else
echo "Trying to apply acs override patch for 5.4+."
wget -O ../acso_5_4.patch "${acso_patch_5_4}"
if $(git apply --check ../acso_5_4.patch)
then
echo "Applying acs override patch for 5.4+."
git apply ../acso_5_4.patch
else
echo "Trying to apply acs override patch for 4.18+."
wget -O ../acso_4_18.patch "${acso_patch_4_18}"
if $(git apply --check ../acso_4_18.patch)
then
echo "Applying acs override patch for 4.18+."
git apply ../acso_4_18.patch
else
echo "Trying to apply acs override patch for 4.17+."
wget -O ../acso_4_17.patch "${acso_patch_4_17}"
if $(git apply --check ../acso_4_17.patch)
then
echo "Applying acs override patch for 4.17+."
git apply ../acso_4_17.patch
else
echo "Trying to apply acs override patch for 4.14+."
wget -O ../acso_4_14.patch "${acso_patch_4_14}"
if $(git apply --check ../acso_4_14.patch)
then
echo "Applying acs override patch for 4.14+."
git apply ../acso_4_14.patch
else
echo "Trying to apply acs override patch for 4.10+."
wget -O ../acso_4_10.patch "${acso_patch_4_10}"
if $(git apply --check ../acso_4_10.patch)
then
echo "Applying acs override patch for 4.10+."
git apply ../acso_4_10.patch
else
echo "Last resort: Trying to apply acs override patch for Ubuntu repository kernel source."
wget -O ../acso_4_18_ubuntu.patch "${acso_patch_4_18_ubuntu}"
if $(git apply --check ../acso_4_18_ubuntu.patch)
then
echo "Applying acs override patch for Ubuntu repository kernel source."
git apply ../acso_4_18_ubuntu.patch
else
echo "[ERROR]: Failed to apply acs override patch. Exiting."
exit
fi
rm -f ../acso_4_18_ubuntu.patch
fi
rm -f ../acso_4_10.patch
fi
rm -f ../acso_4_14.patch
fi
rm -f ../acso_4_17.patch
fi
rm -f ../acso_4_18.patch
fi
rm -f ../acso_5_4.patch
fi
rm -f ../acso_5_6_12.patch
kernel_localversion+="-acso"
}
function try_agesa_patch() {
##by reddit user https://www.reddit.com/user/hansmoman/
##https://www.reddit.com/r/VFIO/comments/bqeixd/apparently_the_latest_bios_on_asrockmsi_boards/eo4neta
agesa_patch="https://clbin.com/VCiYJ"
agesa_patch_filename="agesa.patch"
echo "Trying to apply AMD AGESA patch."
wget -O ../${agesa_patch_filename} "${agesa_patch}"
if $(git apply --check ../${agesa_patch_filename})
then
echo "Applying AMD AGESA patch."
git apply ../${agesa_patch_filename}
else
echo "[ERROR]: Failed to apply AMD AGESA patch. Exiting."
exit
fi
rm -f ../${agesa_patch_filename}
kernel_localversion+="-agesa"
}
function try_vega_patch() {
##Original by github user https://gist.github.com/numinit
vega_patch_new="https://gist.github.com/mdPlusPlus/1754d82b53269ead770133829874fbfd/raw/"
vega_patch="https://gist.github.com/numinit/1bbabff521e0451e5470d740e0eb82fd/raw"
vega_patch_filename="fix-vega-reset.patch"
echo "Trying to apply AMD Vega reset patch."
wget -O ../${vega_patch_filename} "${vega_patch_new}"
if $(git apply --check ../${vega_patch_filename})
then
echo "Applying AMD Vega reset patch."
git apply ../${vega_patch_filename}
else
rm -f ../${vega_patch_filename}
wget -O ../${vega_patch_filename} "${vega_patch}"
if $(git apply --check ../${vega_patch_filename})
then
echo "Applying AMD Vega reset patch."
git apply ../${vega_patch_filename}
else
echo "[ERROR]: Failed to apply AMD Vega reset patch. Exiting."
exit
fi
fi
rm -f ../${vega_patch_filename}
kernel_localversion+="-vega"
}
function stable_preparations() {
echo "The newest available stable kernel version is ${stable_version}. Kernels below 4.10 are not supported."
echo -n "Which version do you want to download? [${stable_version}] "
read -r user_version
if ! [ -z "${user_version}" ]
then
stable_version="${user_version}"
fi
kernel_version="${stable_version}"
kernel_name="linux-${kernel_version}"
##Test whether the version string starts with 3, 4, or 5 and sets the URL accordingly
if [[ $stable_version == 5* ]]
then
stable_link="${stable_releases_5x_url}linux-${stable_version}.tar.xz"
else
if [[ $stable_version == 4* ]]
then
stable_link="${stable_releases_4x_url}linux-${stable_version}.tar.xz"
else
if [[ $stable_version == 3* ]]
then
stable_link="${stable_releases_3x_url}linux-${stable_version}.tar.xz"
else
echo "${stable_version} is not a vaild version number. Exiting."
exit
fi
fi
fi
wget "${stable_link}"
tar xf "${kernel_name}.tar.xz"
cd "${kernel_name}" || exit
independent_code
}
function mainline_preparations() {
kernel_version="${mainline_version}"
kernel_name="linux-${kernel_version}"
wget "${mainline_link}"
tar xf "${kernel_name}.tar.gz"
cd "${kernel_name}" || exit
independent_code
}
function repo_preparations() {
kernel_name="${repo_pkg}"
sudo apt install "${repo_pkg}"
tar xf "/usr/src/${kernel_name}.tar.bz2"
cd "${kernel_name}" || exit
makefile_version=$(grep "^VERSION" Makefile | tr -d '[:space:]' | cut -d '=' -f 2)
makefile_patchlevel=$(grep "^PATCHLEVEL" Makefile| tr -d '[:space:]' | cut -d '=' -f 2)
makefile_sublevel=$(grep "^SUBLEVEL" Makefile | tr -d '[:space:]' | cut -d '=' -f 2)
#makefile_extraversion=$(grep "^EXTRAVERSION" Makefile| tr -d '[:space:]' | cut -d '=' -f 2)
if ! [ -z "${makefile_version}" ]
then
kernel_version="${makefile_version}"
if ! [ -z "${makefile_patchlevel}" ]
then
kernel_version="${makefile_version}.${makefile_patchlevel}"
if ! [ -z "${makefile_sublevel}" ]
then
kernel_version="${makefile_version}.${makefile_patchlevel}.${makefile_sublevel}"
fi
fi
fi
##linux-hwe (5.0.0-25.26~18.04.1) bionic; urgency=medium
##->
##5.0.0-25.26~18.04.1
#kernel_version=$(head -n 1 debian/changelog | cut -d '(' -f 2 | cut -d ')' -f 1)
##This somehow comes out empty when run in the script, but is successful when issued manually
independent_code
}
function independent_code() {
kernel_localversion=""
if [[ -z "${acso}" || ( "${acso}" != "n" && "${acso}" != "N" ) ]]
then
try_acso_patch
fi
if [[ "${agesa}" == "y" || "${agesa}" == "Y" ]]
then
try_agesa_patch
fi
if [[ "${vega}" == "y" || "${vega}" == "Y" ]]
then
try_vega_patch
fi
##temporary
#fix_steam
cp "${kernel_config}" .config
yes '' | make oldconfig
##set xhci_hcd to load as a module instead of including it directly into the kernel
##results in vfio_pci being able to grab usb controllers before xhci_hcd is able to
sed -i -e 's/^CONFIG_USB_XHCI_HCD=y/CONFIG_USB_XHCI_HCD=m/g' .config
##Enable AMD's HSA driver for ROCm support. Thanks at https://github.com/jfturcot
sed -i -e 's/^#\ CONFIG_HSA_AMD\ is\ not\ set/CONFIG_HSA_AMD=y/g' .config
##Disable debug builds
sed -i -e 's/^CONFIG_DEBUG_INFO=y/CONFIG_DEBUG_INFO=n/g' .config
sed -i -e 's/^CONFIG_DEBUG_KERNEL=y/CONFIG_DEBUG_KERNEL=n/g' .config
##check for versions containing only a single dot instead of two
##but only when not choosing the repo source
if [[ "${s_or_m_or_r}" != "r" && "${s_or_m_or_r}" != "R" ]]
then
dots=$(echo "${kernel_version}" | awk -F "." '{print NF-1}')
dashes=$(echo "${kernel_version}" | awk -F "-" '{print NF-1}')
if [ "${dots}" -lt 2 ]
then
if [ "${dashes}" -lt 1 ]
then
##5.1 -> 5.1.0
kernel_version="${kernel_version}.0"
else
##5.1-rc1 -> 5.1.0-rc1
kernel_version="$(echo "${kernel_version}" | sed 's/-/.0-/')"
fi
kernel_name="linux-${kernel_version}"
fi
fi
make clean
make -j "$(nproc)" bindeb-pkg LOCALVERSION="${kernel_localversion}" || exit
if [[ -z "${install}" || "${install}" == "y" || "${install}" == "Y" ]]
then
sudo dpkg -i ../linux-image-${kernel_version}${kernel_localversion}*.deb ../linux-headers-${kernel_version}${kernel_localversion}*.deb
if [[ -z "${default}" || "${default}" == "y" || "${default}" == "Y" ]]
then
if [ "$(lsb_release -s -d | cut -d ' ' -f 1)" == "Ubuntu" ]
then
##removing previous commented line
sudo sed -i -e 's/^#GRUB_DEFAULT=.*//g' "${grub_config}"
##commenting current line
sudo sed -i 's/^GRUB_DEFAULT=/#GRUB_DEFAULT=/' "${grub_config}"
##adding line
## TODO multilanguage! only works for en-US (and other en-*) right now!
grub_line="GRUB_DEFAULT=\"Advanced options for Ubuntu>Ubuntu, with Linux ${kernel_version}${kernel_localversion}\""
sudo sed -i -e "s/^#GRUB_DEFAULT=.*/\0\n${grub_line}/" "${grub_config}"
sudo update-grub
fi
fi
fi
cd "${current_dir}" || exit
source_dir='/usr/src/kernels/'${kernel_version}${kernel_localversion}
sudo mkdir -p "/usr/src/kernels/"${kernel_version}${kernel_localversion}
sudo cp -a "${working_dir}/${kernel_name}/." "${source_dir}"
rm -rf "${working_dir}"
}
##actual logic
init
stable_or_mainline_or_repo
@meberlein
Copy link
Author

Code forked to support the following:
Copying the working directory to /usr/src/kernels/ so that the NVIDIA driver can be compiled against the latest kernel as there are some incompatibilities with kernel 5.8. Install command for latest NVIDIA drivers becomes NVIDIA-Linux-x86_64-450.66.run --kernel-source-path=/usr/src/kernels/5.8.7-acso/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment