#!/bin/bash source /etc/make.conf progname=cl-kernel OVERLAY_DIRECTORY="/usr/local/portage/layman/calculate" KERNEL_CONFIG_DIR="${OVERLAY_DIRECTORY}/profiles/kernel" SHORTOPTS="k:c:t:n:v:e:rho" LONGOPTS="help,no-install,kerneldir:,kernel-config:,make-tarball:,kernel-name:,kernel-version:,kernel-extraversion:,remove-splash,no-clean,menuconfig,use-own-config" print_help() { cat <<'EOF' Usage: cl-kernel [options] [-c FILE|-o] [destination] Make kernel. Options: -h, --help Print this help message -k, --kerneldir DIR Location of the kernel sources -c, --kernel-config FILE Kernel configuration file to use for compilation -t, --make-tarball FILE Make archive containing kernel,initramfs and modules. -n, --kernel-name NAME Tag the kernel and ramdisk with a name: If not defined the option defaults to 'calculate' -e, --extraversion VER Specify extraversion for kernel -v, --kernel-version VER Specify version for kernel -r, --remove-splash Remove splash images from initramfs. -o, --use-own-config Use config from kernel directory. --no-clean Do not run make clean before compilation --menuconfig Run menuconfig after oldconfig 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 } # Using: rm_link_with_file filename rm_link_with_file() { [[ -L $1 ]] && rm -f `readlink -f $1` rm -f $1 } # Using: cp_link_with_file filename suffix cp_link_with_file() { if [[ -L $1 ]] then rm -f `readlink -f ${1}`$2 cp -aH ${1} `readlink -f ${1}`$2 ln -sf `readlink ${1}`${2} ${1}${2} else rm -f ${1}${2} cp -aH ${1} ${1}${2} fi } # Using: make_old_file filename (result filename.old) # Description: move filename to filename.old (support symlinking) make_old_file() { if [[ -e $1 ]] then rm_link_with_file $1.old cp_link_with_file $1 .old fi rm_link_with_file $1 } 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 } set_kernel_version() { sed -ri "s/^VERSION = .*$/VERSION = $KV_MAJOR/" \ ${KERNEL_DIR}/Makefile sed -ri "s/^PATCHLEVEL = .*$/PATCHLEVEL = $KV_MINOR/" \ ${KERNEL_DIR}/Makefile sed -ri "s/^SUBLEVEL = .*$/SUBLEVEL = $KV_PATCH/" \ ${KERNEL_DIR}/Makefile sed -ri "s/^EXTRAVERSION = .*$/EXTRAVERSION = $KV_TYPE/" \ ${KERNEL_DIR}/Makefile } 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" # remove old initramfs rm ${BOOT_DIR}/initramfs-${KERNEL_NAME}-*-${KERNEL_VERSION} || warning "Cann't remove old initramfs" } initramfs_clean() { # remove sound moudles find -name sound -exec rm -rf {} \; &>/dev/null # remove splash images if need [[ ${REMOVE_SPLASH} == 'true' ]] && rm etc/splash/tty1/images/* >/dev/null } initramfs_pack() { make_old_file ${BOOT_DIR}/initrd # 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" } rename_kernel_systemmap() { # rename kernel (remove arch from name) mv ${BOOT_DIR}/kernel-${KERNEL_NAME}-*-${KERNEL_VERSION} \ ${BOOT_DIR}/linux-${KERNEL_NAME}-${KERNEL_VERSION} || die "Cann't rename kernel" # rename systemmap (remove arch from name) mv ${BOOT_DIR}/System.map-${KERNEL_NAME}-*-${KERNEL_VERSION} \ ${BOOT_DIR}/System.map-${KERNEL_NAME}-${KERNEL_VERSION} || die "Cann't rename System.map" } install_kernel() { make_old_file ${BOOT_DIR}/System.map make_old_file ${BOOT_DIR}/vmlinuz rename_kernel_systemmap # change kernel (make symlink) ln -sf linux-${KERNEL_NAME}-${KERNEL_VERSION} ${BOOT_DIR}/vmlinuz || warning "Cann't make vmlinuz link" # change System.map (make symlink) ln -sf System.map-${KERNEL_NAME}-${KERNEL_VERSION} \ ${BOOT_DIR}/System.map || warning "Cann't make System.map link" # change initramfs (make symlink) ln -sf initramfs-${KERNEL_NAME}-${KERNEL_VERSION} ${BOOT_DIR}/initrd || warning "Cann't make initrd link" # copy config make_old_file ${BOOT_DIR}/config-${KERNEL_NAME}-${KERNEL_VERSION} cp ${KERNEL_CONFIG} ${BOOT_DIR}/config-${KERNEL_NAME}-${KERNEL_VERSION} set_new_current_kernel calculate --initrd } 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 } make_tarball() { rename_kernel_systemmap # remove symlink for tarball find lib -type l -delete || warning "Cann't delete symbolic links" # get some files from kernel sources ABSKERNEL_DIR="$(dirname `readlink -f $KERNEL_DIR/Makefile`)" mkdir -p `pwd`${ABSKERNEL_DIR}/include/linux || die "Cann't create kernel sources directory" pushd `pwd`${ABSKERNEL_DIR} &>/dev/null cp ${ABSKERNEL_DIR}/.config . || die "Cann't copy kernel config" cp ${ABSKERNEL_DIR}/System.map . || die "Cann't copy System.map" cp ${ABSKERNEL_DIR}/Module.symvers . || die "Cann't copy Module.symvers" cd include/linux cp ${ABSKERNEL_DIR}/include/linux/version.h . || die "Cann't copy version header" popd &>/dev/null tar cjf ${KERNEL_TARBALL} boot lib usr || die "Cann't create kernel tarbal" } KERNEL_DIR=/usr/src/linux KERNEL_CONFIG= USE_OWN_CONFIG=false KERNEL_TARBALL= SYSTEMNAME=$(sed -nr '/^system/ s/^[^=]+=(.*)$/\1/p' \ /etc/calculate/calculate.ini) KERNEL_NAME=${SYSTEMNAME} KERNEL_VERSION= DESTINATION= KERNEL_EXTRAVERSION= REMOVE_SPLASH=false ARCH=`arch` NO_INSTALL=false NOCLEAN="" MENUCONFIG="" 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 ;; --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 ;; -t|--make-tarball) KERNEL_TARBALL=$2 shift 2 ;; -r|--remove-splash) REMOVE_SPLASH=true shift ;; -n|--kernel-name) KERNEL_NAME=$2 shift 2 ;; -v|--kernel-version) KERNEL_VERSION=$2 shift 2 ;; -e|--extraversion) KERNEL_EXTRAVERSION=$2 shift 2 ;; --no-install) NO_INSTALL=true shift ;; --) shift ;; *) if [[ -z ${DESTINATION} ]] then DESTINATION=$1 shift else die "unknown second option: $1" fi ;; esac done # check kernel directory [[ -e ${KERNEL_DIR}/Makefile ]] || die "Wrong kernel sources directory: ${KERNEL_DIR}" [[ -z ${DESTINATION} ]] && DESTINATION="/" # if kernel_version not defined get it from Makefile of sources [[ -z ${KERNEL_VERSION} ]] && \ 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} # tarball should be created in empty directory if [[ -n ${KERNEL_TARBALL} ]] && [[ $(ls $DESTINATION | wc -l ) -gt 2 ]]; then die "tarball should be created in empty directory, need specify destination" fi 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} \ --module-prefix=${MODULE_INS_PATH} --makeopts=${MAKEOPTS} \ ${NOCLEAN} ${MENUCONFIG} --no-save-config \ --kernel-config=${KERNEL_CONFIG} --kernname=${KERNEL_NAME} \ --bootdir=${BOOT_DIR} all || die "kernel was not builded" pushd ${DESTINATION} &>/dev/null initramfs_unpack initramfs_clean initramfs_pack # if specified tarball then make archive else install kernel [[ -n ${KERNEL_TARBALL} ]] && make_tarball || install_kernel