#!/bin/sh set -e KERNFRAG=${KERNFRAG:-/etc/kernfrag} RUNNING_CONFIG=$(mktemp --suffix=-kern-config) zcat /proc/config.gz > "$RUNNING_CONFIG" # We do want to expand tmpdir now rather than later, # and mktemp should give us a path without spaces. # shellcheck disable=SC2064 trap "{ rm $RUNNING_CONFIG; }" EXIT err() { printf "kern: %s\n" "$@" >&2 } errx() { err "$@" exit 1 } need_kernel_source() { test -r Kbuild -a -r Kconfig || errx "current directory does not contain a kernel source tree, refusing" } has_boot_mount() { awk '{print $2}' /etc/fstab | grep -q ^/boot$ } is_boot_mounted() { mountpoint -q /boot } mount_boot_on_demand() { if has_boot_mount && ! is_boot_mounted; then sudo mount /boot fi } get_latest_kernel() { eselect --brief kernel list | tail -n1 } get_selected_kernel() { readlink /usr/src/linux } get_running_kernel() { uname -r } set_kernel() { kern=${1:-$(get_latest_kernel)} selected=$(get_selected_kernel) kerndir=/usr/src/$kern test -d "$kerndir" || errx "No such file or directory: $kerndir" if test "$kern" = "$selected"; then err "Warning: Latest kernel already selected: $kern" return fi printf "Selecting kernel: %s\n" "$kern" sudo eselect kernel set "$kern" sudo chown -R "$(id -un)":"$(id -gn)" "$kerndir" } config_kernel() { need_kernel_source host=${1:-$(hostname)} test -d "$KERNFRAG" || errx "No such file or directory: $KERNFRAG" printf "Starting merge for %s...\n\n" "$host" awk -v prefix="$KERNFRAG/fragments/" '{print prefix $0}' \ "$KERNFRAG/templates/base" "$KERNFRAG/templates/$host" | xargs scripts/kconfig/merge_config.sh } diff_kernel() { need_kernel_source diff=${1:-$RUNNING_CONFIG} if command -v git >/dev/null; then git diff --no-index "$diff" .config else diff -u "$diff" .config fi } build_kernel() { need_kernel_source make -j"$(nproc)" } install_kernel() { need_kernel_source mount_boot_on_demand sudo make install modules_install } post_install_kernel() { sudo emerge --ask=n @module-rebuild } clean_kernel() { sudo eclean-kernel -An3 } strip_config() { sed -nE '/^(# )?CONFIG_.*/p' "$1" } test_diff() { dt=$(mktemp) strip_config "$RUNNING_CONFIG" > "$dt" if ! strip_config .config | diff -q "$dt" -; then diff_kernel || true printf "Continue? [y/N] " read -r response if test "$response" != "y"; then rm "$dt" return 1 fi fi rm "$dt" } all() { set_kernel cd /usr/src/linux config_kernel test_diff build_kernel install_kernel post_install_kernel clean_kernel } if test $# -eq 0; then all exit 0 fi cmd=$1 shift case $cmd in set) set_kernel "$@";; config) config_kernel "$@";; diff) diff_kernel "$@";; build) build_kernel;; install) install_kernel;; postinst) post_install_kernel;; clean) clean_kernel;; all) all;; esac