#!/bin/bash # $Id$ PATH="${PATH}:/sbin:/usr/sbin" GK_V='4.0.7' GK_TIME_START=$(date +%s) TODEBUGCACHE=yes # Until an error occurs or LOGFILE is fully qualified. small_die() { echo "ERROR: $*" >&2 exit 1 } # We don't know where our config is, so we check for it, and default to using # /etc/genkernel.conf if nobody has specified one. # NOTE: We are look for --config=... in a way that doesn't modify $@ since we access that again, later for arg in "$@" do [[ "${arg}" == --config=* ]] && CMD_GK_CONFIG=${arg#--config=} done # Pull in our configuration to get GK_SHARE only... _GENKERNEL_CONF=${CMD_GK_CONFIG:-/etc/genkernel.conf} GK_SHARE=$(source "${_GENKERNEL_CONF}" &>/dev/null && echo ${GK_SHARE}) if [ -z "${GK_SHARE}" ] then small_die "GK_SHARE is not set. Please check used genkernel config file at '${_GENKERNEL_CONF}'!" fi # Make sure that we do not clash with the environment GK_DETERMINEARGS_FILE="${GK_SHARE}/gen_determineargs.sh" GK_SETTINGS=( $(awk '/[^#]set_config_with_override/ { print $3 }' "${GK_DETERMINEARGS_FILE}" 2>/dev/null) ) if [ ${#GK_SETTINGS[@]} -gt 0 ] then GK_SETTINGS+=( CALLBACK ) GK_SETTINGS+=( EXTRAVERSION ) GK_SETTINGS+=( MOD_INSTALL ) for GK_SETTING in "${GK_SETTINGS[@]}" do if [[ "${GK_SETTING}" == "MAKEOPTS" ]] then continue fi for var_to_unset in ${GK_SETTING} CMD_${GK_SETTING} do if [ -n "${!var_to_unset}" ] then echo "WARNING: Will unset existing variable '${var_to_unset}' to avoid clashing with genkernel config ..." >&2 unset ${var_to_unset} || small_die "Failed to unset existing variable '${var_to_unset}'!" fi done done unset GK_DETERMINEARGS_FILE GK_SETTINGS GK_SETTING var_to_unset else small_die "Failed to extract genkernel options from '${GK_DETERMINEARGS_FILE}'!" fi # Now we can source our configuration... source "${_GENKERNEL_CONF}" || small_die "Could not read ${_GENKERNEL_CONF}" # set default LOGLEVEL if uninitialized LOGLEVEL=${LOGLEVEL:-1} # Start sourcing other scripts source "${GK_SHARE}"/defaults/software.sh || small_die "Could not read '${GK_SHARE}/defaults/software.sh'" source "${GK_SHARE}"/defaults/config.sh || small_die "Could not read '${GK_SHARE}/defaults/config.sh'" source "${GK_SHARE}"/gen_funcs.sh || small_die "Could not read '${GK_SHARE}/gen_funcs.sh'" source "${GK_SHARE}"/gen_cmdline.sh || small_die "Could not read '${GK_SHARE}/gen_cmdline.sh'" source "${GK_SHARE}"/gen_arch.sh || small_die "Could not read '${GK_SHARE}/gen_arch.sh'" source "${GK_SHARE}"/gen_determineargs.sh || small_die "Could not read '${GK_SHARE}/gen_determineargs.sh'" source "${GK_SHARE}"/gen_compile.sh || small_die "Could not read '${GK_SHARE}/gen_compile.sh'" source "${GK_SHARE}"/gen_configkernel.sh || small_die "Could not read '${GK_SHARE}/gen_configkernel.sh'" source "${GK_SHARE}"/gen_initramfs.sh || small_die "Could not read '${GK_SHARE}/gen_initramfs.sh'" source "${GK_SHARE}"/gen_moddeps.sh || small_die "Could not read '${GK_SHARE}/gen_moddeps.sh'" source "${GK_SHARE}"/gen_package.sh || small_die "Could not read '${GK_SHARE}/gen_package.sh'" source "${GK_SHARE}"/gen_bootloader.sh || small_die "Could not read '${GK_SHARE}/gen_bootloader.sh'" export GK_MASTER_PID=${BASHPID} set_default_gk_trap BUILD_KERNEL="no" BUILD_RAMDISK="no" BUILD_MODULES="no" # Parse all command line options... GK_OPTIONS=$* # Save for later while [ $# -gt 0 ] do GK_OPTION=$1; shift parse_cmdline ${GK_OPTION} done unset GK_OPTION # Check if no action is specified... if ! isTrue "${BUILD_KERNEL}" && ! isTrue "${BUILD_RAMDISK}" then usage exit 1 fi NORMAL=${GOOD} print_info 1 "Gentoo Linux Genkernel; Version ${GK_V}${NORMAL}" print_info 1 "Using genkernel configuration from '${_GENKERNEL_CONF}' ..." unset _GENKERNEL_CONF print_info 1 "Running with options: ${GK_OPTIONS}" if ! hash grep &>/dev/null then gen_die "grep not found. Is sys-apps/grep installed?" fi if ! hash zgrep &>/dev/null then print_warning 1 "zgrep not found. Is app-arch/gzip installed? You will be unable to use compressed config files!" fi # Save any customizations of MODULES_* first. override_module_vars="$(compgen -A variable |grep '^MODULES_')" for v in ${override_module_vars} do print_info 2 "Saving ${v} to override defaults" newvar=override_${v} eval "${newvar}='${!v}'" done determine_real_args if isTrue "${BUILD_RAMDISK}" && ! isTrue "${SANDBOX}" then print_warning 1 '' 1 0 print_warning 1 "${BOLD}WARNING:${NORMAL} Will build initramfs ${BOLD}without${NORMAL} sandbox support " 0 SANDBOX_WARNING_TIMER=0 while [[ ${SANDBOX_WARNING_TIMER} -lt 5 ]] do printf '.' sleep 1 let SANDBOX_WARNING_TIMER=${SANDBOX_WARNING_TIMER}+1 done print_warning 1 '' 1 0 fi print_info 2 '' 1 0 print_info 2 "Sourcing default modules_load from '${GK_SHARE}/defaults/modules_load' ..." source "${GK_SHARE}/defaults/modules_load" || gen_die "Could not read '${GK_SHARE}/defaults/modules_load'!" # Read arch-specific config print_info 2 "Sourcing arch-specific config.sh from '${ARCH_CONFIG}' ..." source "${ARCH_CONFIG}" || gen_die "Could not read '${ARCH_CONFIG}'!" _MODULES_LOAD="${GK_SHARE}/arch/${ARCH}/modules_load" if [ -f "${_MODULES_LOAD}" ] then print_info 2 "Sourcing arch-specific modules_load from '${_MODULES_LOAD}' ..." source "${_MODULES_LOAD}" || gen_die "Could not read '${_MODULES_LOAD}'!" else print_info 2 "No arch-specific modules_load found; Skipping ..." fi unset _MODULES_LOAD # Now apply customizations of MODULES_* for v in ${override_module_vars} do newvar=override_${v} print_info 2 "Override ${v}, default (${!v}), new value (${!newvar})" eval "${v}='${!newvar}'" done unset v override_module_vars newvar # Merge additional modules_load from config for group_modules in ${!AMODULES_*} do group="$(echo ${group_modules} | cut -d_ -f2)" eval cmodules="\$${group_modules}" eval MODULES_${group}=\"\${MODULES_${group}} ${cmodules}\" print_info 2 " Merged AMODULES_${group}:'${cmodules}' into MODULES_${group}" done unset group group_modules determine_KV # $KV is now either set to the version from previous compilation, # which would include LOCALVERSION suffix, or initialized with # unmodified KERNEL_SOURCE version (which normally has no LOCALVERSION set). determine_kernel_arch determine_output_filenames determine_kernel_config_file setup_cache_dir check_distfiles KERNCACHE_IS_VALID="no" if [ -n "${KERNCACHE}" ] then gen_kerncache_is_valid fi if isTrue "${KERNCACHE_IS_VALID}" && ! isTrue "${CMD_INSTALL}" && ! isTrue "${BUILD_RAMDISK}" then error_msg="Nothing to do: Selected action does not include building initramfs." error_msg+=" Because kerncache is valid, no kernel will be build." error_msg+=" However, due to set --no-install option, we will not even install kernel binary from kerncache." gen_die "${error_msg}" fi print_info 1 '' 1 0 print_info 1 "Working with Linux kernel ${BOLD}${KV}${NORMAL} for ${BOLD}${ARCH}${NORMAL}" print_info 1 "Using kernel config file '${KERNEL_CONFIG}' ..." if isTrue "${BUILD_KERNEL}" && ! isTrue "${KERNCACHE_IS_VALID}" then print_info 1 '' print_info 1 "Note: The version above is subject to change (depends on config and status of kernel sources)." fi isTrue "${CMD_INSTALL}" && make_bootdir_writable check_disk_space_requirements if isTrue "${BUILD_KERNEL}" && ! isTrue "${KERNCACHE_IS_VALID}" then print_info 1 '' 1 0 # Configure kernel config_kernel # Make prepare if ! isTrue "${ARCH_HAVENOPREPARE}" then compile_generic prepare kernel else print_info 2 "$(get_indent 1)>> Skipping 'make prepare' due to ARCH_HAVENOPREPARE=yes!" fi # KV may have changed due to the configuration determine_KV if [ -f "${TEMP}/.old_kv" ] then determine_output_filenames old_KV=$(cat "${TEMP}/.old_kv") print_info 1 "$(get_indent 1)>> Kernel version has changed (probably due to config change) since genkernel start:" print_info 1 "$(get_indent 1) We are now building Linux kernel ${BOLD}${KV}${NORMAL} for ${BOLD}${ARCH}${NORMAL} ..." else print_info 2 "$(get_indent 1)>> Kernel version has not changed since genkernel start" fi if isTrue "${INTEGRATED_INITRAMFS}" then compile_kernel no else compile_kernel yes fi # Compile modules if isTrue "${BUILD_MODULES}" && ! isTrue "${BUILD_STATIC}" then compile_modules compile_external_modules fi if isTrue "${SAVE_CONFIG}" then print_info 1 "$(get_indent 1)>> Saving config of successful build to '/etc/kernels/${GK_FILENAME_CONFIG}' ..." [ ! -e '/etc/kernels' ] && mkdir -p /etc/kernels cp "${KERNEL_OUTPUTDIR}/.config" "/etc/kernels/${GK_FILENAME_CONFIG}" || \ print_warning 1 "Unable to copy the kernel configuration file; Ignoring non-fatal error ..." # Just a warning because ordinary users are not allowed to write in /etc fi elif [[ -n "${KERNEL_LOCALVERSION}" && "${KERNEL_LOCALVERSION}" != "${LOV}" ]] then if [[ "${KERNEL_LOCALVERSION}" == "UNSET" && -z "${LOV}" ]] then # LOV is already unset... : else print_warning 1 '' 1 0 print_warning 1 "Current kernel's LOCALVERSION is set to '${LOV}'; Will ignore set --kernel-localversion value '${KERNEL_LOCALVERSION}' because kernel was not build ..." fi fi if isTrue "${KERNCACHE_IS_VALID}" then if isTrue "${CMD_INSTALL}" then print_info 1 '' 1 0 gen_kerncache_extract_kernel fi if ! isTrue "${BUILD_STATIC}" then if ! isTrue "${CMD_INSTALL}" && [ -z "${INSTALL_MOD_PATH}" ] then # We have to set $INSTALL_MOD_PATH to avoid installing files # to /lib/modules because --no-install was set INSTALL_MOD_PATH="$(mktemp -d -p "${TEMP}" kerncache-modules_XXXXXXX 2>/dev/null)" if [ -z "${INSTALL_MOD_PATH}" ] then gen_die "Internal error: Variable 'INSTALL_MOD_PATH' is empty; mktemp() for kerncache modules failed!" else print_info 5 '' 1 0 print_info 5 "INSTALL_MOD_PATH set to '${INSTALL_MOD_PATH}' because --kerncache is used but --no-install was set ..." mkdir "${INSTALL_MOD_PATH}/lib" || gen_die "Failed to create '${INSTALL_MOD_PATH}/lib'!" fi fi print_info 1 '' 1 0 gen_kerncache_extract_modules fi if isTrue "${SAVE_CONFIG}" then print_info 1 '' 1 0 gen_kerncache_extract_config fi fi # Run callback if [ -n "${CMD_CALLBACK}" ] then print_info 1 '' 1 0 print_info 1 "Preparing to run callback: \"${CMD_CALLBACK}\"" 0 CALLBACK_ESCAPE=0 CALLBACK_COUNT=0 trap "CALLBACK_ESCAPE=1" TERM KILL INT QUIT ABRT while [[ "${CALLBACK_ESCAPE}" -eq 0 && ${CALLBACK_COUNT} -lt 5 ]] do sleep 1; printf '.'; let CALLBACK_COUNT=${CALLBACK_COUNT}+1 done if [ "${CALLBACK_ESCAPE}" -eq 0 ] then print_info 1 '' 1 0 print_info 1 '' 1 0 eval ${CMD_CALLBACK} | tee -a "${LOGFILE}" CMD_STATUS="${PIPESTATUS[0]}" print_info 1 '' 1 0 print_info 1 "<<< Callback exit status: ${CMD_STATUS}" [ "${CMD_STATUS}" -ne 0 ] && gen_die '--callback failed!' else print_warning 1 '' 1 0 print_warning 1 ">>> Callback cancelled ..." fi # restore default trap set_default_gk_trap fi if isTrue "${BUILD_RAMDISK}" then print_info 1 '' 1 0 # Compile initramfs create_initramfs else print_info 1 '' 1 0 print_info 1 "initramfs: >> Not building since only the kernel was requested ..." fi if isTrue "${INTEGRATED_INITRAMFS}" then print_info 1 '' 1 0 cfg_CONFIG_INITRAMFS_SOURCE=$(kconfig_get_opt "${KERNEL_OUTPUTDIR}/.config" "CONFIG_INITRAMFS_SOURCE") if [[ "${cfg_CONFIG_INITRAMFS_SOURCE}" != "\"${CPIO_ARCHIVE}.cpio\"" ]] then gen_die "Sanity check failed: CONFIG_INITRAMFS_SOURCE is not set to '${CPIO_ARCHIVE}.cpio' in '${KERNEL_OUTPUTDIR}/.config'!" fi unset cfg_CONFIG_INITRAMFS_SOURCE # We build the kernel a second time to include the initramfs compile_kernel yes fi if [ -n "${KERNCACHE}" ] then if ! isTrue "${KERNCACHE_IS_VALID}" then # Only update KERNCACHE when KERNCACHE wasn't used because # when it was used nothing has been changed so no update is # necessary. print_info 1 '' 1 0 gen_kerncache else print_info 3 '' 1 0 print_info 3 "kerncache: >> Existing kerncache was used and kernel/modules therefore didn't change; Skipping '${KERNCACHE}' generation ..." fi fi if [ -n "${MINKERNPACKAGE}" ] then print_info 1 '' 1 0 gen_minkernpackage fi if [ -n "${MODULESPACKAGE}" ] then print_info 1 '' 1 0 gen_modulespackage fi if isTrue "${BUILD_KERNEL}" then show_warning_initramfs_is_required=yes print_info 1 '' 1 0 print_info 1 'Kernel compiled successfully!' if isTrue "${CMD_INSTALL}" then set_bootloader # When we have installed kernel and initramfs *and* # updated bootloader, we can assume that initramfs will # be used... case "${BOOTLOADER}" in grub) show_warning_initramfs_is_required=no ;; grub2) show_warning_initramfs_is_required=no ;; esac else print_info 1 '' if ! isTrue "${KERNCACHE_IS_VALID}" then print_info 1 "You will find the kernel image in '${TMPDIR}/${GK_FILENAME_TEMP_KERNEL}'." if isTrue "${GENZIMAGE}" then print_info 1 "You will find the kernelz binary in '${TMPDIR}/${GK_FILENAME_TEMP_KERNELZ}'." fi fi if isTrue "${BUILD_RAMDISK}" then if isTrue "${INTEGRATED_INITRAMFS}" then show_warning_initramfs_is_required=no print_info 1 "Initramfs is integrated into kernel image." else print_info 1 "You will find the initramfs in '${TMPDIR}/${GK_FILENAME_TEMP_INITRAMFS}'." fi fi fi if isTrue "${CMD_INSTALL}" || ! isTrue "${KERNCACHE_IS_VALID}" then print_info 1 '' print_info 1 'Required kernel parameter:' print_info 1 '' print_info 1 ' root=/dev/$ROOT' print_info 1 '' print_info 1 'Where $ROOT is the device node for your root partition as the' print_info 1 'one specified in /etc/fstab' if isTrue "${INTEGRATED_INITRAMFS}" && isTrue "${BUILD_RAMDISK}" then show_warning_initramfs_is_required=no print_info 1 '' print_info 1 "Initramfs is integrated into kernel image." fi fi if isTrue "${show_warning_initramfs_is_required}" && isTrue "${BUILD_RAMDISK}" then INITRAMFS_FILE="${TMPDIR}/${GK_FILENAME_TEMP_INITRAMFS}" isTrue "${CMD_INSTALL}" && INITRAMFS_FILE="${BOOTDIR}/${GK_FILENAME_INITRAMFS}" print_warning 1 '' 1 0 print_warning 1 "If you require Genkernel's hardware detection features, you ${BOLD}MUST${NORMAL}" print_warning 1 "tell your bootloader to use the provided initramfs file '${INITRAMFS_FILE}'." unset INITRAMFS_FILE fi unset show_warning_initramfs_is_required fi if isTrue "${BUILD_RAMDISK}" then if ! isTrue "${BUILD_KERNEL}" then INITRAMFS_FILE="${TMPDIR}/${GK_FILENAME_TEMP_INITRAMFS}" isTrue "${CMD_INSTALL}" && INITRAMFS_FILE="${BOOTDIR}/${GK_FILENAME_INITRAMFS}" print_info 1 '' print_info 1 "You will find the initramfs in '${INITRAMFS_FILE}'." unset INITRAMFS_FILE fi print_warning 1 '' 1 0 print_warning 1 "${BOLD}WARNING... WARNING... WARNING...${NORMAL}" print_warning 1 'Additional kernel parameters that *may* be required to boot properly:' isTrue "${SPLASH}" && print_warning 1 "- Add \"vga=791 splash=silent,theme:${SPLASH_THEME} console=tty1 quiet\" if you use a splash framebuffer ]" isTrue "${BCACHE}" && print_warning 1 '- Add "dobcache" for bcache support' isTrue "${BTRFS}" && print_warning 1 '- Add "dobtrfs" for Btrfs device scanning support' isTrue "${MULTIPATH}" && print_warning 1 '- Add "domultipath" for multipath support' isTrue "${ISCSI}" && print_warning 1 '- For iSCSI support, add at least:' isTrue "${ISCSI}" && print_warning 1 ' - "iscsi_initiatorname="' isTrue "${ISCSI}" && print_warning 1 ' - "iscsi_target="' isTrue "${ISCSI}" && print_warning 1 ' - "iscsi_address="' isTrue "${DMRAID}" && print_warning 1 '- Add "dodmraid" for dmraid support or "dodmraid="' isTrue "${MDADM}" && print_warning 1 '- Add "domdadm" for MDRAID support' isTrue "${LVM}" && print_warning 1 '- Add "dolvm" for LVM support' isTrue "${LUKS}" && print_warning 1 '- Add "crypt_root=" for LUKS-encrypted root' isTrue "${LUKS}" && print_warning 1 '- Add "crypt_swap=" for LUKS-encrypted swap' isTrue "${SSH}" && print_warning 1 '- Add "dosshd" to start SSH daemon in initramfs' if isTrue "${ZFS}" then print_warning 1 '- Add "dozfs" for ZFS volume management support' print_warning 1 ' and either "root=ZFS" to use bootfs autodetection or "root=ZFS="' print_warning 1 ' to force booting from a specific dataset' print_warning 1 '' if [ -f "${TEMP}/.embedded_hostid" ] then saved_hostid=$(cat "${TEMP}/.embedded_hostid") print_warning 1 "Hostid '${saved_hostid}' is embedded into initramfs." print_warning 1 "If you will use this initramfs for a different system you MUST set 'spl_hostid=' parameter to overwrite embedded hostid!" unset saved_hostid else print_warning 1 "No hostid embedded into initramfs. You MUST set 'spl_hostid=' parameter to provide hostid for ZFS!" fi print_warning 1 '' print_warning 1 'If importing ZFS pool is slow, add dozfs=cache or dozfs=force to kernel commandline.' print_warning 1 '"man genkernel" explains "dozfs" in detail.' fi if isTrue "$(is_gzipped "${KERNEL_CONFIG}")" then # Support --kernel-config=/proc/config.gz, mainly CONFGREP=zgrep else CONFGREP=grep fi if [ $(${CONFGREP} 'CONFIG_EXT[0-9]_FS=' "${KERNEL_CONFIG}" | wc -l) -ge 2 ] then print_warning 1 '' print_warning 1 'With support for several ext* filesystems available, it may be needed to' print_warning 1 'add "rootfstype=ext3" or "rootfstype=ext4" to the list of boot parameters.' fi unset CONFGREP fi isTrue "${CMD_INSTALL}" && restore_boot_mount_state print_info 1 '' 1 0 print_info 1 'Do NOT report kernel bugs as genkernel bugs unless your bug' print_info 1 'is about the default genkernel configuration...' print_info 1 '' print_info 1 'Make sure you have the latest ~arch genkernel before reporting bugs.' # Final Cleanup cleanup