#!/bin/sh

#
# File: build-driver
#
# Description: script to build the SEP driver
#
# Version: 1.7
#
# Copyright(C) 2008 Intel Corporation.  All Rights Reserved.
#
#     This file is part of SEP Development Kit
#
#     SEP Development Kit is free software; you can redistribute it
#     and/or modify it under the terms of the GNU General Public License
#     version 2 as published by the Free Software Foundation.
#
#     SEP Development Kit is distributed in the hope that it will be useful,
#     but WITHOUT ANY WARRANTY; without even the implied warranty of
#     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#     GNU General Public License for more details.
#
#     You should have received a copy of the GNU General Public License
#     along with SEP Development Kit; if not, write to the Free Software
#     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
#
#     As a special exception, you may use this file as part of a free software
#     library without restriction.  Specifically, if other files instantiate
#     templates or use macros or inline functions from this file, or you compile
#     this file and link it with other files to produce an executable, this
#     file does not by itself cause the resulting executable to be covered by
#     the GNU General Public License.  This exception does not however
#     invalidate any other reasons why the executable file might be covered by
#     the GNU General Public License.
#

# set the path to include "standard" locations so commands below can be found

PATH="/sbin:/usr/sbin:/usr/local/sbin:/bin:/usr/bin/:/usr/local/sbin:/usr/local/bin:/usr/local/gnu/bin:.:"${PATH}""
export PATH

print_err()
{
  MSG="$*"
  if [ -w /dev/stderr ]; then
      if [ ! -S /dev/stderr ] ; then
          echo "$MSG" >> /dev/stderr
      else
          echo "$MSG" >&2
      fi
  else
    echo "$MSG"
  fi
}

# ------------------------------ COMMANDS ------------------------------------

CUT="cut"
ECHO="echo"
GREP="grep"
HEAD="head"
SED="sed"
UNAME="uname"
WHICH="which"
TR="tr"
CAT="cat"
RPMBUILD="rpmbuild"

COMMANDS_TO_CHECK="${CUT} ${GREP} ${HEAD} ${UNAME} ${WHICH} ${TR} ${CAT}"

# if any of the COMMANDS_TO_CHECK are not executable, then exit script

OK="true"
for c in ${COMMANDS_TO_CHECK} ; do
  CMD=`${WHICH} $c 2>&1` ;
  ret_val=$?
  if [ ${ret_val} -ne 0 ] ; then
    OK="false"
    print_err "ERROR: unable to find command \"$c\" !"
  fi
done
if [ ${OK} != "true" ] ; then
  echo "Please add the above commands to your PATH and re-run the script ... exiting."
  exit 255
fi

# ------------------------------ CONSTANTS -----------------------------------

# basic name of driver
DRIVER_NAME=sep5
TOOL_VERSION=1.0.0

UBUNTU="Ubuntu"
FEDORA="Fedora"
REDHAT="Red Hat"
OPENSUSE="openSUSE"
SLES="SLES"
CENTOS="CentOS"
DEBIAN="Debian"
CLEARLNX="Clear Linux OS"
OSLIST_TO_CHECK="${UBUNTU} ${FEDORA} ${REDHAT} ${OPENSUSE} ${CENTOS} ${SLES} ${DEBIAN} ${CLEARLNX}"
DASHES="--------------------"

# ------------------------------ VARIABLES -----------------------------------

SCRIPT=$0
SCRIPT_ARGS="$*"
SCRIPT_DIR=`dirname "$SCRIPT"`
PLATFORM=`${UNAME} -m`
KERNEL_VERSION=`${UNAME} -r`
MACHINE_TYPE=`${UNAME} -m`
DRIVER_DIRECTORY=$PWD
DRIVER_SOURCE_DIRECTORY=$PWD
PER_USER_MODE="NO"
NMI_MODE="YES"
MINLOG_MODE="NO"
MAXLOG_MODE="NO"
UDEV_AVAILABLE="YES"
CURRENT_DIST="Unknown"
FEDORA_VERSION=""
PACKAGE_MANAGER="yum"
BUILD_PMT="YES"
DRIVER_GROUP="vtune"

# ------------------------------ FUNCTIONS -----------------------------------

# function to detect OS Distribution

get_os_distribution()
{
  OUTBUF=`${CAT} /etc/*-release`

  for dist in ${OSLIST_TO_CHECK} ; do
    case ${OUTBUF} in
      *"${dist}"*)
      CURRENT_DIST=${dist}
      break
      ;;
    esac
  done

  if [ "${CURRENT_DIST}" = "Unknown" ] ; then
    OUTBUF=`lsb_release -a`

    for dist in ${OSLIST_TO_CHECK} ; do
      case *"${dist}"* in
        ${OUTBUF})
        CURRENT_DIST=${dist}
        break
        ;;
      esac
    done
  fi

  if [ "${CURRENT_DIST}" = "Unknown" ] ; then
    OUTBUF=`${CAT} /proc/version`

    for dist in ${OSLIST_TO_CHECK} ; do
      case *"${dist}"* in
        ${OUTBUF})
        CURRENT_DIST=${dist}
        break
        ;;
      esac
    done
  fi

  if [ "${CURRENT_DIST}" = "Unknown" ] ; then
    # For Clear Linux
    OUTBUF=`${CAT} /usr/lib/os-release`

    for dist in ${OSLIST_TO_CHECK} ; do
      case *"${dist}"* in
        ${OUTBUF})
        CURRENT_DIST=${dist}
        break
        ;;
      esac
    done
  fi

  if [ ${CURRENT_DIST} = "Red" ] ; then
    CURRENT_DIST=${REDHAT}
  elif [ ${CURRENT_DIST} = "Clear" ] ; then
    CURRENT_DIST=${CLEARLNX}
  elif [ ${CURRENT_DIST} = ${FEDORA} ] ; then
    OUTBUF=`${CAT} /etc/fedora-release`
    FEDORA_VERSION=${OUTBUF//[!0-9]/}

    if [ ${FEDORA_VERSION} -ge 22 ] ; then
      PACKAGE_MANAGER="dnf"
    fi
  fi
}

# function to show usage and exit

print_usage_and_exit()
{
  err=${1:-0}
  echo ""
  echo "Usage: $0 [ options ]"
  echo ""
  echo " where \"options\" are the following:"
  echo ""
  echo "    --help | -h"
  echo "      prints out usage"
  echo ""
  echo "    --non-interactive | -ni"
  echo "      attempts to automatically build the driver using"
  echo "      default values without prompting for user input"
  echo ""
  echo "    --print-driver-name"
  echo "      returns the name of the driver that would be built"
  echo "      based on the current running kernel"
  echo ""
  echo "    --install-dir=path"
  echo "      \"path\" is an existing, writable directory where the"
  echo "      driver will be copied after it is successfully built;"
  echo "      this defaults to \"${DRIVER_DIRECTORY}\""
  echo ""
  echo "    --print-kernel-checksum"
  echo "      returns kernel checksum information for running kernel;"
  echo "      this can be used to verify driver/kernel compatibility"
  echo ""
  echo "    --kernel-file=file"
  echo "      \"file\" is pathname of kernel file for currently"
  echo "      running kernel; used for comparing kernel checksums;"
  echo "      this can be either compressed (vmlinuz) or"
  echo "      uncompressed (vmlinux) kernel file, but must be the"
  echo "      kernel that was booted; this defaults to \"/boot/vmlinuz-${KERNEL_VERSION}\""
  echo ""
  echo "    --kernel-version=version"
  echo "      \"version\" is version string of kernel that should"
  echo "      be used for checksum or for building the driver;"
  echo "      this defaults to \"${KERNEL_VERSION}\""
  echo ""
  echo "    --kernel-src-dir=path"
  echo "      \"path\" directory of the configured kernel source tree;"
  echo "      several paths are searched to find a suitable default,"
  echo "      including \"/lib/modules/${KERNEL_VERSION}/{source,build}\","
  echo "      \"/usr/src/linux-${KERNEL_VERSION}\", and \"/usr/src/linux\""
  echo ""
  echo "    --c-compiler=c_compiler"
  echo "      \"c_compiler\" is the C compiler used to compile the kernel;"
  echo "      this defaults to \"gcc\""
  echo ""
  echo "    --make-command=make_command"
  echo "      \"make_command\" is the make command used to build the kernel;"
  echo "      this defaults to \"make\""
  echo ""
  echo "    --make-args=args"
  echo "      arguments to pass to make command (e.g., \"-n\" causes all make"
  echo "      commands to be shown but does not actually carry them out,"
  echo "      \"V=1\" shows the detailed build commands, etc.)"
  echo ""
  echo "    --exit-if-driver-exists"
  echo "      exits if a pre-built driver for the current running"
  echo "      kernel exists in the driver install directory"
  echo ""
  echo "    --verbose"
  echo "      Provide detailed messages"
  echo ""
  echo "    --config-file=file"
  echo "      \"file\" is pathname of configuration file to read"
  echo "      default VARIABLE=VALUE entries from; NOTE: order of"
  echo "      this option (relative to the other options) matters"
  echo ""
  echo "    --per-user | -pu"
  echo "      build the driver in secure sampling mode"
  echo ""
  echo "    --no-udev"
  echo "      build the driver for the system with no device manager"
  echo ""
  echo "    --enable-config-check"
  echo "      Enable dependency checks for certain kernel config flags like CONFIG_STACK_VALIDATION."
  echo "      Please use when faced with driver compilation errors."
  echo ""
  echo "    --build-rpm"
  echo "      Build RPM package file for kernel modules"
  echo ""
  echo "    --group=group | -g=group"
  echo "      restricts access to the ${DRIVER_NAME} driver to users in the specified"
  echo "      group; if this option is not provided, the group \"${DRIVER_GROUP}\""
  echo "      will be used"
  echo "      this can only be used with \"--build-rpm\" option"
  echo ""
  echo ""
  exit ${err}
}

# print kernel checksum info for future comparision
# check for kernel file in kernel source tree
#  KERNEL_FILE=${KERNEL_SRC_DIR}/vmlinux
#  KERNEL_FILE=`cat /proc/cmdline | tr ' ' '\n' | grep BOOT_FILE | cut -d '=' -f 2`

print_kernel_checksum()
{
  KERNEL_FILE=$1
  MD5SUM=`${WHICH} ${MD5SUM:-md5sum} 2>&1`

  if [ -x "${MD5SUM}" ] ; then
    if [ -r "${KERNEL_FILE}" ] ; then
      CHECKSUM=`${MD5SUM} ${KERNEL_FILE}`
      echo "${CHECKSUM}  ${kernel_version}  ${MACHINE_TYPE}"
    fi
  fi
}

read_config_file()
{
  CONFIG_FILE=$1
  if [ -r "${CONFIG_FILE}" ] ; then
    driver_install_dir=`${GREP} "^VDK_INSTALL_DIR=" ${CONFIG_FILE} | ${SED} -e s^VDK_INSTALL_DIR=^^`
    c_compiler=`${GREP} "^VDK_C_COMPILER=" ${CONFIG_FILE} | ${SED} -e s^VDK_C_COMPILER=^^`
    make_command=`${GREP} "^VDK_MAKE_COMMAND=" ${CONFIG_FILE} | ${SED} -e s^VDK_MAKE_COMMAND=^^`
    kernel_src_dir=`${GREP} "^VDK_KERNEL_SRC_DIR=" ${CONFIG_FILE} | ${SED} -e s^VDK_KERNEL_SRC_DIR=^^`
    use_kernel_src_dir=1
  else
      print_err ""
      print_err "Warning: unable to access config file \"${CONFIG_FILE}\" ... option ignored ..."
  fi
}

get_first() {
  echo $1
}

# function to suggest installation

print_how_to_install()
{
  package_to_install=$1

  if [ ${package_to_install} = "gcc" -o ${package_to_install} = "make" ] ; then
    print_err ""
    print_err "Please use the following command to install \"${package_to_install}\" on ${CURRENT_DIST}:"
    case ${CURRENT_DIST} in
      ${UBUNTU} | ${DEBIAN})
        print_err "     apt install build-essential"
        ;;
      ${FEDORA})
        print_err "     ${PACKAGE_MANAGER} ${package_to_install}"
        ;;
      ${REDHAT} | ${CENTOS})
        print_err "     yum group install \"Development Tools\""
        ;;
      ${OPENSUSE} | ${SLES})
        print_err "     zypper install ${package_to_install}"
        ;;
      ${CLEARLNX})
        print_err "     swupd bundle-add c-basic"
        ;;
      *)
        print_err "Unknown Linux distribution"
    esac
  else
    if [ $2 = "install" ] ; then
      print_err ""
      print_err "Please use the following command to install kernel header on ${CURRENT_DIST}:"
      INSTALL_ACTION="install"
    else
      print_err "Please use the following command to reinstall kernel header on ${CURRENT_DIST}:"
      if [ ${CURRENT_DIST} = ${OPENSUSE} -o ${CURRENT_DIST} = ${SLES} ] ; then
        INSTALL_ACTION="in -f"
      elif [ ${CURRENT_DIST} = ${UBUNTU} -o ${CURRENT_DIST} = ${DEBIAN} ] ; then
        INSTALL_ACTION="install"
      else
        INSTALL_ACTION="reinstall"
      fi
    fi

    case ${CURRENT_DIST} in
      ${UBUNTU} | ${DEBIAN})
        if [ $2 = "install" ] ; then
          print_err "     apt ${INSTALL_ACTION} linux-headers-$(uname -r)"
        else
          print_err "     apt ${INSTALL_ACTION} --reinstall linux-headers-$(uname -r)"
        fi
        ;;
      ${REDHAT} | ${CENTOS})
        print_err "     yum ${INSTALL_ACTION} kernel-devel-$(uname -r)"
        ;;
      ${FEDORA})
        print_err "     ${PACKAGE_MANAGER} ${INSTALL_ACTION} kernel-devel-$(uname -r)"
        ;;
      ${OPENSUSE} | ${SLES})
        print_err "     zypper search -s kernel-devel (search for kernel version 'uname -r')"
        print_err "     zypper ${INSTALL_ACTION} <kernel-devel-package>"
        ;;
      ${CLEARLNX})
        print_err "swupd search linux-dev (search for kernel version 'uname -r')"
        if [ $2 = "install" ] ; then
          print_err "     swupd bundle-remove linux-dev"
        fi
        print_err "     swupd bundle-add linux-dev"
        ;;
      *)
        print_err "     Unknown Linux distribution"
    esac
  fi

  print_err ""
}

exit_if_file_inaccessible()
{
  proposed_file=$1
  type=$2
  attr=${3:-f}
  # check for executable
  if [ "$attr" = "x" ] ; then
    file=`${WHICH} $proposed_file 2>&1`
    if [ ! -$attr "$file" ] ; then
      print_err "ERROR: \"$proposed_file\" either does not exist or is not an executable!"
      print_how_to_install $type
      exit 111
    fi
  # otherwise assume regular file
  else
    if [ ! -$attr "$proposed_file" ] ; then
      print_err "ERROR: \"$proposed_file\" is either not a file or is not accessible!"
      print_how_to_install $type "install"
      exit 111
    fi
  fi
}

exit_if_directory_inaccessible()
{
  dir=$1
  err=$2
  is_kernel=$3
  if [ ! -d "$dir" ] ; then
    echo ""
    if [ $is_kernel = "kernel_header" ] ; then
      print_err "ERROR: kernel source directory \"$dir\" either does not exist or not a valid kernel source directory."
      print_how_to_install $is_kernel "install"
    else
      print_err "ERROR: \"$dir\" either does not exist or is not a directory!"
    fi
    exit $err
  fi
  if [ ! -r "$dir" ] ; then
    echo ""
    if [ $is_kernel = "kernel_header" ] ; then
      print_err "ERROR: kernel source directory \"$dir\" is not accessible!"
      print_err "Please provide read access to kernel source directory."
    else
      print_err "ERROR: directory \"$dir\" is not accessible!"
    fi
    exit $err
  fi
}

exit_if_wrong_kernel_path()
{
  if [ $use_kernel_src_dir -eq 1 ] ; then
    print_err ""
    print_err "ERROR: Improper Linux kernel source directory \"$kernel_src_dir\" is specified ... exiting."
    print_err ""
    exit 254
  fi
}

non_interactive=0
print_driver_name=0
print_kernel_checksum=0
use_install_dir=0
build_kernel=2  #  0=no, 1=yes, 2=maybe
exit_if_driver_exists=0
verbose=0
archive_driver=0
use_kernel_src_dir=0
config_check=0
sep_drivers_only=0
build_rpm=0

while [ $# -gt 0 ] ; do
  case "$1" in
    --help | -h)
      print_usage_and_exit 0
      ;;
    --non-interactive | -ni)
       non_interactive=1
       ;;
    --print-driver-name)
       print_driver_name=1
       build_kernel=0
       ;;
    --install-dir=*)
       driver_install_dir=`echo $1 | sed s?^--install-dir=??g`
       use_install_dir=1
       ;;
    --kernel-file=*)
       kernel_file=`echo $1 | sed s?^--kernel-file=??g`
       ;;
    --kernel-version=*)
       kernel_version=`echo $1 | sed s?^--kernel-version=??g`
       ;;
    --kernel-src-dir=*)
       kernel_src_dir=`echo $1 | sed s?^--kernel-src-dir=??g`
       use_kernel_src_dir=1
       ;;
    --c-compiler=*)
       c_compiler=`echo $1 | sed s?^--c-compiler=??g`
       ;;
    --make-command=*)
       make_command=`echo $1 | sed s?^--make-command=??g`
       ;;
    --make-args=*)
       make_args=`echo $1 | sed s?^--make-args=??g`
       ;;
    --print-kernel-checksum)
       print_kernel_checksum=1
       build_kernel=0
       ;;
    --exit-if-driver-exists)
       exit_if_driver_exists=1
       ;;
    --verbose)
       verbose=1
       ;;
    --sep-drivers-only | -sdo)
       sep_drivers_only=1
       ;;
    --config-file=*)
       config_file=`echo $1 | sed s?^--config-file=??g`
       read_config_file $config_file
       ;;
    --per-user | -pu)
       PER_USER_MODE="YES"
       ;;
    --archive-driver | -ad)
       archive_driver=1
       ;;
    --pmi)
       NMI_MODE="NO"
       ;;
    --minlog)
        MINLOG_MODE="YES"
       ;;
    --maxlog)
        MAXLOG_MODE="YES"
       ;;
    --no-udev)
        UDEV_AVAILABLE="NO"
       ;;
    --enable-config-check)
        config_check=1
        ;;
    --build-rpm)
        build_rpm=1
        ;;
    --group=* | -g=*)
        CMDSTR=`echo $1`
        if [[ $CMDSTR == *"group"* ]]; then
          DRIVER_GROUP=`echo $1 | sed s?^--group=??g`
        else
          DRIVER_GROUP=`echo $1 | sed s?^-g=??g`
        fi
        ;;
    *)
       echo ""
       echo "Invalid option: \"$1\""
       print_usage_and_exit 254
       ;;
  esac
  shift
done

get_os_distribution

if [ -z "${kernel_version}" ] ; then
  kernel_version=${KERNEL_VERSION}
fi

if [ -z "${kernel_src_dir}" ] ; then
  kernel_src_dir=/usr/src/linux-${kernel_version}
else
  exit_if_directory_inaccessible $kernel_src_dir 110 "kernel_header"
fi

if [ -z "${kernel_file}" ] ; then
  kernel_file=/boot/vmlinuz-${kernel_version}
else
  exit_if_file_inaccessible $kernel_file kernel_header
fi

if [ -z "${c_compiler}" ] ; then
  c_compiler=gcc
else
  exit_if_file_inaccessible $(get_first $c_compiler) gcc x
fi

if [ -z "${make_command}" ] ; then
  make_command=make
else
  exit_if_file_inaccessible $make_command make x
fi

# function to describe default option

show_preamble()
{
  if [ $verbose -eq 1 ] ; then
    echo ""
    echo "Options in brackets \"[ ... ]\" indicate default values"
    echo "that will be used when only the ENTER key is pressed."
  fi
  echo ""
}

# function to return absolute path location (from script directory)

get_absolute_path()
{
  target_dir=$1
  if [ -d ${target_dir} ] ; then
    cd ${SCRIPT_DIR}
    cd ${target_dir}
    actual_dir=$PWD
    cd ${SCRIPT_DIR}
    echo "${actual_dir}"
  else
    echo "${target_dir}"
  fi
}

# function to check if devtoolset is installed

check_devtoolset_presence()
{
  if [ ! -d ${DEFAULT_DEVTOOLSET_BASE} ] ; then
    return
  fi

  DEVTOOLSET=`ls ${DEFAULT_DEVTOOLSET_BASE} | ${GREP} "devtoolset" | ${TR} '\n' ' ' | ${CUT} -d ' ' -f1`
  if [ -n "${DEVTOOLSET}" ] ; then
    devtoolset_installed="YES"
  fi
  DEFAULT_DEVTOOLSET_BIN_PATH="${DEFAULT_DEVTOOLSET_BASE}/${DEVTOOLSET}/root/usr/bin"

  # check if gcc and make exists
  if [ ! -f "${DEFAULT_DEVTOOLSET_BIN_PATH}/gcc" -o ! -f "${DEFAULT_DEVTOOLSET_BIN_PATH}/make" ] ; then
    devtoolset_installed="NO"
  fi
}

# function to repeat this script or exit with error code

repeat_or_exit()
{
  EXIT_CODE=$1
  echo ""
  # for now, just exit with error
  exit ${EXIT_CODE}
  if [ $non_interactive -eq 1 ] ; then
    exit ${EXIT_CODE}
  fi
  echo -n "Retry building the driver? (yes/no) [Yes] "
  read YESNO
  if [ "${YESNO}" = "N" -o "${YESNO}" = "n" -o "${YESNO}" = "no" -o "${YESNO}" = "No" ] ; then
    echo ""
    exit ${EXIT_CODE}
  else
    exec ${SCRIPT} ${SCRIPT_ARGS}
  fi
  echo ""
}

# ----------------------------- PRE-CHECK ------------------------------------

# check if OS and platform is supported

# if ARCH variable is set, unset it to avoid conflicts below

unset ARCH

if [ "${PLATFORM}" = "x86_64" ] ; then
  ARCH="x32_64"
elif [ "${PLATFORM}" = "i386" -o "${PLATFORM}" = "i486" -o "${PLATFORM}" = "i586" -o "${PLATFORM}" = "i686" ] ; then
  ARCH="x32"
else
  print_err ""
  print_err "ERROR: Unsupported platform \"${PLATFORM}\" ... exiting."
  print_err ""
  exit 254
fi

# determine if using kernel 2.6 sources or later

KS_MAKEFILE=${kernel_src_dir}/Makefile
if [ -r ${KS_MAKEFILE} ] ; then
  kernel_major=`${GREP} "^VERSION" ${KS_MAKEFILE} | ${HEAD} -1 | ${SED} -e 's/ //g' | ${CUT} -d '=' -f 2`
  kernel_minor=`${GREP} "^PATCHLEVEL" ${KS_MAKEFILE} | ${HEAD} -1 | ${SED} -e 's/ //g' | ${CUT} -d '=' -f 2`
  kernel_patch=`${GREP} "^SUBLEVEL" ${KS_MAKEFILE} | ${HEAD} -1 | ${SED} -e 's/ //g' | ${CUT} -d '=' -f 2`
else
  kernel_major=$(echo ${kernel_version} | cut -d. -f1)
  kernel_minor=$(echo ${kernel_version} | cut -d. -f2)
  kernel_patch=$(echo ${kernel_version} | cut -d. -f3)
fi

# if not using kernel 2.6.x or later, then exit with error

if [ 6 -gt ${kernel_minor} ] ; then
  if [ 2 -ge ${kernel_major} ] ; then
    print_err ""
    print_err "ERROR: Linux kernels prior to 2.6.x are unsupported ... exiting."
    print_err ""
    exit 254
  fi
fi

# print checksum and exit, if requested

if [ $print_kernel_checksum -eq 1 ] ; then
  print_kernel_checksum $kernel_file
  exit 0
fi

# check whether kernel is for UP or SMP

SMP=`${UNAME} -v | ${GREP} SMP`
if [ -z "${SMP}" ] ; then
  ARITY="up"
else
  ARITY="smp"
fi

# check driver file extension

EXT="ko"

if [ "$PER_USER_MODE" = "YES" ]; then
    PER_USER_EXT="-pu"
fi

# name of the driver that will be built (see Makefile)

DRIVER_FILENAME=${DRIVER_NAME}${PER_USER_EXT}-${ARCH}-${kernel_version}${ARITY}.${EXT}

if [ $print_driver_name -eq 1 ] ; then
  echo "${DRIVER_FILENAME}"
  exit 0
fi

# ----------------------- BUILD / INSTALL DRIVER -----------------------------

if [ -z "$driver_install_dir" ] ; then
  driver_install_dir=${DRIVER_DIRECTORY}
else
  exit_if_directory_inaccessible $driver_install_dir 101
fi

if [ -d $driver_install_dir ] ; then
  DRIVER_DIRECTORY=$driver_install_dir
fi

DRIVER_DIRECTORY=`get_absolute_path ${DRIVER_DIRECTORY}`

# if specifed, check whether pre-built driver exists and exit if it does

if [ $exit_if_driver_exists -eq 1 ] ; then
  if [ -r $driver_install_dir/${DRIVER_FILENAME} ] ; then
    echo ""
    echo "Found pre-built driver: $driver_install_dir/${DRIVER_FILENAME}"
    echo ""
    exit 0
  else
    show_preamble
    echo "Pre-built driver \"${DRIVER_FILENAME}\" was NOT found"
    echo "in directory \"$driver_install_dir\" ."
    echo ""
    echo -n "Proceed with building a driver for this kernel? (Yes/No) [Yes] "
    if [ $non_interactive -eq 1 ] ; then
      YESNO=y
    else
      read YESNO
    fi
    echo ""
    if [ "${YESNO}" = "N" -o "${YESNO}" = "n" -o "${YESNO}" = "no" -o "${YESNO}" = "No" ] ; then
      exit 100
    fi
  fi
else
  if [ $non_interactive -eq 0 ] ; then
    show_preamble
  fi
fi

# prompt for C compiler

OLD_CC=${CC}
NEW_CC=""
CURRENT_CC="$c_compiler"
CC_FILE=`${WHICH} $(get_first $c_compiler) 2>/dev/null`
if [ -z "${CC_FILE}" ] ; then
  CURRENT_CC=$c_compiler
fi
if [ $verbose -eq 1 -o $non_interactive -eq 0 ] ; then
  echo -n "C compiler to use: [ ${CC_FILE} ] "
fi
if [ $non_interactive -eq 0 ] ; then
  read NEW_CC
else
  if [ $verbose -eq 1 ] ; then
    echo ""
  fi
fi
if [ -z "${NEW_CC}" ] ; then
  NEW_CC=${CURRENT_CC}
fi
CC_FILE=`${WHICH} $(get_first ${NEW_CC}) 2>/dev/null`
if [ -z "${CC_FILE}" -o -d "${CC_FILE}" -o ! -x "${CC_FILE}" ] ; then
  print_err ""
  print_err "ERROR: invalid or inaccessible C compiler \"${NEW_CC}\" !"
  print_how_to_install "gcc"
  repeat_or_exit 255
fi

export CC="${CC_FILE}"

CC_VERSION_OUTPUT=`${CC} -v 2>&1`
CC_VERSION_STR=`echo ${CC_VERSION_OUTPUT} | awk -F'gcc version ' '{print $2}' | ${CUT} -d ' ' -f 1`
if [ ! -z ${CC_VERSION_STR} ] ; then
  cc_major=$(echo ${CC_VERSION_STR} | ${CUT} -d. -f1)
  cc_minor=$(echo ${CC_VERSION_STR} | ${CUT} -d. -f2)
  cc_patch=$(echo ${CC_VERSION_STR} | ${CUT} -d. -f3)

  echo "C compiler version: ${CC_VERSION_STR}"
  if [ $non_interactive -eq 0 ] ; then
    echo ""
  fi
fi

# prompt for make command

NEW_MAKE=""
CURRENT_MAKE=`${WHICH} $make_command 2>&1`
if [ -z "${CURRENT_MAKE}" ] ; then
  CURRENT_MAKE=$make_command
fi
if [ $verbose -eq 1 -o $non_interactive -eq 0 ] ; then
  echo -n "Make command to use: [ ${CURRENT_MAKE} ] "
fi
if [ $non_interactive -eq 0 ] ; then
  read NEW_MAKE
else
  if [ $verbose -eq 1 ] ; then
    echo ""
  fi
fi
if [ -z "${NEW_MAKE}" ] ; then
  NEW_MAKE=${CURRENT_MAKE}
fi
CHECK_MAKE=`${WHICH} "${NEW_MAKE}" 2>&1`
if [ -z "${CHECK_MAKE}" -o -d "${CHECK_MAKE}" -o ! -x "${CHECK_MAKE}" ] ; then
  print_err ""
  print_err "ERROR: invalid or inaccessible make command \"${NEW_MAKE}\" !"
  print_how_to_install "make"
  repeat_or_exit 255
fi

export MAKE="${CHECK_MAKE}"

MAKE_VERSION_OUTPUT=`${MAKE} -v 2>&1`
MAKE_VERSION_STR=`echo ${MAKE_VERSION_OUTPUT} | awk -F'GNU Make ' '{print $2}' | ${CUT} -d ' ' -f 1`
if [ ! -z ${MAKE_VERSION_STR} ] ; then
  make_major=$(echo ${MAKE_VERSION_STR} | ${CUT} -d. -f1)
  make_minor=$(echo ${MAKE_VERSION_STR} | ${CUT} -d. -f2)

  echo "Make version: ${MAKE_VERSION_STR}"
  if [ $non_interactive -eq 0 ] ; then
    echo ""
  fi
fi

# prompt for kernel source directory

DEFAULT_KERNEL_SRC_DIR=${kernel_src_dir}

# search heuristic for determining default kernel source directory
if [ $use_kernel_src_dir -eq 0 ] ; then
  if [ ! -d ${DEFAULT_KERNEL_SRC_DIR} ] ; then
    DEFAULT_KERNEL_SRC_DIR=/lib/modules/${kernel_version}/build
    if [ ! -d ${DEFAULT_KERNEL_SRC_DIR} ] ; then
      DEFAULT_KERNEL_SRC_DIR=/lib/modules/${kernel_version}/source
      if [ ! -d ${DEFAULT_KERNEL_SRC_DIR} ] ; then
        DEFAULT_KERNEL_SRC_DIR=/usr/src/linux-${major}.${minor}
        if [ ! -d ${DEFAULT_KERNEL_SRC_DIR} ] ; then
          DEFAULT_KERNEL_SRC_DIR=/usr/src/linux
          if [ ! -d ${DEFAULT_KERNEL_SRC_DIR} ] ; then
            DEFAULT_KERNEL_SRC_DIR=/usr/src/kernel
            if [ ! -d ${DEFAULT_KERNEL_SRC_DIR} ] ; then
              # punt ...
              DEFAULT_KERNEL_SRC_DIR=${kernel_src_dir}
            fi
          fi
        fi
      fi
    fi
  fi
fi

DEFAULT_KERNEL_HEADER_DIR=${CURRENT_KERNEL_SRC_DIR}
if [ ! -f ${DEFAULT_KERNEL_HEADER_DIR}/include/linux/profile.h ] ; then
  DEFAULT_KERNEL_HEADER_DIR=/lib/modules/${kernel_version}/build
  if [ ! -f ${DEFAULT_KERNEL_HEADER_DIR}/include/linux/profile.h ] ; then
    DEFAULT_KERNEL_HEADER_DIR=/lib/modules/${kernel_version}/source
    if [ ! -f ${DEFAULT_KERNEL_HEADER_DIR}/include/linux/profile.h ] ; then
      DEFAULT_KERNEL_HEADER_DIR=/usr/src/linux-${major}.${minor}
      if [ ! -f ${DEFAULT_KERNEL_HEADER_DIR}/include/linux/profile.h ] ; then
        DEFAULT_KERNEL_HEADER_DIR=/usr/src/linux
        if [ ! -f ${DEFAULT_KERNEL_HEADER_DIR}/include/linux/profile.h ] ; then
          DEFAULT_KERNEL_HEADER_DIR=/usr/src/kernel
          if [ ! -f ${DEFAULT_KERNEL_HEADER_DIR}/include/linux/profile.h ] ; then
            # punt ...
            DEFAULT_KERNEL_HEADER_DIR=${kernel_src_dir}
          fi
        fi
      fi
    fi
  fi
fi
KERNEL_HEADER_DIR=`get_absolute_path ${DEFAULT_KERNEL_HEADER_DIR}`

# ---------------------------------------------------------------------------

CURRENT_KERNEL_SRC_DIR=${KERNEL_SRC_DIR:-${DEFAULT_KERNEL_SRC_DIR}}

if [ $verbose -eq 1 -o $non_interactive -eq 0 ] ; then
  echo -n "Kernel source directory: [ ${CURRENT_KERNEL_SRC_DIR} ] "
fi
if [ $non_interactive -eq 0 ] ; then
  read KERNEL_SRC_DIR
  if [ -n "${KERNEL_SRC_DIR}" ] ; then
    use_kernel_src_dir=1
  fi
else
  if [ $verbose -eq 1 ] ; then
    echo ""
  fi
fi
if [ -z "${KERNEL_SRC_DIR}" ] ; then
  KERNEL_SRC_DIR=${CURRENT_KERNEL_SRC_DIR}
fi
KERNEL_SRC_DIR=`get_absolute_path ${KERNEL_SRC_DIR}`

exit_if_directory_inaccessible ${KERNEL_SRC_DIR} 125 "kernel_header"

echo "Kernel version: ${kernel_major}.${kernel_minor}.${kernel_patch}"
echo ""

# check if kernel source directory contains "configured" kernel headers
# (e.g., at a minimum, "version.h" file and "asm" directory must exist);
# if not, then specify a bogus (non-existent) directory so subsequent
# search heuristics are used

good_kernel_path=0
missing_items=
if [ -r ${KERNEL_SRC_DIR}/include/linux/version.h ] ; then
  if [ -d ${KERNEL_SRC_DIR}/include/asm -o -L ${KERNEL_SRC_DIR}/include/asm ] ; then
    good_kernel_path=1
  elif [ -d ${KERNEL_SRC_DIR}/include/asm-generic -o -L ${KERNEL_SRC_DIR}/include/asm-generic ] ; then
    good_kernel_path=1
  fi
fi

if [ ${good_kernel_path} -eq 0 ] ; then
  if [ -r ${KERNEL_SRC_DIR}/include/generated/uapi/linux/version.h ] ; then
    if [ -d ${KERNEL_SRC_DIR}/arch/x86/include/generated/asm -o -L ${KERNEL_SRC_DIR}/arch/x86/include/generated/asm ] ; then
      good_kernel_path=1
    elif [ -d ${KERNEL_SRC_DIR}/arch/x86/include/generated/asm-generic -o -L ${KERNEL_SRC_DIR}/arch/x86/include/generated/asm-generic ] ; then
      good_kernel_path=1
    else
      missing_items="asm "
    fi
  else
    missing_items="version.h "
  fi
fi

if [ ${good_kernel_path} -eq 0 ] ; then
  print_err ""
  print_err "ERROR: The following required item(s) are not found:"
  print_err ${missing_items}
  print_err ""
  print_err "If required item(s) are due to incorrectly installed or corrupted kernel headers,"
  print_how_to_install "kernel_header" "reinstall"
  exit 126
fi

proc_version=/proc/version
if [ -r ${proc_version} ] ; then
  is_clang=`${CAT} ${proc_version} | ${GREP} -c "clang"`
  if [ ${is_clang} -eq 1 ] ; then
    make_args="${make_args} CONFIG_CC_IS_CLANG="
  fi
fi

if [ ${DRIVER_GROUP} != "vtune" -a ${build_rpm} -eq 0 ] ; then
  print_err "Warning: -g | --group option can only be used with --build-rpm option."
  print_err "         Discarding ..."
  print_err ""
fi

# initialize variable for devtoolset check
devtoolset_installed="NO"
DEFAULT_DEVTOOLSET_BASE="/opt/rh"
DEVTOOLSET=
DEFAULT_DEVTOOLSET_BIN_PATH=

if [ ${config_check} -eq 1 ] ; then
  make_params="CONFIG_STACK_VALIDATION"

  for make_param in ${make_params}; do
    # check if the config is passed as make-args
    echo ${make_args} | ${GREP} -we ${make_param} > /dev/null 2>&1
    make_args_passed=$?

    # check for the config flag in config file
    ${GREP} ${KERNEL_SRC_DIR}/.config -we "${make_param}=y" > /dev/null 2>&1
    result=$?

    if [ ${result} -eq 0 -a ${make_args_passed} -ne 0 ] ; then
      # additional check is only requried if CONFIG_STACK_VALIDATION is set
      # if "CONFIG_STACK_VALIDATION=" is passed as --make-args parameter means user has already installed devtoolset
      # ...and is using devtoolset gcc and make commands: so no need of the check
      if [ ${make_param} = "CONFIG_STACK_VALIDATION" ] ; then
        # check for tools/objtool/objtool binary in kernel source
        if [ ! -f ${KERNEL_SRC_DIR}/tools/objtool/objtool ] ; then
          check_devtoolset_presence

          print_err ""
          print_err "WARNING   : ${make_param} is enabled for the kernel."
          print_err ""

          if [ "${devtoolset_installed}" = "NO" ] ; then
            print_err "ERROR     : The relevant devtool binary is not available in the system."
            print_err "            Please install devtoolset-6"
            print_err "            Use the following command to build the driver after devtoolset installation:"
            DEFAULT_DEVTOOLSET_BIN_PATH="<devtoolset_base>/root/usr/bin"
          else
            # continue driver build if devtoolset installed
            echo "            REPLACING THE DEFAULT TOOLSET WITH DEVTOOLSET LOCATED AT ${DEFAULT_DEVTOOLSET_BIN_PATH}."
            echo ""
            echo "            Using the following command to build the driver:"
            # updating CC, MAKE and make args
            export CC="${DEFAULT_DEVTOOLSET_BIN_PATH}/gcc"
            if [ ! -f ${CC} ] ; then
              print_err "ERROR: invalid or inaccessible C compiler \"${CC}\" !"
              exit 103
            fi

            export MAKE="${DEFAULT_DEVTOOLSET_BIN_PATH}/make"
            if [ ! -f ${MAKE} ] ; then
              print_err "ERROR: invalid or inaccessible C compiler \"${MAKE}\" !"
              exit 104
            fi

            make_args="${make_args} ${make_param}="
          fi

          echo "            ./build-driver --c-compiler=${DEFAULT_DEVTOOLSET_BIN_PATH}/gcc --make-command=${DEFAULT_DEVTOOLSET_BIN_PATH}/make --make-args=\"${make_param}=\" -ni"
          echo ""

          if [ "${devtoolset_installed}" = "NO" ] ; then
            print_err "ERROR: devtoolset is not available."
            exit 102
          fi
        fi
      fi
    fi
  done
fi

# check for the mandatory kernel config flags
make_params="CONFIG_MODULES CONFIG_MODULE_UNLOAD CONFIG_SMP"

if [ ${kernel_major} -gt 5 ] || [ ${kernel_major} -eq 5 -a ${kernel_minor} -ge 17 ]; then
  # flags required since kernel 5.17
  make_params=${make_params}" CONFIG_TRACEPOINTS CONFIG_KPROBES"
else
  # flags required before kernel 5.17
  make_params=${make_params}" CONFIG_PROFILING"
fi
if [ ${kernel_major} -gt 5 ] || [ ${kernel_major} -eq 5 -a ${kernel_minor} -ge 10 ]; then
  # flags required since kernel 5.10
  make_params=${make_params}" CONFIG_KALLSYMS"
fi

for make_param in ${make_params}; do
  # check if the config is passed as make-args
  echo ${make_args} | ${GREP} -we ${make_param} > /dev/null 2>&1
  make_args_passed=$?

  # check for the config flag in config file
  ${GREP} ${KERNEL_SRC_DIR}/.config -we "^${make_param}=y" > /dev/null 2>&1
  result=$?

  if [ ${result} -ne 0 -a ${make_args_passed} -ne 0 ] ; then
    print_err ""
    print_err "WARNING: ${make_param} is not set in the kernel header's configuration."
    print_err "         SEP functionality may be limited."
    print_err ""
  fi
done

# check for the config flag in config file
${GREP} ${KERNEL_SRC_DIR}/.config -we "CONFIG_INTEL_PMT_TELEMETRY=m" > /dev/null 2>&1
pmt_result=$?
#if  [ ${pmt_result} -eq 0 ] ; then
#    BUILD_PMT="YES"
#fi

# make the driver

if [ ! -z "${make_args}" ] ; then
    driver_src_path=`echo ${make_args} | awk -F'-C ' '{print $2}'`
    if [ ! -z "${driver_src_path}" ] ; then
        DRIVER_SOURCE_DIRECTORY=$driver_src_path
    fi
fi

make_args="KERNEL_VERSION=$kernel_version KERNEL_SRC_DIR=$KERNEL_SRC_DIR KERNEL_HEADER_DIR=$KERNEL_HEADER_DIR PER_USER_MODE=$PER_USER_MODE NMI_MODE=$NMI_MODE MINLOG_MODE=$MINLOG_MODE MAXLOG_MODE=$MAXLOG_MODE BUILD_PMT=$BUILD_PMT KBUILD_EXTRA_SYMBOLS=${DRIVER_SOURCE_DIRECTORY}/socperf/src/Module.symvers $make_args"

if [ $verbose -eq 1 ] ; then
  echo ""
  printf "%s %-18s %s\n" ${DASHES} "Cleaning workspaces" ${DASHES}
  ${MAKE} clean VERBOSE=$verbose SEP_DRIVERS_ONLY=$sep_drivers_only
else
  echo "Cleaning workspaces ... "
  ${MAKE} clean VERBOSE=$verbose SEP_DRIVERS_ONLY=$sep_drivers_only
  if [ $? -ne 0 ] ; then
    echo "Failed"
  else
    echo "Done"
  fi
fi

${MAKE} CC="$CC" MAKE=$MAKE $make_args default VERBOSE=$verbose SEP_DRIVERS_ONLY=$sep_drivers_only

ERR=$?
echo ""
if [ $ERR -ne 0 ] ; then
  if [ ${kernel_major} -ge 5 ] ; then
    if [ ! -z ${CC_VERSION_STR} -a ${cc_major} -lt 9 ] ; then
      print_err ""
      print_err "ERROR: Driver build failed. It could be due to an older gcc version(${cc_major}.${cc_minor}.${cc_patch}) on Linux kernel ${kernel_major}.${kernel_minor}.${kernel_patch}"
      print_err "       Use of gcc version 9 or newer is recommended"
      print_err ""
    fi
  fi

  echo "Failed to build the drivers"

  repeat_or_exit 100
fi

if [ $verbose -eq 1 ] ; then
  printf "%s %-18s %s\n" ${DASHES} "Done building the drivers" ${DASHES}
else
  echo "Done building the drivers"
fi


# rename driver to correct kernel version for cross-compiled drivers

if [ $use_kernel_src_dir -eq 1 ] ; then
  if [ -r ${DRIVER_SOURCE_DIRECTORY}/${DRIVER_FILENAME} ] ; then
    vermagicstr=$( strings ${DRIVER_SOURCE_DIRECTORY}/${DRIVER_FILENAME} | ${GREP} vermagic )
    vermagic=${vermagicstr#*=}
    updated_kernel_version=${vermagic%% *}

    if [ "${kernel_version}" != "${updated_kernel_version}" ] ; then
      socperf_driver_filename=`ls socperf/src | ${GREP} "${kernel_version}"`
      pax_driver_filename=`ls pax | ${GREP} "${kernel_version}"`
      updated_driver_filename_suffix=${PER_USER_EXT}-${ARCH}-${updated_kernel_version}${ARITY}.${EXT}
      updated_driver_filename=${DRIVER_NAME}${updated_driver_filename_suffix}
      updated_socperf_driver_filename=${socperf_driver_filename%%-*}${updated_driver_filename_suffix}
      updated_pax_driver_filename=${pax_driver_filename%%-*}${updated_driver_filename_suffix}

      # rename sep driver
      echo -n "Renaming ${DRIVER_FILENAME} to ${updated_driver_filename} ... "
      mv ${DRIVER_SOURCE_DIRECTORY}/${DRIVER_FILENAME} ${DRIVER_SOURCE_DIRECTORY}/${updated_driver_filename}
      echo "done"
      # rename socperf driver
      echo -n "Renaming ${socperf_driver_filename} to ${updated_socperf_driver_filename} ... "
      mv ${DRIVER_SOURCE_DIRECTORY}/socperf/src/${socperf_driver_filename} ${DRIVER_SOURCE_DIRECTORY}/socperf/src/${updated_socperf_driver_filename}
      echo "done"
      # rename pax driver
      echo -n "Renaming ${pax_driver_filename} to ${updated_pax_driver_filename} ... "
      mv ${DRIVER_SOURCE_DIRECTORY}/pax/${pax_driver_filename} ${DRIVER_SOURCE_DIRECTORY}/pax/${updated_pax_driver_filename}
      echo "done"
      echo ""

      kernel_version=${updated_kernel_version}
    fi

    USED_KERNEL_VERSION=
    if [ -r ${KERNEL_SRC_DIR}/include/linux/utsrelease.h ] ; then
      USED_KERNEL_VERSION=`${CAT} ${KERNEL_SRC_DIR}/include/linux/utsrelease.h | ${CUT} -d ' ' -f3 | ${SED} -e 's/^"//' -e 's/"$//'`
    elif [ -r ${KERNEL_SRC_DIR}/include/generated/utsrelease.h ] ; then
      USED_KERNEL_VERSION=`${CAT} ${KERNEL_SRC_DIR}/include/generated/utsrelease.h | ${CUT} -d ' ' -f3 | ${SED} -e 's/^"//' -e 's/"$//'`
    fi

    if [ -n "${USED_KERNEL_VERSION}" ] ; then
      if [ ${KERNEL_VERSION} != ${USED_KERNEL_VERSION} ] ; then
        print_err ""
        print_err "Warning: Kernel version ${USED_KERNEL_VERSION} was used to build these driver modules."
        print_err "         Kernel version on the system is ${KERNEL_VERSION}."
        print_err "         The driver modules may not be loadable on the system and may result in undefined behavior."
        print_err ""
      fi
    fi
  fi
fi

# where to install the driver once it is successfully built

if [ ! -w $driver_install_dir ] ; then
  print_err "Warning: directory \"$driver_install_dir\" is not writable."
  print_err ""
  driver_install_dir=.
  use_install_dir=0
fi

if [ $use_install_dir -eq 1 ] ; then
  # install the previously built driver to specified location
  # adding KERNEL_VERSION to update the kernel version in case of cross-compile
  make_args="$make_args INSTALL=${DRIVER_DIRECTORY} KERNEL_VERSION=${kernel_version} install SEP_DRIVERS_ONLY=$sep_drivers_only"
  ${MAKE} $make_args
fi

if [ $archive_driver -eq 1 ] ; then
  archive_file=sep_driver_${ARCH}-${kernel_version}${ARITY}.tar.bz2

  mkdir -p ${DRIVER_SOURCE_DIRECTORY}/sep/sepdk/pax
  cp ${DRIVER_SOURCE_DIRECTORY}/../../sep_vars.sh ${DRIVER_SOURCE_DIRECTORY}/sep
  cp *${ARCH}-${kernel_version}${ARITY}*.ko insmod-sep rmmod-sep ${DRIVER_SOURCE_DIRECTORY}/sep/sepdk
  cp *.py ${DRIVER_SOURCE_DIRECTORY}/sep/sepdk
  cp pax/*${ARCH}-${kernel_version}${ARITY}*.ko pax/insmod-pax pax/rmmod-pax ${DRIVER_SOURCE_DIRECTORY}/sep/sepdk/pax
  (cd ${DRIVER_SOURCE_DIRECTORY} ; tar cjvf ${archive_file} sep)
  rm -rf ${DRIVER_SOURCE_DIRECTORY}/sep
fi


ERR=$?

if [ ${ERR} -ne 0 ] ; then
  repeat_or_exit 101
fi

CMD=`${WHICH} ${RPMBUILD} 2>&1` ;
ret_val=$?
if [ ${build_rpm} -eq 1 -a ${ret_val} -ne 0 ] ; then
  print_err "ERROR: unable to find command \"${RPMBUILD}\" !"
  print_err "       Please install \"${RPMBUILD}\" and try again"
  build_rpm=0
fi

if [ ${build_rpm} -eq 1 ] ; then
  echo ""
  if [ $verbose -eq 1 ] ; then
    printf "%s %-18s %s\n" ${DASHES} "Generating RPM package file" ${DASHES}
  else
    echo "Generating RPM package file ... "
  fi
  IS_VTUNE_BUILD=0
  NAME_PREFIX="sep"
  if [ -d "vtsspp" ] ; then
    NAME_PREFIX="vtune"
  fi
  RPM_STRIPPED_KERNEL_VERSION=`echo "${kernel_version}" | tr - _` # Replace '-' by '_' because rpmbuild command does not aceept hyphen in Version
  if [ ! -z "${updated_kernel_version}" -a "${kernel_version}" != "${updated_kernel_version}" ] ; then
    # Cross Compile - Update driver filename
    DRIVER_FILENAME=${updated_driver_filename}
  fi
  RPM_PACKAGE_NAME=${NAME_PREFIX}_sepdk-${RPM_STRIPPED_KERNEL_VERSION}
  RPM_KO_ARCHIVE_DIR=${DRIVER_SOURCE_DIRECTORY}/${RPM_PACKAGE_NAME}
  if [ -d "${RPM_PACKAGE_NAME}" ] ; then
    rm -rf ${RPM_PACKAGE_NAME}
  fi
  mkdir ${RPM_PACKAGE_NAME}
  mkdir -p ${RPM_PACKAGE_NAME}/socperf/src
  mkdir ${RPM_PACKAGE_NAME}/pax
  if [ -d "vtsspp" ] ; then
    mkdir ${RPM_PACKAGE_NAME}/vtsspp
  fi
  if [ -d "socwatch" ] ; then
    mkdir -p ${RPM_PACKAGE_NAME}/socwatch/drivers
  fi

  cp ${DRIVER_FILENAME} ${RPM_KO_ARCHIVE_DIR}/
  cp insmod-sep ${RPM_KO_ARCHIVE_DIR}/
  cp rmmod-sep ${RPM_KO_ARCHIVE_DIR}/
  cp boot-script ${RPM_KO_ARCHIVE_DIR}/
  socperf_driver_name=socperf3-${ARCH}-${kernel_version}${ARITY}.${EXT}
  if [ ! -z "${updated_kernel_version}" -a "${kernel_version}" != "${updated_kernel_version}" ] ; then
    socperf_driver_name=${updated_socperf_driver_filename}
  fi
  cp ${DRIVER_SOURCE_DIRECTORY}/socperf/src/${socperf_driver_name} ${RPM_KO_ARCHIVE_DIR}/socperf/src/
  cp ${DRIVER_SOURCE_DIRECTORY}/socperf/src/insmod-socperf ${RPM_KO_ARCHIVE_DIR}/socperf/src/
  cp ${DRIVER_SOURCE_DIRECTORY}/socperf/src/rmmod-socperf ${RPM_KO_ARCHIVE_DIR}/socperf/src
  pax_driver_name=pax-${ARCH}-${kernel_version}${ARITY}.${EXT}
  if [ ! -z "${updated_kernel_version}" -a "${kernel_version}" != "${updated_kernel_version}" ] ; then
    pax_driver_name = ${updated_pax_driver_filename}
  fi
  cp pax/${pax_driver_name} ${RPM_KO_ARCHIVE_DIR}/pax/
  cp pax/insmod-pax ${RPM_KO_ARCHIVE_DIR}/pax/
  cp pax/rmmod-pax ${RPM_KO_ARCHIVE_DIR}/pax/
  if [ -d "vtsspp" ] ; then
    IS_VTUNE_BUILD=1
    TOOL_VERSION="2024.1.0"
    vtsspp_driver_name=vtsspp-${ARCH}-${kernel_version}${ARITY}.${EXT}
    if [ ! -z "${updated_kernel_version}" -a "${kernel_version}" != "${updated_kernel_version}" ] ; then
      vtsspp_driver_name=vtsspp-${ARCH}-${updated_kernel_version}${ARITY}.${EXT}
    fi
    cp vtsspp/${vtsspp_driver_name} ${RPM_KO_ARCHIVE_DIR}/vtsspp/
    cp vtsspp/insmod-vtsspp ${RPM_KO_ARCHIVE_DIR}/vtsspp/
    cp vtsspp/rmmod-vtsspp ${RPM_KO_ARCHIVE_DIR}/vtsspp/
  fi
  if [ -d "socwatch" ] ; then
    socwatch_driver_name=socwatch2_15-${ARCH}-${kernel_version}${ARITY}.${EXT}
    if [ ! -z "${updated_kernel_version}" -a "${kernel_version}" != "${updated_kernel_version}" ] ; then
      socwatch_driver_name=socwatch2_15-${ARCH}-${updated_kernel_version}${ARITY}.${EXT}
    fi
    cp socwatch/drivers/${socwatch_driver_name} ${RPM_KO_ARCHIVE_DIR}/socwatch/drivers
    cp socwatch/drivers/insmod-socwatch ${RPM_KO_ARCHIVE_DIR}/socwatch/drivers
    cp socwatch/drivers/rmmod-socwatch ${RPM_KO_ARCHIVE_DIR}/socwatch/drivers
  fi
  tar -C ${DRIVER_SOURCE_DIRECTORY} -zcf ${RPM_PACKAGE_NAME}.tar.gz ${RPM_PACKAGE_NAME}

  if [ $verbose -eq 1 ] ; then
    ${RPMBUILD} --define "_sourcedir ${DRIVER_SOURCE_DIRECTORY}" --define "VERS ${RPM_STRIPPED_KERNEL_VERSION}" --define "kernel_version ${kernel_version}" --define "NAME ${NAME_PREFIX}_sepdk" --define "FLAVOR default" --define "ARCH ${ARCH}" --define "ARITY ${ARITY}" --define "DRIVER_GROUP ${DRIVER_GROUP}" --define "SEP_DRIVER_NAME ${DRIVER_NAME}" --define "IS_VTUNE_BUILD ${IS_VTUNE_BUILD}" --define "BUILD_RELEASE ${TOOL_VERSION}" -ba sepdk.spec
  else
    ${RPMBUILD} --define "_sourcedir ${DRIVER_SOURCE_DIRECTORY}" --define "VERS ${RPM_STRIPPED_KERNEL_VERSION}" --define "kernel_version ${kernel_version}" --define "NAME ${NAME_PREFIX}_sepdk" --define "FLAVOR default" --define "ARCH ${ARCH}" --define "ARITY ${ARITY}" --define "DRIVER_GROUP ${DRIVER_GROUP}" --define "SEP_DRIVER_NAME ${DRIVER_NAME}" --define "IS_VTUNE_BUILD ${IS_VTUNE_BUILD}" --define "BUILD_RELEASE ${TOOL_VERSION}" -ba sepdk.spec > /dev/null 2>&1
  fi

  rm -rf ${HOME}/rpmbuild/BUILDROOT/*

  ERR=$?
  if [ $ERR -ne 0 ] ; then
    echo ""
    print_err "Failed to generate the RPM package file"
  else
    echo "======================================"
    echo "The RPM package file is available at"
    echo "${HOME}/rpmbuild/RPMS/${NAME_PREFIX}_sepdk-${RPM_STRIPPED_KERNEL_VERSION}-${TOOL_VERSION}.${ARCH}.rpm"
    echo "======================================"
    if [ $verbose -eq 1 ] ; then
      printf "%s %-18s %s\n" ${DASHES} "Done generating RPM package file" ${DASHES}
    else
      echo "Done generating RPM package file"
    fi
  fi
  rm -rf ${RPM_PACKAGE_NAME}
  rm ${RPM_PACKAGE_NAME}.tar.gz
fi

# all done

echo ""
exit 0
