diff options
-rw-r--r-- | eclass/kmod.eclass | 322 |
1 files changed, 322 insertions, 0 deletions
diff --git a/eclass/kmod.eclass b/eclass/kmod.eclass new file mode 100644 index 000000000000..b51409ce0ff9 --- /dev/null +++ b/eclass/kmod.eclass @@ -0,0 +1,322 @@ +# Copyright 1999-2003 Gentoo Technologies, Inc. +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-x86/eclass/kmod.eclass,v 1.11 2004/04/10 20:07:00 latexer Exp $ + +# This eclass provides help for compiling external kernel modules from +# source. +# +# BEWARE: This eclass is superceding the old kmod.eclass. It does *not* +# implement the same functionality as the old kmod.eclass! + +# DOCUMENTATION: Most documentation for this can be found at: +# http://www.gentoo.org/doc/en/2.6-koutput.xml +# +# More documentation comments will follow in the header of this soon! + +# Variables you can use to change behavior +# +# KMOD_SOURCES - space seperated list of source to unpack in +# src_unpack() if you don't want ${A} unpacked. +# +# KMOD_KOUTPUT_PATCH - Patch to apply in src_unpack() if a seperate output +# directory is detected. +# + +inherit eutils + +ECLASS=kmod +INHERITED="$INHERITED $ECLASS" +S=${WORKDIR}/${P} +DESCRIPTION="Based on the $ECLASS eclass" + +SRC_URI="${SRC_URI:-unknown - please fix me!!}" +KERNEL_DIR="${KERNEL_DIR:-${ROOT}/usr/src/linux}" + +EXPORT_FUNCTIONS src_unpack src_compile pkg_postinst + +kmod_get_make_var () +{ + grep "^${1}" ${2} | head -n 1 | grep -v ":=" | cut -d = -f 2- \ + | awk '{ print $1 }' +} + +# getconfigvar() - Prints the value of a certain config varaible from the +# current kernel's config file. Will return "n" for an unset +# option + +kmod_get_config_var() +{ + local configopt="CONFIG_${1}" + local configresult + + if [ -z ${KV_OUTPUT} ]; then + get_kernel_info + fi + + configresult="`grep ^$configopt ${KV_OUTPUT}/.config | cut -d= -f 2-`" + if [ -z "${configresult}" ]; then + echo "n" + else + echo ${configresult} | awk '{ print $1 }' + fi +} + +# get_kernel_info is used to get our build environment. It initializes several +# variables that can be used in ebuilds +# +# KV_MAJOR, KV_MINOR, KV_PATCH - the kernel major, minor, and pathlevel #'s +# KV_TYPE - the type, as found from EXTRAVERSION. +# +# KV_VERSION_FULL - full string for the kernel version +# +# KV_OUTPUT - the output direcotry if used with a 2.6 kernel +# +# KV_OBJ - extension for kernel objects, "o" for 2.4 kernels and "ko" for 2.6 +# +get_kernel_info() +{ + # yes, this is horrible, but it is effective + # + # KV_DIR contains the real directory name of the directory containing + # the Linux kernel that we are going to compile against + + if [ -h ${KERNEL_DIR} ] ; then + einfo "`echo ${KERNEL_DIR} | tr -s /` is a symbolic link" + einfo "Determining the real directory of the Linux kernel source code" + KV_DIR="`readlink ${KERNEL_DIR}`" + elif [ -d ${KERNEL_DIR} ] ; then + einfo "`echo ${KERNEL_DIR} | tr -s /` is a real directory" + KV_DIR="`ls -d ${KERNEL_DIR}`" + # KV_DIR="`ls -ld --full-time ${KERNEL_DIR} | awk '{ print $9 }'`" + else + eerror "Directory '${KERNEL_DIR}' cannot be found" + die + fi + KV_DIR="`basename ${KV_DIR}`" + + # now, we need to break that down into versions + + KV_DIR_VERSION_FULL="`echo $KV_DIR | cut -f 2- -d -`" + + KV_DIR_MAJOR="`echo ${KV_DIR_VERSION_FULL} | cut -f 1 -d .`" + KV_DIR_MINOR="`echo ${KV_DIR_VERSION_FULL} | cut -f 2 -d .`" + KV_DIR_PATCH="`echo ${KV_DIR_VERSION_FULL} | cut -f 3 -d . | cut -f 3 -d -`" + KV_DIR_TYPE="`echo ${KV_DIR_VERSION_FULL} | cut -f 2- -d -`" + + # sanity check - do the settings in the kernel's makefile match + # the directory that the kernel src is stored in? + + KV_MK_FILE="${KERNEL_DIR}/Makefile" + KV_MK_MAJOR="`kmod_get_make_var VERSION ${KV_MK_FILE}`" + KV_MK_MINOR="`kmod_get_make_var PATCHLEVEL ${KV_MK_FILE}`" + KV_MK_PATCH="`kmod_get_make_var SUBLEVEL ${KV_MK_FILE}`" + KV_MK_TYPE="`kmod_get_make_var EXTRAVERSION ${KV_MK_FILE}`" + + KV_MK_VERSION_FULL="${KV_MK_MAJOR}.${KV_MK_MINOR}.${KV_MK_PATCH}${KV_MK_TYPE}" + + KV_MK_OUTPUT="`kmod_get_make_var KBUILD_OUTPUT ${KV_MK_FILE}`" + + # May need to deal with a dynamically set KBUILD_OUTPUT variable + if [ "${KV_MK_OUTPUT/VERSION/}" != "${KV_MK_OUTPUT}" ]; then + KV_MK_OUTPUT="${KV_MK_OUTPUT/\$(VERSION)/${KV_MK_MAJOR}}" + KV_MK_OUTPUT="${KV_MK_OUTPUT/\$(PATCHLEVEL)/${KV_MK_MINOR}}" + KV_MK_OUTPUT="${KV_MK_OUTPUT/\$(SUBLEVEL)/${KV_MK_PATCH}}" + KV_MK_OUTPUT="${KV_MK_OUTPUT/\$(EXTRAVERSION)/${KV_MK_TYPE}}" + fi + + if [ "$KV_MK_VERSION_FULL" != "${KV_DIR_VERSION_FULL}" ]; then + ewarn + ewarn "The kernel Makefile says that this is a ${KV_MK_VERSION_FULL} kernel" + ewarn "but the source is in a directory for a ${KV_DIR_VERSION_FULL} kernel." + ewarn + ewarn "This goes against the recommended Gentoo naming convention." + ewarn "Please rename your source directory to 'linux-${KV_MK_VERSION_FULL}'" + ewarn + fi + + # these variables can be used by ebuilds to determine whether they + # will work with the targetted kernel or not + # + # do not rely on any of the variables above being available + + KV_VERSION_FULL="${KV_MK_VERSION_FULL}" + KV_MAJOR="${KV_MK_MAJOR}" + KV_MINOR="${KV_MK_MINOR}" + KV_PATCH="${KV_MK_PATCH}" + KV_TYPE="${KV_MK_TYPE}" + + # if we found an output location, use that. otherwise use KERNEL_DIR. + if [ ! -z "${KV_MK_OUTPUT}" ] + then + KV_OUTPUT="${ROOT}/${KV_MK_OUTPUT}" + else + KV_OUTPUT="${KERNEL_DIR}" + fi + + # KV_OBJ can be used when manually installing kernel modules + if [ "${KV_MINOR}" -gt "4" ] + then + KV_OBJ="ko" + else + KV_OBJ="o" + fi + + einfo "Building for Linux ${KV_VERSION_FULL} found in `echo ${KERNEL_DIR} | tr -s /`" + + if is_kernel 2 5 || is_kernel 2 6 + then + einfo "which outputs to `echo ${KV_OUTPUT} | tr -s /`" + + # Warn them if they aren't using a different output directory + if [ "${KV_OUTPUT}" = "${ROOT}/usr/src/linux" ]; then + ewarn "By not using the kernel's ability to output to an alternative" + ewarn "directory, some external module builds may fail." + ewarn "See <insert link to user doc here>" + fi + fi +} + +# kmod_make_linux_writeable() is used to allow portage to write to +# /usr/src/linux. This is a BIG no-no, but the "easiest" way for +# 2.6 module compilation. Since it's so horrible, we force users to accept +# doing it via a variable controlled by /etc/env.d/20kernel and kernel-config + +kmod_make_linux_writable() +{ + # LINUX_PORTAGE_WRITABLE is set in /etc/env.d/20kernel to "yes" + # if someone really wants to do that + [ -x ${ROOT}/usr/bin/config-kernel ] && LINUX_PORTAGE_WRITABLE="$(${ROOT}/usr/bin/config-kernel --is-writable)" + + if [ "${LINUX_PORTAGE_WRITABLE}" != "yes" ] + then + if [ "${FEATURES/sandbox/}" != "${FEATURES}" ] + then + eerror "Due to the 2.6 kernel build system, external module compilation" + eerror "with a normal setup requires write access to ${KERNEL_DIR}" + eerror "There are several ways to fix/prevent this." + eerror "Users can willingly let portage make this writable by doing" + eerror "# config-kernel --allow-writable yes" + eerror "However, this is considered a security risk!" + eerror "" + eerror "The prefered method is to enable Gentoo's new 'koutput' method" + eerror "for kernel modules. See the doc" + eerror "http://www.gentoo.org/doc/en/2.6-koutput-user.xml" + eerror "To enable this, you'll need to run" + eerror "# config-kernel --output-dir /var/tmp/kernel-output" + eerror "and then install a new kernel" + die "Incompatible kernel setup" + else + ewarn "Detected sandbox disabled for kernel module ebuild" + fi + fi + + eerror "Making ${ROOT}/usr/src/linux-${KV} writable by portage!!!" + addwrite ${ROOT}/usr/src/linux-${KV} +} + + +# kmod_do_buildpatches performs the needed koutput patches as needed +kmod_do_buildpatches() +{ + if [ -z ${KV_OUTPUT} ]; then + get_kernel_info + fi + + cd ${S} + if is_koutput && [ -n "${KMOD_KOUTPUT_PATCH}" ]; then + EPATCH_SINGLE_MESSAGE="Patching to enable koutput compatibility" \ + epatch ${KMOD_KOUTPUT_PATCH} + fi +} + +kmod_src_unpack () +{ + check_KV + kmod_universal_unpack +} + +kmod_universal_unpack() +{ + get_kernel_info + + # KMOD_SOURCES is used if you don't want to unpack just ${A} + # It can be set to "none" if you need to unpack things by hand + # (like the nvidia-kernel ebuild). If set to "none", you'll have + # to do any patching by hand as ${S} won't be around yet! + # You can just call kmod_do_buildpatches after unpacking ${S} + # if need be. + if [ -z "${KMOD_SOURCES}" ] + then + unpack ${A} + elif [ "${KMOD_SOURCES}" != "none" ] + then + unpack ${KMOD_SOURCES} + fi + + if is_kernel 2 5 || is_kernel 2 6 + then + # If we have sources we've unpacked, patch as needed + if [ "${KMOD_SOURCES}" != "none" ]; then + kmod_do_buildpatches + fi + fi +} + +kmod_src_compile () +{ + if is_kernel 2 5 || is_kernel 2 6 + then + # If we're on 2.5/2.6 and not koutputing, we need to make + # /usr/src/linux writable to succeed + if ! is_koutput + then + kmod_make_linux_writable + fi + + unset ARCH + fi + emake KERNEL_DIR=${KERNEL_DIR} || die +} + +kmod_pkg_postinst() +{ + einfo "Checking kernel module dependancies" + test -r "${ROOT}/${KV_OUTPUT}/System.map" && \ + depmod -ae -F "${ROOT}/${KV_OUTPUT}/System.map" -b "${ROOT}" -r ${KV} +} + +# is_kernel() takes two arguments. They should be the major and minor number +# of the kernel you'd like to check for. e.g. +# +# if is_kernel 2 6; then foo; fi +# +is_kernel() { + if [ -z "${KV_MAJOR}" ] + then + get_kernel_info + fi + + if [ "${KV_MAJOR}" -eq "${1}" -a "${KV_MINOR}" -eq "${2}" ] + then + return 0 + else + return 1 + fi +} + +# is_koutput() should be used to determing if we are using the koutput +# method of compilation for 2.6 kernels + +is_koutput() { + if [ -z ${KV_OUTPUT} ] + then + get_kernel_info + fi + + if [ "${KV_OUTPUT}" != "${ROOT}/usr/src/linux" ]; then + return 0 + else + return 1 + fi +} + |