#!/usr/bin/env bash set -o nounset set -o errexit set -o errtrace ktest_dir=$(dirname "$(readlink -f "$0")") KTEST=$ktest_dir/ktest . "$ktest_dir/lib/libktest.sh" checkdep gcc checkdep make checkdep bison checkdep flex checkdep bc ktest_kernel_source="." # dir of kernel source # set with: -k # defaults: current directory ktest_njobs=$(nproc) ktest_precise=false COVERAGE="" # doing code coverage? MAKEARGS=() DEPMOD=depmod if ! which depmod > /dev/null; then DEPMOD=/sbin/depmod fi usage() { echo "build-test-kernel: Run generic virtual machine tests" echo "Usage: build-test-kernel cmd [options]" ktest_usage_cmds echo " oldconfig Run make oldconfig" echo " config Run make nconfig" echo echo " options:" ktest_usage_opts echo echo " options for build-test-kernel run:" ktest_usage_run_opts echo " -k kernel source dir" echo " -c enable coverage for this dir (only valid without -K)" echo " -M Extra arguments to be passed to make when building the kernel" echo ktest_usage_post } if [[ $# = 0 ]]; then usage exit 1 fi #parse command and shift for rest of arg parsing CMD="$1" shift while getopts "k:Pc:M:h${ktest_args}" arg; do case $arg in k) ktest_kernel_source="$OPTARG" ;; P) ktest_precise=true ;; c) if [[ ! -d $OPTARG ]]; then echo "$OPTARG must be a directory" exit 1 fi checkdep lcov # Strip trailing / from directory name, substitute _ for / OPTARG=$(echo "${OPTARG%/}"|tr / _) MAKEARGS+=("GCOV_PROFILE_$OPTARG=y") COVERAGE=1 ;; M) MAKEARGS+=("$OPTARG") ;; h) usage exit 0 ;; esac parse_ktest_arg $arg done shift $(( OPTIND - 1 )) parse_args_post # default parameters [[ -z $ktest_kernel_source ]] && ktest_kernel_source="." if [[ ! -d $ktest_kernel_source ]]; then echo "kernel source directory $ktest_kernel_source does not exist" exit 1 fi ktest_kernel_source=$(readlink -e "$ktest_kernel_source") ktest_kernel_build="$ktest_out/kernel_build.$ktest_arch" mkdir -p "$ktest_kernel_build" if [[ -n $CROSS_COMPILE ]]; then checkdep "$ARCH_TRIPLE-gcc" "gcc-$ARCH_TRIPLE" fi run_ktest() { arg=$1 shift "$KTEST" "$arg" $KTESTARGS "$@" } do_make() { if [[ -n $CROSS_COMPILE ]]; then export ARCH="$KERNEL_ARCH" export CROSS_COMPILE="$ARCH_TRIPLE-" fi make --jobs="$ktest_njobs" \ --directory="$ktest_kernel_source" \ O="$ktest_kernel_build" \ INSTALL_MOD_PATH="$ktest_kernel_binary" \ "${ktest_kernel_make_append[@]}" \ "${MAKEARGS[@]}" \ "$@" } new_config() { local kconfig="$ktest_kernel_build/.config" local config_tool="$ktest_kernel_source/scripts/config" if [[ ! -f $kconfig ]]; then do_make allnoconfig # Really undefine everything: sed -i -e 's/\(CONFIG_.*\)=.*/# \1 is not set/' "$kconfig" fi } kernel_opt() { local cmd=$1 local opt=$2 local kconfig="$ktest_kernel_build/.config" local config_tool="$ktest_kernel_source/scripts/config" local val=y if [[ $opt =~ = ]]; then local val=${opt#*=} opt="${opt%=*}" fi case $cmd in set) "$config_tool" --file "$kconfig" --set-val "$opt" "$val" ;; check) local c=$("$config_tool" --file "$kconfig" -s "$opt") [[ $c = undef ]] && c=n if [[ $c != $val ]]; then echo "Kernel config option $opt is $c; should be $val" exit 1 fi ;; esac } build_kernel() { rm -rf "$ktest_kernel_binary" mkdir -p "$ktest_kernel_binary" local kconfig="$ktest_kernel_build/.config" if $ktest_precise && [[ -f "$kconfig" ]]; then mv "$kconfig" "$kconfig".bak fi new_config log_verbose "kernel_config_require: ${ktest_kernel_config_require[@]}" MAKEARGS+=("LOCALVERSION=-ktest") for opt in "${ktest_kernel_config_require[@]}"; do [[ -n $opt ]] && kernel_opt set "$opt" done do_make olddefconfig for opt in "${ktest_kernel_config_require[@]}"; do [[ -n $opt ]] && kernel_opt check "$opt" done # Preserve timestamp if config didn't change: if $ktest_precise && [[ -f "$kconfig".bak ]] && diff -q "$kconfig" "$kconfig".bak; then mv "$kconfig".bak "$kconfig" fi case $KERNEL_ARCH in mips) do_make -k vmlinuz ;; *) do_make -k ;; esac local BOOT=$ktest_kernel_build/arch/$KERNEL_ARCH/boot case $ktest_arch in x86*) install -m0644 "$BOOT/bzImage" "$ktest_kernel_binary/vmlinuz" ;; aarch64) install -m0644 "$BOOT/Image" "$ktest_kernel_binary/vmlinuz" ;; mips) install -m0644 "$BOOT/vmlinux.strip" "$ktest_kernel_binary/vmlinuz" #install -m0644 "$ktest_kernel_build/vmlinux" "$ktest_kernel_binary/vmlinuz" ;; default) echo "Don't know how to install kernel" exit 1 ;; esac install -m0644 "$ktest_kernel_build/vmlinux" "$ktest_kernel_binary/vmlinux" install -m0644 "$ktest_kernel_build/.config" "$ktest_kernel_binary/config" # if there weren't actually any modules selected, make modules_install gets # confused: touch "$ktest_kernel_build/modules.order" touch "$ktest_kernel_build/modules.builtin" do_make modules_install local kernel_version=$(cat "$ktest_kernel_build/include/config/kernel.release") $DEPMOD -b "$ktest_kernel_binary/" -v $kernel_version } cmd_run() { if [[ $# = 0 ]]; then echo "build-test-kernel: missing test" usage exit 1 fi ktest_test=$(realpath "$1") shift ktest_testargs="$@" echo Running test $(basename "$ktest_test") on $(uname -n) at $(pwd) parse_test_deps "$ktest_test" if [[ -n $COVERAGE ]]; then ktest_kernel_config_require+=(GCOV_KERNEL) fi run_quiet "building kernel" build_kernel start_vm } cmd_boot() { cmd_run "$ktest_dir/boot.ktest" } cmd_oldconfig() { new_config do_make oldconfig } cmd_config() { new_config do_make nconfig } cmd_faddr2line() { ./scripts/faddr2line "$ktest_kernel_build/vmlinux" $@ } cmd_help() { usage } if [[ $(type -t "cmd_$CMD") == function ]]; then CMD="cmd_$CMD" elif [[ $(type -t "ktest_$CMD") == function ]]; then CMD="ktest_$CMD" else usage exit 1 fi $CMD "$@"