#!/usr/bin/env bash
#
# Copyright (c) 2021 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0

set -u

# NOTE: Some env variables are set in the Dockerfile - those that are
# intended to be over-rideable.
export QAT_SRC=~/src/QAT
export ROOTFS_DIR=~/src/rootfs
export GOPATH=~/src/go
export PATH=${PATH}:/usr/local/go/bin:${GOPATH}/bin

kata_repo=github.com/kata-containers/kata-containers
kata_repo_path=${GOPATH}/src/${kata_repo}

grab_qat_drivers()
{
	/bin/echo -e "\n\e[1;42mDownload and extract the drivers\e[0m"
	mkdir -p $QAT_SRC
	cd $QAT_SRC
 	wget $QAT_DRIVER_URL
	if [ ! -f ${QAT_SRC}/${QAT_DRIVER_VER} ];then
		/bin/echo -e "\e[1;41mQAT Driver ${QAT_DRIVER_VER} doesn't exist\e[0m"
		echo "Check https://01.org/intel-quickassist-technology to find the latest"
		echo "QAT driver version, update the Dockerfile, and try again."
		exit 1
	fi
	tar xzf ${QAT_DRIVER_VER}
}

grab_kata_repos()
{
	# Check out all the repos we will use now, so we can try and ensure they use the specified branch
	# Only check out the branch needed, and make it shallow and thus space/bandwidth efficient
	# Use a green prompt with white text for easy viewing
	/bin/echo -e "\n\e[1;42mClone and checkout Kata repo\e[0m"
	[ -d "${kata_repo_path}" ] || git clone --single-branch --branch $KATA_REPO_VERSION --depth=1 https://${kata_repo} ${kata_repo_path}
}

configure_kernel()
{
	cp /input/qat.conf ${kata_repo_path}/tools/packaging/kernel/configs/fragments/common/qat.conf
	# We need yq and go to grab kernel versions etc.
	${kata_repo_path}/ci/install_yq.sh
	${kata_repo_path}/tests/install_go.sh -p
	cd ${kata_repo_path}
	/bin/echo -e "\n\e[1;42mDownload and configure Kata kernel with CRYPTO support\e[0m"
	./tools/packaging/kernel/build-kernel.sh setup
}

build_kernel()
{
	cd ${kata_repo_path}
	LINUX_VER=$(ls -d kata-linux-*)
	sed -i 's/EXTRAVERSION =/EXTRAVERSION = .qat.container/' $LINUX_VER/Makefile
	/bin/echo -e "\n\e[1;42mBuild Kata kernel with CRYPTO support\e[0m"
	./tools/packaging/kernel/build-kernel.sh build
}

build_rootfs()
{
	# Due to an issue with debootstrap unmounting /proc when running in a
	# --privileged container, change into /proc to keep it from being umounted.
	# This should only be done for Ubuntu and Debian based OS's. Other OS
	# distributions had issues if building the rootfs from /proc

	if [ "${ROOTFS_OS}" == "ubuntu" ]; then
		cd /proc
	fi
	/bin/echo -e "\n\e[1;42mDownload ${ROOTFS_OS} based rootfs\e[0m"
	sudo -E SECCOMP=no EXTRA_PKGS='kmod' ${kata_repo_path}/tools/osbuilder/rootfs-builder/rootfs.sh $ROOTFS_OS
}

build_qat_drivers()
{
	/bin/echo -e "\n\e[1;42mCompile driver modules\e[0m"
	cd ${kata_repo_path}
	linux_kernel_path=${kata_repo_path}/${LINUX_VER}
	KERNEL_MAJOR_VERSION=$(awk '/^VERSION =/{print $NF}' ${linux_kernel_path}/Makefile)
	KERNEL_PATHLEVEL=$(awk '/^PATCHLEVEL =/{print $NF}' ${linux_kernel_path}/Makefile)
	KERNEL_SUBLEVEL=$(awk '/^SUBLEVEL =/{print $NF}' ${linux_kernel_path}/Makefile)
	KERNEL_EXTRAVERSION=$(awk '/^EXTRAVERSION =/{print $NF}' ${linux_kernel_path}/Makefile)
 	KERNEL_ROOTFS_DIR=${KERNEL_MAJOR_VERSION}.${KERNEL_PATHLEVEL}.${KERNEL_SUBLEVEL}${KERNEL_EXTRAVERSION}
 	cd $QAT_SRC
	KERNEL_SOURCE_ROOT=${linux_kernel_path} ./configure ${QAT_CONFIGURE_OPTIONS}
	make all -j $(nproc)
}

add_qat_to_rootfs()
{
	/bin/echo -e "\n\e[1;42mCopy driver modules to rootfs\e[0m"
	cd $QAT_SRC
	sudo -E make INSTALL_MOD_PATH=${ROOTFS_DIR} qat-driver-install -j$(nproc --ignore=1)
	sudo cp $QAT_SRC/build/usdm_drv.ko ${ROOTFS_DIR}/lib/modules/${KERNEL_ROOTFS_DIR}/updates/drivers
	sudo depmod -a -b ${ROOTFS_DIR} ${KERNEL_ROOTFS_DIR}
	cd ${kata_repo_path}/tools/osbuilder/image-builder
	/bin/echo -e "\n\e[1;42mBuild rootfs image\e[0m"
	sudo -E ./image_builder.sh ${ROOTFS_DIR}
}

copy_outputs()
{
	/bin/echo -e "\n\e[1;42mCopy kernel and rootfs to the output directory and provide sample configuration files\e[0m"
	mkdir -p ${OUTPUT_DIR} || true
	sudo cp ${linux_kernel_path}/arch/x86/boot/bzImage $OUTPUT_DIR/vmlinuz-${LINUX_VER}_qat
	sudo cp ${linux_kernel_path}/vmlinux $OUTPUT_DIR/vmlinux-${LINUX_VER}_qat
	sudo cp  ${kata_repo_path}/tools/osbuilder/image-builder/kata-containers.img $OUTPUT_DIR
	sudo mkdir -p ${OUTPUT_DIR}/configs || true
	# Change extension from .conf.vm to just .conf and change the SSL section to
	# SHIM so it works with Kata containers
	for f in $QAT_SRC/quickassist/utilities/adf_ctl/conf_files/*.conf.vm; do
		output_conf_file=$(basename -- "$f" .conf.vm).conf
		sudo cp -- "$f" "${OUTPUT_DIR}/configs/${output_conf_file}"
		sudo sed -i 's/\[SSL\]/\[SHIM\]/g' ${OUTPUT_DIR}/configs/${output_conf_file}
	done
	/bin/echo -e "Check the ./output directory for the kernel and rootfs\n"
}

help() {
cat << EOF
Usage: $0 [-h] [options]
   Description:
        This script builds kernel and rootfs artifacts for Kata Containers,
        configured and built to support QAT hardware.
   Options:
        -d,         Enable debug mode
        -h,         Show this help
EOF
}

main()
{
	local check_in_container=${OUTPUT_DIR:-}
	if [ -z "${check_in_container}" ]; then
		echo "Error: 'OUTPUT_DIR' not set" >&2
		echo "$0 should be run using the Dockerfile supplied." >&2
		exit 1
	fi

	local OPTIND
	while getopts "dh" opt;do
		case ${opt} in
		d)
		    set -x
		    ;;
		h)
		    help
		    exit 0;
		    ;;
		?)
		    # parse failure
		    help
		    echo "ERROR: Failed to parse arguments"
		    exit 1
		    ;;
		esac
	done
	shift $((OPTIND-1))

	sudo chown -R qatbuilder:qatbuilder /home/qatbuilder
	grab_qat_drivers
	grab_kata_repos
	configure_kernel
	build_kernel
	build_rootfs
	build_qat_drivers
	add_qat_to_rootfs
	copy_outputs
}

main "$@"