# Copyright 1999-2017 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 # @ECLASS: linux-build.eclass # @MAINTAINER: # Bertrand Jacquin # @BLURB: Eclass for building kernel # @DESCRIPTION: # Build kernel properly case "${EAPI:-0}" in 6) ;; *) die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}" ;; esac ETYPE="sources" inherit savedconfig kernel-2 detect_version EXPORT_FUNCTIONS pkg_setup src_prepare src_compile src_install pkg_postinst : ${LINUX_BUILD_MOD_SIG_DAYS:=365} : ${LINUX_BUILD_MOD_SIG_KEY_ALG:=rsa} : ${LINUX_BUILD_MOD_SIG_KEY_SIZE:=2048} SLOT="${PV%.*}" DESCRIPTION="Kernel stable sources and build" HOMEPAGE="https://www.kernel.org" SRC_URI="${KERNEL_URI} ${GENPATCHES_URI} ${ARCH_URI}" SRCDIR="${WORKDIR}/linux-${KV_FULL}" BUILDDIR="${WORKDIR}/build" KV_EXTRA="${EXTRAVERSION}" S="${SRCDIR}" IUSE="build source" REQUIRED_USE="symlink? ( source )" DEPEND="sys-devel/bc sys-apps/diffutils sys-apps/kmod" RDEPEND="" # @FUNCTION: _linux-build_configval # @INTERNAL # @DESCRIPTION: # Request a CONFIG value from .config file # Return true if set, and define CONFIG_ # Return false if not set _linux-build_configval() { local _v="CONFIG_$1" # Export only the needed config value # when not already define declare -p "${_v}" > /dev/null 2>&1 \ || . <(sed -n "/^${_v}=/ p" "${BUILDDIR}/.config") case "${!_v}" in "") declare "$_v=n" ; export "${_v}" ; return 1 ;; *) export "${_v}" ; return 0 ;; esac } _linux-build_get-portage-versions() { local -a _v local _rv if [[ "${PF}" != "${P}" ]] ; then _v+=( "${PF}" ) fi _v+=( "${P}" ) if [[ -n "${REPLACING_VERSIONS}" ]] ; then for _rv in ${REPLACING_VERSIONS} ; do _v+=( "${PN}-${_rv}" ) done fi _v+=( "${PN}" ) echo "${_v[@]}" } _linux-build_pkg_setup-build-config() { local _v if ! use savedconfig ; then return 0 fi if [[ -e "${PORTAGE_CONFIGROOT%/}/etc/portage/savedconfig/${CATEGORY}/${PF}" ]] ; then einfo "Restoring configuration from ${PORTAGE_CONFIGROOT%/}/etc/portage/savedconfig/${CATEGORY}/${PF}" eend 0 return 0 fi for _v in $(_linux-build_get-portage-versions) ; do einfo "Checking existence of ${PORTAGE_CONFIGROOT%/}/etc/portage/savedconfig/${CATEGORY}/${_v}" if [[ -e "${PORTAGE_CONFIGROOT%/}/etc/portage/savedconfig/${CATEGORY}/${_v}" ]] ; then eend 0 einfo "Restoring configuration from ${PORTAGE_CONFIGROOT%/}/etc/portage/savedconfig/${CATEGORY}/${PF}" cp "${PORTAGE_CONFIGROOT%/}/etc/portage/savedconfig/${CATEGORY}/${_v}" \ "${PORTAGE_CONFIGROOT%/}/etc/portage/savedconfig/${CATEGORY}/${PF}" \ || die "Failed to copy ${PORTAGE_CONFIGROOT%/}/etc/portage/savedconfig/${CATEGORY}/${_v}" eend 0 return 0 fi eend 1 done return 1 } _linux-build_pkg_setup-build-x509() { local _v for _v in $(_linux-build_get-portage-versions) ; do einfo "Checking existence of ${PORTAGE_CONFIGROOT%/}/etc/ssl/private/${_v}.pem" if [[ -e "${PORTAGE_CONFIGROOT%/}/etc/ssl/private/${_v}.pem" ]] ; then eend 0 mkdir "${T}/certs" einfo "Restoring x509 pair from ${PORTAGE_CONFIGROOT%/}/etc/portage/savedconfig/${CATEGORY}/${PF}" cp --preserve=mode,ownership \ "${PORTAGE_CONFIGROOT%/}/etc/ssl/private/${_v}.pem" "${T}/certs/signing_key.pem" \ || die "Failed to copy ${PORTAGE_CONFIGROOT%/}/etc/ssl/private/${_v}.pem" eend 0 return 0 fi eend 1 done return 1 } _linux-build_pkg_setup-build() { _linux-build_pkg_setup-build-config _linux-build_pkg_setup-build-x509 } linux-build_pkg_setup() { kernel-2_pkg_setup use build && _linux-build_pkg_setup-build } _linux-build_src_prepare_build() { local i mkdir "${BUILDDIR}" mkdir "${WORKDIR}/boot" if [[ -e "${PORTAGE_CONFIGROOT%/}/etc/portage/savedconfig/${CATEGORY}/${PF}" ]] ; then cp "${PORTAGE_CONFIGROOT%/}/etc/portage/savedconfig/${CATEGORY}/${PF}" "${BUILDDIR}/.config" \ || die "Failed to copy ${PORTAGE_CONFIGROOT%/}/etc/portage/savedconfig/${CATEGORY}/${PF}" else ewarn "Generate .config using 'defconfig'" emake defconfig "${myopt[@]}" fi if _linux-build_configval CMDLINE_BOOL && _linux-build_configval CMDLINE ; then einfo "Creating kernel.arg" einfo " CONFIG_CMDLINE='${CONFIG_CMDLINE}'" echo "${CONFIG_CMDLINE}" > "${WORKDIR}/boot/kernel.arg" fi local -a BOOTLOADERS=( sys-boot/grub:0 /boot/grub/grub.conf sys-boot/syslinux:0 /boot/extlinux/extlinux.conf ) KV_INSTALLED="$(best_version ${CATEGORY}/${PN}:${SLOT})" KV_INSTALLED="${KV_INSTALLED/#${CATEGORY}\/${PN}-}" if [[ -n "${KV_INSTALLED}" ]] ; then for (( i = 0 ; i < ${#BOOTLOADERS[@]} ; i+=2 )) ; do if ! has_version "${BOOTLOADERS[i]}" || [[ ! -e "${EPREFIX}/${BOOTLOADERS[i+1]}" ]] ; then continue fi BOOTLOADER_DIR="${BOOTLOADERS[i+1]%/*}" BOOTLOADER_FILE="${BOOTLOADERS[i+1]##*/}" mkdir -p "${WORKDIR}/bootloader/${BOOTLOADER_DIR}" # Handle collision protect for (( j = 0 ; j < 9999 ; j++ )) ; do printf -v BOOTLOADER_PROTECTED_FILE "._cfg%04d_${BOOTLOADER_FILE}" "${j}" if [[ ! -e "${EPREFIX}/${BOOTLOADER_DIR}/${BOOTLOADER_PROTECTED_FILE}" ]] ; then break fi done einfo "Generating ${BOOTLOADER_DIR}/${BOOTLOADER_FILE}" sed -e "s@${KV_INSTALLED}${KV_EXTRA}@${KV_FULL}@g" \ "${EPREFIX}/${BOOTLOADER_DIR}/${BOOTLOADER_FILE}" \ > "${WORKDIR}/bootloader/${BOOTLOADER_DIR}/${BOOTLOADER_PROTECTED_FILE}" if diff -q \ "${EPREFIX}/${BOOTLOADER_DIR}/${BOOTLOADER_FILE}" \ "${WORKDIR}/bootloader/${BOOTLOADER_DIR}/${BOOTLOADER_PROTECTED_FILE}" > /dev/null ; then rm "${WORKDIR}/bootloader/${BOOTLOADER_DIR}/${BOOTLOADER_PROTECTED_FILE}" fi _CONFIG_PROTECT+=( "${BOOTLOADER_DIR}/${BOOTLOADER_FILE}" ) done echo "CONFIG_PROTECT='${_CONFIG_PROTECT[@]}'" > "${WORKDIR}/env.d_42-${P}" fi _linux-build_configval MODULES || ewarn "CONFIG_MODULES is not set" _linux-build_configval UEVENT_HELPER_PATH \ && ewarn "CONFIG_UEVENT_HELPER_PATH should be empty" _linux-build_configval FHANDLE || ewarn "CONFIG_FHANDLE is needed for >=sys-fs/udev-210" _linux-build_configval NET || ewarn "CONFIG_NET is needed for >=sys-fs/udev-210" if _linux-build_configval MODULE_COMPRESS ; then if _linux-build_configval MODULE_COMPRESS_GZIP ; then if ! has_version "app-arch/gzip" ; then die "app-arch/gzip is required for CONFIG_MODULE_COMPRESS_GZIP" fi elif _linux-build_configval MODULE_COMPRESS_XZ ; then if ! has_version "app-arch/xz-utils" ; then die "app-arch/xz-utils is required for CONFIG_MODULE_COMPRESS_XZ" fi else die "CONFIG_MODULE_COMPRESS needs one of ( CONFIG_MODULE_COMPRESS_GZIP CONFIG_MODULE_COMPRESS_XZ )" fi fi if _linux-build_configval MODULE_SIG ; then if ! has_version "dev-libs/openssl" ; then die "dev-libs/openssl is required for CONFIG_MODULE_SIG" fi if ! _linux-build_configval MODULE_SIG_HASH ; then die "CONFIG_MODULE_SIG_HASH must be defined when using CONFIG_MODULE_SIG" fi mkdir "${BUILDDIR}/certs" if [[ -e "${T}/certs/signing_key.pem" ]] ; then touch "${BUILDDIR}/certs/x509.genkey" cp --preserve=mode,ownership \ "${T}/certs/signing_key.pem" "${BUILDDIR}/certs/signing_key.pem" else einfo "Generating x509 config" cat > "${BUILDDIR}/certs/x509.genkey" <<-EOF [ req ] prompt = no distinguished_name = ${PF}_subj x509_extensions = ${PF}_exts [ ${PF}_subj ] O = Pants On OU = ${KBUILD_BUILD_HOST:-${HOSTNAME}} CN = ${CATEGORY}/${PF} emailAddress = ${KBUILD_BUILD_USER:-${PORTAGE_BUILD_USER}}@${KBUILD_BUILD_HOST:-${HOSTNAME}}" [ ${PF}_exts ] basicConstraints=critical,CA:FALSE keyUsage=digitalSignature subjectKeyIdentifier=hash authorityKeyIdentifier=keyid EOF einfo "Generating x509 pair" openssl req -x509 -nodes -batch \ -days "${LINUX_BUILD_MOD_SIG_DAYS}" \ -newkey "${LINUX_BUILD_MOD_SIG_KEY_ALG}:${LINUX_BUILD_MOD_SIG_KEY_SIZE}" \ "-${CONFIG_MODULE_SIG_HASH}" \ -outform PEM \ -config "${BUILDDIR}/certs/x509.genkey" \ -out "${BUILDDIR}/certs/signing_key.pem" \ -keyout "${BUILDDIR}/certs/signing_key.pem" \ || die "openssl req fail" fi openssl x509 -inform PEM -noout \ -in "${BUILDDIR}/certs/signing_key.pem" \ -subject fi einfo "Checking configuration file" if kernel_is -le 3 5 ; then emake oldnoconfig "${myopt[@]}" else emake olddefconfig "${myopt[@]}" fi if diff -Nu0 "${BUILDDIR}/.config.old" "${BUILDDIR}/.config" \ | egrep -q '^(\-|\+)CONFIG_' ; then eerror "You configuration is not up to date" diff -Nu "${BUILDDIR}/.config.old" "${BUILDDIR}/.config" die "Bad configuration" fi } linux-build_src_prepare() { kernel-2_src_prepare bopt=( -C "${SRCDIR}" KBUILD_OUTPUT="${BUILDDIR}" KCONFIG_CONFIG="${BUILDDIR}/.config" KBUILD_BUILD_USER="${KBUILD_BUILD_USER:-${PORTAGE_BUILD_USER}}" KBUILD_BUILD_HOST="${KBUILD_BUILD_HOST:-${HOSTNAME}}" KBUILD_BUILD_TIMESTAMP="$(date --iso-8601=seconds)" ) copt=( CC="$(tc-getCC)" HOSTCC="${CBUILD}-gcc" CROSS_COMPILE="${CHOST}-" ARCH="$(tc-arch-kernel)" SUBARCH="$(tc-arch-kernel)" ) vopt=( EXTRAVERSION="${KV_EXTRA}" LOCALVERSION= CONFIG_LOCALVERSION= V=1 ) myopt=( "${bopt[@]}" "${copt[@]}" "${vopt[@]}" ) use build && _linux-build_src_prepare_build } _linux-build_src_compile_build() { einfo "Building kernel" emake bzImage "${myopt[@]}" if _linux-build_configval MODULES ; then einfo "Building modules" emake modules "${myopt[@]}" fi } linux-build_src_compile() { use build && _linux-build_src_compile_build } _linux-build_src_install_sources() { kernel-2_src_install } _linux-build_src_install_build() { einfo "Installing kernel" emake install "${myopt[@]}" \ INSTALL_PATH="${WORKDIR}/boot" insinto "/boot/${KV_FULL}" newins "${WORKDIR}/boot/config-${KV_FULL}" kernel.cfg newins "${WORKDIR}/boot/vmlinuz-${KV_FULL}" kernel.img newins "${WORKDIR}/boot/System.map-${KV_FULL}" System.map if _linux-build_configval CMDLINE_BOOL && _linux-build_configval CMDLINE ; then doins "${WORKDIR}/boot/kernel.arg" fi if _linux-build_configval MODULES ; then einfo "Installing modules" emake modules_install "${myopt[@]}" \ INSTALL_MOD_PATH="${WORKDIR}" \ INSTALL_MOD_STRIP="${PORTAGE_STRIP_FLAGS}" einfo "Generating modules.dep" depmod -ae -F "${BUILDDIR}/System.map" -b "${WORKDIR}" "${KV_FULL}" \ || die "depmod failed" rm "${WORKDIR}/lib/modules/${KV_FULL}/build" rm "${WORKDIR}/lib/modules/${KV_FULL}/source" insinto /lib doins -r "${WORKDIR}/lib/modules" # No need to make firmware_install, make modules_install does if [[ -e "${WORKDIR}/lib/firmware" ]] ; then einfo "Installing firmwares" insinto /lib doins -r "${WORKDIR}/lib/firmware" fi fi if [[ -d "${WORKDIR}/bootloader/boot" ]] ; then insinto /boot doins -r "${WORKDIR}"/bootloader/boot/* insinto /etc/env.d newins "${WORKDIR}/env.d_42-${P}" "42-${P}" fi use savedconfig && save_config "${BUILDDIR}/.config" } linux-build_src_install() { use build && _linux-build_src_install_build use source && _linux-build_src_install_sources } linux-build_pkg_postinst() { kernel-2_pkg_postinst # Bypass kernel-2_pkg_postinst madness if ! use symlink && [[ -L "${EROOT}usr/src/linux" ]] ; then rm "${EROOT}usr/src/linux" fi einfo "You may need to:" einfo " make menuconfig ${copt[@]}" }