diff options
author | Andrew Ammerlaan <andrewammerlaan@gentoo.org> | 2024-06-27 12:26:35 +0200 |
---|---|---|
committer | Andrew Ammerlaan <andrewammerlaan@gentoo.org> | 2024-06-28 15:35:35 +0200 |
commit | afeaf7f98275b3d5d7b1902bd22adc93593ba32d (patch) | |
tree | 55fb00b3b24e8adb19c024c9a7f27c98ac8ab831 /sys-kernel | |
parent | sys-firmware/intel-microcode: add ucode image generator hooks (diff) | |
download | gentoo-afeaf7f98275b3d5d7b1902bd22adc93593ba32d.tar.gz gentoo-afeaf7f98275b3d5d7b1902bd22adc93593ba32d.tar.bz2 gentoo-afeaf7f98275b3d5d7b1902bd22adc93593ba32d.zip |
sys-kernel/linux-firmware: add ucode image generator hooks
This creates a AMD microcode image when installing the kernel and when
installkernel/kernel-install is configured to use an initramfs generator other
then dracut. Dracut bundles the microcode in the image it generates, many
other initramfs generators do not and we want these users to also get the
latest CPU microcode.
installkernel-gentoo.git has recently gained support for handling these ucode
images and passing them on to bootloaders and UKI generators.
Note that this should be here and not in installkernel-gentoo.git because we
only want to install this when the initramfs flag is enabled to avoid the
situation where users who don't want an ucode.img get one anyway.
To avoid code-duplication we add and install a little helper script that we can
call both from the ebuild and from the hooks.
Co-authored-by: Zen <z@pyl.onl>
Signed-off-by: Andrew Ammerlaan <andrewammerlaan@gentoo.org>
Closes: https://github.com/gentoo/gentoo/pull/37320
Signed-off-by: Andrew Ammerlaan <andrewammerlaan@gentoo.org>
Diffstat (limited to 'sys-kernel')
-rw-r--r-- | sys-kernel/linux-firmware/files/35-amd-microcode-systemd.install | 35 | ||||
-rw-r--r-- | sys-kernel/linux-firmware/files/35-amd-microcode.install | 39 | ||||
-rw-r--r-- | sys-kernel/linux-firmware/files/linux-firmware-make-amd-ucode-img.bash | 79 | ||||
-rw-r--r-- | sys-kernel/linux-firmware/linux-firmware-20240610-r1.ebuild (renamed from sys-kernel/linux-firmware/linux-firmware-20240610.ebuild) | 33 | ||||
-rw-r--r-- | sys-kernel/linux-firmware/linux-firmware-99999999.ebuild | 32 |
5 files changed, 181 insertions, 37 deletions
diff --git a/sys-kernel/linux-firmware/files/35-amd-microcode-systemd.install b/sys-kernel/linux-firmware/files/35-amd-microcode-systemd.install new file mode 100644 index 000000000000..edafb4d63035 --- /dev/null +++ b/sys-kernel/linux-firmware/files/35-amd-microcode-systemd.install @@ -0,0 +1,35 @@ +#!/usr/bin/env bash + +# Copyright 2024 Gentoo Authors +# This script is installed by sys-kernel/linux-firmware, it is executed by +# systemd's kernel-install, NOT by the traditional installkernel. I.e. this +# plugin is run when the systemd USE flag is enabled or +# SYSTEMD_KERNEL_INSTALL=1 is set in the environment. + +COMMAND="${1}" + +if [[ ${COMMAND} != add ]]; then + exit 0 +fi + +if [[ ${KERNEL_INSTALL_INITRD_GENERATOR} == dracut ]]; then + # Dracut bundles microcode in its initramfs images + [[ ${KERNEL_INSTALL_VERBOSE} == 1 ]] && echo \ + "initrd_generator=${KERNEL_INSTALL_INITRD_GENERATOR} bundles CPU microcode, nothing to do here." + exit 0 +fi + +# do nothing if somehow make-amd-ucode-img is not installed +if ! command -v make-amd-ucode-img >/dev/null; then + [[ ${KERNEL_INSTALL_VERBOSE} == 1 ]] && echo \ + "make-amd-ucode-img command not available" + exit 1 +fi + +[[ ${KERNEL_INSTALL_VERBOSE} == 1 ]] && echo \ + "Generating AMD CPU Microcode early initramfs image..." + +make-amd-ucode-img \ + ${KERNEL_INSTALL_STAGING_AREA}/microcode-amd \ + /lib/firmware/amd-ucode || + { echo "make-amd-ucode-img failed" && exit 1; } diff --git a/sys-kernel/linux-firmware/files/35-amd-microcode.install b/sys-kernel/linux-firmware/files/35-amd-microcode.install new file mode 100644 index 000000000000..185e57be0dae --- /dev/null +++ b/sys-kernel/linux-firmware/files/35-amd-microcode.install @@ -0,0 +1,39 @@ +#!/usr/bin/env bash + +# Copyright 2024 Gentoo Authors +# This script is installed by sys-kernel/linux-firmware, it is executed by +# the traditional installkernel, NOT by systemd's kernel-install. I.e. this +# plugin is run when the systemd USE flag is disabled or +# SYSTEMD_KERNEL_INSTALL=0 is set in the environment. + +# familiar helpers, we intentionally don't use Gentoo functions.sh +die() { + echo -e " ${NOCOLOR-\e[1;31m*\e[0m }${*}" >&2 + exit 1 +} + +einfo() { + echo -e " ${NOCOLOR-\e[1;32m*\e[0m }${*}" >&2 +} + +main() { + # re-define for subst to work + [[ -n ${NOCOLOR+yes} ]] && NOCOLOR= + + if [[ ${INSTALLKERNEL_INITRD_GENERATOR} == dracut ]]; then + # Dracut bundles microcode in its initramfs images + echo "initrd_generator=${INSTALLKERNEL_INITRD_GENERATOR} bundles CPU microcode, nothing to do here." + exit 0 + fi + + # do nothing if somehow make-amd-ucode-img is not installed + [[ -x $(command -v make-amd-ucode-img) ]] || die "make-amd-ucode-img command not available" + + [[ ${EUID} -eq 0 ]] || die "Please run this script as root" + + einfo "Generating AMD CPU Microcode early initramfs image..." + make-amd-ucode-img /boot/amd-uc.img /lib/firmware/amd-ucode || + die "make-amd-ucode-img failed" +} + +main diff --git a/sys-kernel/linux-firmware/files/linux-firmware-make-amd-ucode-img.bash b/sys-kernel/linux-firmware/files/linux-firmware-make-amd-ucode-img.bash new file mode 100644 index 000000000000..5fac567e063d --- /dev/null +++ b/sys-kernel/linux-firmware/files/linux-firmware-make-amd-ucode-img.bash @@ -0,0 +1,79 @@ +#!/usr/bin/env bash + +# Copyright 2024 Gentoo Authors + +our_name=${0} +out=${1} +in=${2} + +# familiar helpers, we intentionally don't use Gentoo functions.sh +die() { + echo -e " ${NOCOLOR-\e[1;31m*\e[0m }${*}" >&2 + exit 1 +} + +einfo() { + echo -e " ${NOCOLOR-\e[1;32m*\e[0m }${*}" >&2 +} + +main() { + # re-define for subst to work + [[ -n ${NOCOLOR+yes} ]] && NOCOLOR= + + + # Set the output file to arg 1 if it's not a directory. + # If it's a directory, set the out file to the directory with the default name. + # If it's a relative filename, include it in the variable. + local ucode_file=${out:-"/boot/amd-uc.img"} + if [[ -d ${ucode_file} ]]; then + ucode_file="${ucode_file}/amd-uc.img" + einfo "Output file is a directory. Using default name: ${ucode_file}" + elif [[ ${ucode_file} != /* ]]; then + ucode_file="$(pwd)/${ucode_file}" + einfo "Output file is a relative path. Using full path: ${ucode_file}" + elif [[ -z ${ucode_file} ]]; then + einfo "Usage: ${our_name} <output image> <microcode directory>" + die "No output file specified" + fi + + # Only AMD microcode is in the linux-firmmware package + local ucode_dir=${in:-"/lib/firmware/amd-ucode"} + if [[ ! -d ${ucode_dir} ]]; then + einfo "Usage: ${our_name} <output image> <microcode directory>" + die "AMD microcode directory does not exist: ${ucode_dir}" + fi + + # Make the tmp dir for the microcode archive + local ucode_tmp_dir="$(mktemp -d)" || die "Failed to create temporary directory" + einfo "Created temporary directory: ${ucode_tmp_dir}" + local ucode_bin_dir="${ucode_tmp_dir}/kernel/x86/microcode" + local ucode_bin_file="${ucode_bin_dir}/AuthenticAMD.bin" + + # Write "1" to the early_cpio flag file + echo 1 > "${ucode_tmp_dir}/early_cpio" || die + + # Make the directory for the microcode bin files + mkdir -p "${ucode_bin_dir}" || die "Failed to create microcode bin directory: ${ucode_bin_dir}" + + # Concatenate all microcode bin files into a single file + cat "${ucode_dir}"/*.bin > "${ucode_bin_file}" || die "Failed to concatenate microcode files into: ${ucode_bin_file}" + + # Check that the concatenated file is not empty + [[ -s "${ucode_bin_file}" ]] || die "Empty microcode file: ${ucode_bin_file}" + + pushd "${ucode_tmp_dir}" &> /dev/null || die + # Create the cpio archive + find . -print0 | cpio --quiet --null -o -H newc -R 0:0 > "${ucode_file}" || die "Failed to create microcode archive in: ${ucode_file}" + popd &> /dev/null || die + + # Check that the cpio archive is not empty + [[ -s "${ucode_file}" ]] || die "Empty microcode archive at: ${ucode_file}" + + einfo "Created microcode archive at: ${ucode_file}" + # Clean up the tmp dir + rm -r "${ucode_tmp_dir}" || die "Failed to remove temporary directory: ${ucode_tmp_dir}" + einfo "Cleaned up temporary directory: ${ucode_tmp_dir}" +} + +main + diff --git a/sys-kernel/linux-firmware/linux-firmware-20240610.ebuild b/sys-kernel/linux-firmware/linux-firmware-20240610-r1.ebuild index 1bb6954d00c8..32bd327957ea 100644 --- a/sys-kernel/linux-firmware/linux-firmware-20240610.ebuild +++ b/sys-kernel/linux-firmware/linux-firmware-20240610-r1.ebuild @@ -102,7 +102,6 @@ src_unpack() { } src_prepare() { - default find . -type f -not -perm 0644 -print0 \ @@ -110,27 +109,12 @@ src_prepare() { || die chmod +x copy-firmware.sh || die + cp "${FILESDIR}/${PN}-make-amd-ucode-img.bash" "${T}/make-amd-ucode-img" || die + chmod +x "${T}/make-amd-ucode-img" || die if use initramfs && ! use dist-kernel; then if [[ -d "${S}/amd-ucode" ]]; then - local UCODETMP="${T}/ucode_tmp" - local UCODEDIR="${UCODETMP}/kernel/x86/microcode" - mkdir -p "${UCODEDIR}" || die - echo 1 > "${UCODETMP}/early_cpio" - - local amd_ucode_file="${UCODEDIR}/AuthenticAMD.bin" - cat "${S}"/amd-ucode/*.bin > "${amd_ucode_file}" || die "Failed to concat amd cpu ucode" - - if [[ ! -s "${amd_ucode_file}" ]]; then - die "Sanity check failed: '${amd_ucode_file}' is empty!" - fi - - pushd "${UCODETMP}" &>/dev/null || die - find . -print0 | cpio --quiet --null -o -H newc -R 0:0 > "${S}"/amd-uc.img - popd &>/dev/null || die - if [[ ! -s "${S}/amd-uc.img" ]]; then - die "Failed to create '${S}/amd-uc.img'!" - fi + "${T}/make-amd-ucode-img" "${S}" "${S}/amd-ucode" || die else # If this will ever happen something has changed which # must be reviewed @@ -357,6 +341,17 @@ src_install() { insinto /usr/lib/dracut/dracut.conf.d newins - 10-${PN}.conf <<<"early_microcode=$(usex initramfs)" ) + if use initramfs; then + # Install installkernel/kernel-install hooks for non-dracut initramfs + # generators that don't bundled the microcode + dobin "${T}/make-amd-ucode-img" + ( + exeinto /usr/lib/kernel/preinst.d + doexe "${FILESDIR}/35-amd-microcode.install" + exeinto /usr/lib/kernel/install.d + doexe "${FILESDIR}/35-amd-microcode-systemd.install" + ) + fi if use initramfs && ! use dist-kernel; then insinto /boot diff --git a/sys-kernel/linux-firmware/linux-firmware-99999999.ebuild b/sys-kernel/linux-firmware/linux-firmware-99999999.ebuild index dc02d051d7ea..26c21e80395e 100644 --- a/sys-kernel/linux-firmware/linux-firmware-99999999.ebuild +++ b/sys-kernel/linux-firmware/linux-firmware-99999999.ebuild @@ -107,27 +107,12 @@ src_prepare() { || die chmod +x copy-firmware.sh || die + cp "${FILESDIR}/${PN}-make-amd-ucode-img.bash" "${T}/make-amd-ucode-img" || die + chmod +x "${T}/make-amd-ucode-img" || die if use initramfs && ! use dist-kernel; then if [[ -d "${S}/amd-ucode" ]]; then - local UCODETMP="${T}/ucode_tmp" - local UCODEDIR="${UCODETMP}/kernel/x86/microcode" - mkdir -p "${UCODEDIR}" || die - echo 1 > "${UCODETMP}/early_cpio" - - local amd_ucode_file="${UCODEDIR}/AuthenticAMD.bin" - cat "${S}"/amd-ucode/*.bin > "${amd_ucode_file}" || die "Failed to concat amd cpu ucode" - - if [[ ! -s "${amd_ucode_file}" ]]; then - die "Sanity check failed: '${amd_ucode_file}' is empty!" - fi - - pushd "${UCODETMP}" &>/dev/null || die - find . -print0 | cpio --quiet --null -o -H newc -R 0:0 > "${S}"/amd-uc.img - popd &>/dev/null || die - if [[ ! -s "${S}/amd-uc.img" ]]; then - die "Failed to create '${S}/amd-uc.img'!" - fi + ."/${T}/make-amd-ucode-img" "${S}/amd-ucode" "${S}/amd-ucode.img" || die else # If this will ever happen something has changed which # must be reviewed @@ -361,6 +346,17 @@ src_install() { insinto /usr/lib/dracut/dracut.conf.d newins - 10-${PN}.conf <<<"early_microcode=$(usex initramfs)" ) + if use initramfs; then + # Install installkernel/kernel-install hooks for non-dracut initramfs + # generators that don't bundled the microcode + dobin "${T}/make-amd-ucode-img" + ( + exeinto /usr/lib/kernel/preinst.d + doexe "${FILESDIR}/35-amd-microcode.install" + exeinto /usr/lib/kernel/install.d + doexe "${FILESDIR}/35-amd-microcode-systemd.install" + ) + fi if use initramfs && ! use dist-kernel; then insinto /boot |