#!/bin/bash source /etc/make.conf progname=cl-kernel OVERLAY_DIRECTORY="/usr/local/portage/layman/calculate" [[ -d "/var/lib/layman/calculate" ]] && OVERLAY_DIRECTORY="/var/lib/layman/calculate" KERNEL_CONFIG_DIR="${OVERLAY_DIRECTORY}/profiles/kernel" SHORTOPTS="k:c:e:hmoq" LONGOPTS="help,kerneldir:,kernel-config:,extraversion:,no-clean,menuconfig,use-own-config,quiet,lvm,dmraid,mdadm" print_help() { cat <<'EOF' Usage: cl-kernel [options] [-c FILE|-o] Make kernel. Options: -c, --kernel-config FILE Kernel configuration file to use for compilation --dmraid Include RMRAID support -e, --extraversion VER Specify extraversion for kernel -h, --help Print this help message -k, --kerneldir DIR Location of the kernel sources --lvm Include LVM support --mdadm Copy /etc/mdadm.conf to initramfs -m, --menuconfig Run menuconfig after oldconfig --no-clean Do not run make clean before compilation -o, --use-own-config Use config from kernel directory. -q, --quiet Do not display kernel compilation process Examples: The most common use is to run it like this, which build and install current kernel. $ cl-kernel $ cl-kernel --menuconfig --kerneldir /usr/src/linux-2.6.31-gentoo-r6 EOF } parse_kernel_version() { if [[ ${KERNEL_VERSION} =~ ^([0-9]+)\.([0-9]+)\.([0-9]+)([-.].+)?$ ]] then # version kernel KV_MAJOR=${BASH_REMATCH[1]} KV_MINOR=${BASH_REMATCH[2]} KV_PATCH=${BASH_REMATCH[3]} [[ -z $1 ]] && KV_TYPE=${BASH_REMATCH[4]} || KV_TYPE=$1 OKV=${KV_MAJOR}.${KV_MINOR}.${KV_PATCH} KERNEL_VERSION=${OKV}${KV_TYPE} else echo "Wrong kernel version: ${KERNEL_VERSION}" exit 0 fi } warning() { echo "Warning: "$1 1>&2 } die() { echo 1>&2 echo "Error: "$1 1>&2 exit 1 } get_value() { sed -rn "s/^$1=\"?([^\"]*)\"?$/\1/p" $2 } set_param() { local paramname=$1 local paramvalue=$2 local filename=$3 sed -ri "s/^$paramname = .*$/$paramname = $paramvalue/" $filename } set_kernel_version() { set_param VERSION $KV_MAJOR ${KERNEL_DIR}/Makefile set_param PATCHLEVEL $KV_MINOR ${KERNEL_DIR}/Makefile set_param SUBLEVEL $KV_PATCH ${KERNEL_DIR}/Makefile set_param EXTRAVERSION $KV_TYPE ${KERNEL_DIR}/Makefile } get_stdin_value() { sed -rn "s/^(.*\s+)?+$1=\"?([^\" ]*)\"?(\s+.*|$)/\2/p" } change_kernel_in_grub() { local ROOTDEV=$( get_stdin_value root < /proc/cmdline ) local NAMESUFFIX=$1 [[ -f /boot/vmlinuz-${NAMESUFFIX} ]] && [[ -f /boot/initramfs-${NAMESUFFIX} ]] && [[ -f /boot/initramfs-${NAMESUFFIX}-install ]] && [[ -f /boot/grub/grub.conf ]] && sed -ri "/^title/{ #find title in grub.conf :readnextline;N; #read next line s/\ninitrd/&/; #if pattern not contents initrd Treadnextline; #goto read next line :changemenuitem; #else try change menuitem s|root=${ROOTDEV}|&|; #if menuitem not for the system Tskipmenuitem; #then skip menuitem s|(/boot/vmlinuz)[^ ]+|\1-${NAMESUFFIX}|; #else change vmlinuz s|initrd (.*)-install$|initrd \1/install|; #hide '-install' s|(/boot/initramfs)[^ /]+|\1-${NAMESUFFIX}|; #change initramfs s|/install$|-install|; #show '-install' :skipmenuitem; }" /boot/grub/grub.conf } initramfs_unpack() { mkdir -p tmp/initramfs || die "Catn't create temporary directory for initramfs" pushd tmp/initramfs >/dev/null # unpack initramfs arcmd="gzip" # check may be initramfs packed by lzma lzma -dc ${BOOT_DIR}/initramfs-${KERNEL_NAME}-*-${KERNEL_VERSION} \ &>/dev/null && arcmd="lzma" ${arcmd} -dc ${BOOT_DIR}/initramfs-${KERNEL_NAME}-*-${KERNEL_VERSION} | cpio -di &>/dev/null || die "Cann't unpack initramfs" } initramfs_clean() { # remove sound moudles find -name sound -exec rm -rf {} \; &>/dev/null } initramfs_pack() { # pack new initramfs find * | cpio -o --quiet -H newc | gzip -9 >${BOOT_DIR}/initramfs-${KERNEL_NAME}-*-${KERNEL_VERSION} || die "Cann't pack initramfs" popd &>/dev/null rm -rf tmp/initramfs || warning "Cann't remove temporary directory contenting initramfs" } set_new_current_kernel() { # set new current kernel if [[ ${KERNEL_DIR} != '/usr/src/linux' ]] then # if source place in /usr/src if [[ ${KERNEL_DIR} =~ ^/usr/src/([^/]+)$ ]] then rm /usr/src/linux && ln -sf ${BASH_REMATCH[1]} /usr/src/linux else # is specifed absolutly path if [[ ${KERNEL_DIR:0:1} == '/' ]] then rm /usr/src/linux && ln -sf ${KERNEL_DIR} /usr/src/linux fi fi fi } # mv file to file with suffix and fix symlink to this file old_file() { local dir=$1 local filename=$2 local suffix=$3 mv -f ${dir}/${filename} ${dir}/${filename}${suffix} &>/dev/null && [[ -f ${dir}/${filename}${suffix} ]] && find ${dir} -lname "$filename" -exec ln -sf ${filename}${suffix} {} \; } detect_linux_shortname() { local makeprofile=$(readlink /etc/make.profile) local profile= local system= local shortname= while [[ $profile != "calculate" && $profile != "." ]] do shortname=$system system=$profile profile=$(basename $makeprofile) makeprofile=$(dirname $makeprofile) done if [[ $profile == "calculate" ]] then echo $shortname else echo "gentoo" fi } install_kernel() { local NEW_KERNEL_VERSION=${KERNEL_VERSION/-calculate}-`arch`-$(detect_linux_shortname) old_file ${BOOT_DIR} vmlinuz-${NEW_KERNEL_VERSION} .old old_file ${BOOT_DIR} System.map-${NEW_KERNEL_VERSION} .old old_file ${BOOT_DIR} initramfs-${NEW_KERNEL_VERSION} .old old_file ${BOOT_DIR} initramfs-${NEW_KERNEL_VERSION}-install .old old_file ${BOOT_DIR} vmlinuz .old old_file ${BOOT_DIR} System.map .old old_file ${BOOT_DIR} initrd .old old_file ${BOOT_DIR} initrd-install .old old_file ${BOOT_DIR} config-${NEW_KERNEL_VERSION} .old mv ${BOOT_DIR}/kernel-${KERNEL_NAME}-*-${KERNEL_VERSION} \ ${BOOT_DIR}/vmlinuz-${NEW_KERNEL_VERSION} ln -sf vmlinuz-${NEW_KERNEL_VERSION} ${BOOT_DIR}/vmlinuz mv ${BOOT_DIR}/System.map-${KERNEL_NAME}-*-${KERNEL_VERSION} \ ${BOOT_DIR}/System.map-${NEW_KERNEL_VERSION} ln -sf System.map-${NEW_KERNEL_VERSION} ${BOOT_DIR}/System.map cp ${BOOT_DIR}/initramfs-${KERNEL_NAME}-*-${KERNEL_VERSION} \ ${BOOT_DIR}/initramfs-${NEW_KERNEL_VERSION} ln -sf initramfs-${NEW_KERNEL_VERSION} ${BOOT_DIR}/initrd mv ${BOOT_DIR}/initramfs-${KERNEL_NAME}-*-${KERNEL_VERSION} \ ${BOOT_DIR}/initramfs-${NEW_KERNEL_VERSION}-install ln -sf initramfs-${NEW_KERNEL_VERSION}-install ${BOOT_DIR}/initrd-install cp ${KERNEL_DIR}/.config ${BOOT_DIR}/config-${NEW_KERNEL_VERSION} change_kernel_in_grub ${NEW_KERNEL_VERSION} } KERNEL_DIR=/usr/src/linux KERNEL_CONFIG= USE_OWN_CONFIG=false SYSTEMNAME=$(sed -nr '/^system=/ s/^[^=]+=(.*)$/\1/p' \ /etc/calculate/calculate.ini) KERNEL_NAME=${SYSTEMNAME} KERNEL_VERSION= DESTINATION= KERNEL_EXTRAVERSION= ARCH=`arch` NOCLEAN="" MENUCONFIG="" GENKERNEL_RAW_OPTS="" LOGLEVEL="--loglevel=2" OPTS=$(getopt -o $SHORTOPTS --long $LONGOPTS -n "$progname" -- "$@") if [ $? -ne 0 ]; then echo "'$progname --help' for more information" 1>&2 exit 1 fi eval set -- "$OPTS" while [ $# -gt 0 ]; do case $1 in -h|--help) print_help exit 0 ;; -m|--menuconfig) MENUCONFIG="--menuconfig" shift ;; --no-clean) NOCLEAN="--no-clean" shift ;; -o|--use-own-config) [[ -n $KERNEL_CONFIG ]] && die "Option '$1' cannot be used in conjunction with '--kernel-config'" USE_OWN_CONFIG=true shift ;; -k|--kerneldir) KERNEL_DIR=$2 shift 2 ;; -c|--kernel-config) [[ $USE_OWN_CONFIG == "true" ]] && die "Option '$1' cannot be used in conjunction with '--use-own-config'" KERNEL_CONFIG=$2 shift 2 ;; -e|--extraversion) KERNEL_EXTRAVERSION=$2 shift 2 ;; -q|--quiet) LOGLEVEL="--loglevel=1" shift ;; --lvm) GENKERNEL_RAW_OPTS="${GENKERNEL_RAW_OPTS} --lvm" shift ;; --dmraid) GENKERNEL_RAW_OPTS="${GENKERNEL_RAW_OPTS} --dmraid" shift ;; --mdadm) GENKERNEL_RAW_OPTS="${GENKERNEL_RAW_OPTS} --mdadm" shift ;; --) shift ;; *) die "unknown second option: $1" ;; esac done # check kernel directory [[ -e ${KERNEL_DIR}/Makefile ]] || die "Wrong kernel sources directory: ${KERNEL_DIR}" [[ -z ${DESTINATION} ]] && DESTINATION="/" # get it from Makefile of sources KERNEL_VERSION=`grep \ -e ^VERSION -e ^PATCHLEVEL -e ^SUBLEVEL -e ^EXTRAVERSION \ ${KERNEL_DIR}/Makefile \ | sed -rn "{N;N;N;s/PATCHLEVEL = |SUBLEVEL = /./g; s/EXTRAVERSION = |VERSION = |\n//g;p}"` MODULE_INS_PATH=${DESTINATION} mkdir -p ${DESTINATION} BOOT_DIR=${DESTINATION%/}/boot # if specify extraversion add - or . before extraversion if it is missed if [[ -n ${KERNEL_EXTRAVERSION} ]] && [[ ${KERNEL_EXTRAVERSION:0:1} != [.-] ]] then if [[ ${KERNEL_EXTRAVERSION:0:1} == [0-9] ]] then # dot before number KERNEL_EXTRAVERSION=.${KERNEL_EXTRAVERSION} else # else - minus KERNEL_EXTRAVERSION=-${KERNEL_EXTRAVERSION} fi fi parse_kernel_version ${KERNEL_EXTRAVERSION} set_kernel_version # select kernel config (in kernel dir, own config or overlay kernel config) # .config.bak used instead .config, because genkernel copy specified kernel # config to "kernel directory/.config" if [[ ${USE_OWN_CONFIG} != "false" ]] || [[ $( readlink -f "${KERNEL_CONFIG}" ) == \ $( readlink -f "${KERNEL_DIR}/.config" ) ]] then KERNEL_CONFIG="${KERNEL_DIR}/.config.bak" [[ -e ${KERNEL_DIR}/.config ]] && cp ${KERNEL_DIR}/.config ${KERNEL_CONFIG} || die "Not found .config in ${KERNEL_DIR}" fi [[ -z ${KERNEL_CONFIG} ]] && KERNEL_CONFIG="${KERNEL_CONFIG_DIR}/config-${SYSTEMNAME}-${ARCH}-${OKV}" [[ -e ${KERNEL_CONFIG} ]] || die "Kernel config not found in ${KERNEL_CONFIG}" mkdir -p ${BOOT_DIR} # run generating kernel genkernel --splash=tty1 --unionfs --all-ramdisk-modules --disklabel \ --slowusb --kerneldir=${KERNEL_DIR} ${LOGLEVEL} \ --module-prefix=${MODULE_INS_PATH} --makeopts=${MAKEOPTS} \ ${NOCLEAN} ${MENUCONFIG} --no-save-config \ --kernel-config=${KERNEL_CONFIG} --kernname=${KERNEL_NAME} \ --bootdir=${BOOT_DIR} ${GENKERNEL_RAW_OPTS} all || \ die "kernel was not builded" KERNEL_LOCALVERSION=$( get_value CONFIG_LOCALVERSION ${KERNEL_DIR}/.config ) KERNEL_VERSION=${KERNEL_VERSION}${KERNEL_LOCALVERSION} pushd ${DESTINATION} &>/dev/null initramfs_unpack initramfs_clean initramfs_pack install_kernel set_new_current_kernel /usr/calculate/install/calculate --initrd if [[ "$(md5sum /boot/initrd | awk '{print $1}')" == \ "$(md5sum /boot/initrd-install | awk '{print $1}')" ]] then echo echo "Perform command after reboot for optimization initramfs:" echo " /usr/calculate/install/calculate --initrd" fi