#! /usr/bin/env bash

# This scripts sets up a snapshot on the target build machine.
# TODO: Add question for compiler location :(
# TODO: do export CROSS_COMPILE before setting up the obj-dirs, so that we get the right prefix
# TODO: Use CROSS_COMPILE from environement as default (in case it is already set)

set -e

# check we're in the right directory
if [ ! -d src/l4 -o ! -d src/fiasco ]; then
  echo "Call setup as ./$(basename $0) in the right directory"
  exit 1
fi

if [ -n "$SYSTEM" ]; then
  echo "SYSTEM environment variable set, not good"
  exit 1
fi

CC=${CC:-${CROSS_COMPILE}gcc}
CXX=${CXX:-${CROSS_COMPILE}g++}
LD=${LD:-${CROSS_COMPILE}ld}

add_to_config()
{
  echo "$@" >> obj/.config
}

write_config()
{
  # write out config, fresh version
  mkdir -p obj
  echo '# snapshot build configuration' > obj/.config

  for c in CONF_DO_X86_32 \
           CONF_DO_UX \
           CONF_DO_AMD64 \
           CONF_DO_ARM \
           CONF_DO_ARM_VIRT_PL2 \
	   CONF_DO_ARM_RPIZ \
           CONF_DO_ARM_RPI3 \
           CONF_DO_ARM_RPI4 \
           CONF_DO_ARM_IMX6UL_PL1 \
           CONF_DO_ARM_IMX6UL_PL2 \
           CONF_DO_ARM64 \
           CONF_DO_ARM64_VIRT \
           CONF_DO_ARM64_RCAR3 \
           CONF_DO_ARM64_RPI3 \
           CONF_DO_ARM64_RPI4 \
           CONF_DO_ARM64_RPI5 \
           CONF_DO_ARM64_SBSA \
           CONF_DO_ARM64_S32G \
           CONF_DO_ARM64_ZYNQMP \
           CONF_DO_MIPS32R2 \
           CONF_DO_MIPS32R6 \
           CONF_DO_MIPS64R2 \
           CONF_DO_MIPS64R6 \
           CONF_FAILED_ARM \
           CONF_FAILED_ARM64 \
           CONF_FAILED_UX \
           CONF_FAILED_AMD64 \
           CONF_FAILED_MIPS32R2 \
           CONF_FAILED_MIPS32R6 \
           CONF_FAILED_MIPS64R2 \
           CONF_FAILED_MIPS64R6 \
           CROSS_COMPILE_ARM \
           CROSS_COMPILE_ARM64 \
           CROSS_COMPILE_MIPS32R2 \
           CROSS_COMPILE_MIPS32R6 \
           CROSS_COMPILE_MIPS64R2 \
           CROSS_COMPILE_MIPS64R6 \
  ; do
    local v=$(eval echo \$$c)
    [ -n "$v" ] && add_to_config $c="$v"
  done

  return 0
}

do_clean()
{
  # same as in Makefile
  rm -rf obj
}

do_config()
{
  if [ -n "$SETUP_CONFIG_ALL" ]; then
    CONF_DO_X86_32=1
    CONF_DO_AMD64=1
    #CONF_DO_MIPS=1
    CONF_DO_ARM=1
    CONF_DO_ARM64=1

    CONF_DO_ARM_VIRT_PL2=1
    CONF_DO_ARM_RPIZ=1
    CONF_DO_ARM_RPI3=1
    CONF_DO_ARM_RPI4=1
    CONF_DO_ARM_IMX6UL_PL1=1
    CONF_DO_ARM_IMX6UL_PL2=1
    CONF_DO_ARM64_VIRT=1
    CONF_DO_ARM64_RCAR3=1
    CONF_DO_ARM64_RPI3=1
    CONF_DO_ARM64_RPI4=1
    CONF_DO_ARM64_RPI5=1
    CONF_DO_ARM64_SBSA=1
    CONF_DO_ARM64_S32G=1
    CONF_DO_ARM64_ZYNQMP=1

    #CONF_DO_MIPS32R2=1
    #CONF_DO_MIPS32R6=1
    #CONF_DO_MIPS64R2=1
    #CONF_DO_MIPS64R6=1

    CROSS_COMPILE_ARM=arm-linux-gnueabihf-
    CROSS_COMPILE_ARM64=aarch64-linux-gnu-
    CROSS_COMPILE_MIPS32R2=mips-linux-
    CROSS_COMPILE_MIPS32R6=mips-linux-
    CROSS_COMPILE_MIPS64R2=mips-linux-
    CROSS_COMPILE_MIPS64R6=mips-linux-

    write_config
    return 0;
  fi


  if command -v dialog; then

    tmpfile=`tempfile 2>/dev/null` || tmpfile=/tmp/test$$
    trap "rm -f $tmpfile" 0 1 2 5 15

    dialog \
      --visit-items \
      --begin 2 10 \
	--infobox \
	 "The list of choices represents a popular set of target platforms.  Many more are available." \
	 5 60 \
      --and-widget --begin 9 10 \
	--checklist "Select Targets to build:" 12 60 5 \
	 x86-32    "ia32"                                      off \
	 amd64     "amd64/x86_64 "                             off \
	 arm       "ARM (platform selection follows)"          off \
	 arm64     "ARM64 / AARCH64"                           off \
	 mips      "MIPS"                                      off \
	 2> $tmpfile

	 #UX-32     "  add Fiasco-UX-32 (selects x86-32)"       off

    result=$(cat $tmpfile)

    if [ -z "$result" ]; then
      echo
      echo "ERROR: You did not select any platform."
      echo "ERROR: Please do so by running 'make setup' again."
      echo
      exit 1
    fi


    for e in $result; do
      # fixup for older dialogs
      [ "${e#\"}" = "$e" ] && e="\"$e\""
      case "$e" in
	\"x86-32\") CONF_DO_X86_32=1 ;;
	\"UX-32\") CONF_DO_UX=1; CONF_DO_X86_32=1 ;;
	\"amd64\") CONF_DO_AMD64=1 ;;
	\"mips\") CONF_DO_MIPS=1 ;;
	\"arm\") CONF_DO_ARM=1 ;;
	\"arm64\") CONF_DO_ARM64=1 ;;
      esac
    done

    if [ -n "$CONF_DO_ARM" ]; then
      dialog \
	--visit-items \
	--begin 2 10 \
	  --infobox \
	   "The list of choices represents a popular set of target platforms. Many more are available." \
	   5 60 \
	--and-widget --begin 9 10 \
	  --checklist "Select ARM Targets to build:" 12 60 5 \
	   arm-virt-pl2    "QEMU Virt Platform"  on \
	   arm-rpiz        "Raspberry Pi Zero"   off \
	   arm-rpi3        "Raspberry Pi 3"      off \
	   arm-rpi5        "Raspberry Pi 5"      off \
	   arm-imx6ul-pl1  "NXP i.MX6UL/ULL"     off \
	   arm-imx6ul-pl2  "NXP i.MX6UL/ULL Virtualization" off \
	   2> $tmpfile

      result=$(cat $tmpfile)

      for e in $result; do
	# fixup for older dialogs
	[ "${e#\"}" = "$e" ] && e="\"$e\""
	case "$e" in
	  \"arm-virt-pl2\")   CONF_DO_ARM_VIRT_PL2=1 ;;
	  \"arm-rpiz\")       CONF_DO_ARM_RPIZ=1 ;;
	  \"arm-rpi3\")       CONF_DO_ARM_RPI3=1 ;;
	  \"arm-rpi4\")       CONF_DO_ARM_RPI4=1 ;;
	  \"arm-imx6ul-pl1\") CONF_DO_ARM_IMX6UL_PL1=1 ;;
	  \"arm-imx6ul-pl2\") CONF_DO_ARM_IMX6UL_PL2=1 ;;
	esac
      done
    fi

    if [ -n "$CONF_DO_ARM64" ]; then
      dialog \
	--visit-items \
	--begin 2 10 \
	  --infobox \
	   "The list of choices represents a popular set of target platforms. Many more are available." \
	   5 60 \
	--and-widget --begin 9 10 \
	  --checklist "Select ARM Targets to build:" 11 60 4 \
	   arm64-virt   "QEMU Virt Platform"  on \
	   arm64-rpi3   "Raspberry Pi 3"      off \
	   arm64-rpi4   "Raspberry Pi 4"      off \
	   arm64-rpi5   "Raspberry Pi 5"      off \
	   arm64-rcar3  "Renesas R-Car 3"     off \
	   arm64-s32g   "NXP S32G"            off \
	   arm64-zynqmp "Xilinx ZynqMP"       off \
	   2> $tmpfile

      result=$(cat $tmpfile)

      for e in $result; do
	# fixup for older dialogs
	[ "${e#\"}" = "$e" ] && e="\"$e\""
	case "$e" in
	  \"arm64-virt\")   CONF_DO_ARM64_VIRT=1 ;;
	  \"arm64-rcar3\")  CONF_DO_ARM64_RCAR3=1 ;;
	  \"arm64-rpi3\")   CONF_DO_ARM64_RPI3=1 ;;
	  \"arm64-rpi4\")   CONF_DO_ARM64_RPI4=1 ;;
	  \"arm64-rpi5\")   CONF_DO_ARM64_RPI5=1 ;;
	  \"arm64-sbsa\")   CONF_DO_ARM64_SBSA=1 ;;
	  \"arm64-s32g\")   CONF_DO_ARM64_S32G=1 ;;
	  \"arm64-zynqmp\") CONF_DO_ARM64_ZYNQMP=1 ;;
	esac
      done
    fi

    if [ -n "$CONF_DO_MIPS" ]; then
      dialog \
	--begin 2 10 \
	  --infobox \
	   "Please choose which MIPS little-endian variant to build." \
	   5 60 \
	--and-widget --begin 9 10 \
	  --checklist "Select MIPS variant to build:" 11 60 4 \
	   mips32r2    "MIPS32r2" off \
	   mips32r6    "MIPS32r6" off \
	   mips64r2    "MIPS64r2" off \
	   mips64r6    "MIPS64r6" off \
	   2> $tmpfile

      result=$(cat $tmpfile)
      for e in $result; do
	[ "${e#\"}" = "$e" ] && e="\"$e\""
	case "$e" in
	  \"mips32r2\") CONF_DO_MIPS32R2=1 ;;
	  \"mips32r6\") CONF_DO_MIPS32R6=1 ;;
	  \"mips64r2\") CONF_DO_MIPS64R2=1 ;;
	  \"mips64r6\") CONF_DO_MIPS64R6=1 ;;
	esac
      done
    fi

    # query cross compiler prefix
    #if [ -n "$CONF_DO_X86_32" -o -n "$CONF_DO_AMD64" ]; then
    #  dialog --no-mouse --visit-items \
    #         --inputbox "X86 (cross) compiler prefix (CROSS_COMPILE)" 8 70 "" \
    #      2> $tmpfile
    #  CROSS_COMPILE_X86_32=$(cat $tmpfile)
    #  CROSS_COMPILE_AMD64=$(cat $tmpfile)
    #fi


    if [ -n "$CONF_DO_ARM" ]; then
      dialog --no-mouse --visit-items \
	--inputbox "ARM cross compiler prefix (CROSS_COMPILE)" 8 70 "arm-linux-gnueabihf-" \
	2> $tmpfile
      CROSS_COMPILE_ARM=$(cat $tmpfile)
    fi

    if [ -n "$CONF_DO_ARM64" ]; then
      dialog --no-mouse --visit-items \
	--inputbox "AARCH64 cross compiler prefix (CROSS_COMPILE)" 8 70 "aarch64-linux-gnu-" \
	2> $tmpfile
      CROSS_COMPILE_ARM64=$(cat $tmpfile)
    fi

    if [ -n "$CONF_DO_MIPS32R2" ]; then
      dialog --no-mouse --visit-items \
	--inputbox "MIPS el-32r2 cross compiler prefix (CROSS_COMPILE)" 8 70 "mips-linux-" \
	2> $tmpfile
      CROSS_COMPILE_MIPS32R2=$(cat $tmpfile)
    fi
    if [ -n "$CONF_DO_MIPS32R6" ]; then
      dialog --no-mouse --visit-items \
	--inputbox "MIPS el-32r6 cross compiler prefix (CROSS_COMPILE)" 8 70 "mips-linux-" \
	2> $tmpfile
      CROSS_COMPILE_MIPS32R6=$(cat $tmpfile)
    fi

    if [ -n "$CONF_DO_MIPS64R2" ]; then
      dialog --no-mouse --visit-items \
	--inputbox "MIPS el-64r2 cross compiler prefix (CROSS_COMPILE)" 8 70 "mips-linux-" \
	2> $tmpfile
      CROSS_COMPILE_MIPS64R2=$(cat $tmpfile)
    fi
    if [ -n "$CONF_DO_MIPS64R6" ]; then
      dialog --no-mouse --visit-items \
	--inputbox "MIPS el-64r6 cross compiler prefix (CROSS_COMPILE)" 8 70 "mips-linux-" \
	2> $tmpfile
      CROSS_COMPILE_MIPS64R6=$(cat $tmpfile)
    fi

  else

    echo "'dialog' program not found,"
    echo "press ENTER to continue and just build for x86-64"
    echo "abort with Ctrl-C, install dialog and issue 'make setup' again."
    read 

    CONF_DO_AMD64=1
  fi

  write_config
  return 0;
}

###########################################################

check_build_tools()
{
  if ! command -v make; then
    echo "Please install the 'make' program."
    exit 1;
  fi
  if [ ! -d src/l4 ]; then
    echo "Not the right environment."
    exit 1;
  fi
  cd src/l4 && make check_build_tools
}

load_config()
{
  if [ ! -e obj/.config ]; then
    echo "Configuration missing, not configured?!"
    exit 1
  fi

  . obj/.config
}

redo_config()
{
  if [ -n "$CONF_FAILED_ARM" ]; then
    unset CONF_DO_ARM
    add_to_config "unset CONF_DO_ARM"
    unset CONF_DO_ARM_VIRT_PL2
    unset CONF_DO_ARM_RPIZ
    unset CONF_DO_ARM_RPI3
    unset CONF_DO_ARM_RPI4
    unset CONF_DO_ARM_IMX6UL_PL1
    unset CONF_DO_ARM_IMX6UL_PL2
  fi

  if [ -n "$CONF_FAILED_UX" ]; then
    unset CONF_DO_UX
    add_to_config "unset CONF_DO_UX"
  fi

  if [ -n "$CONF_FAILED_AMD64" ]; then
    unset CONF_DO_AMD64
    add_to_config "unset CONF_DO_AMD64"
  fi

  if [ -n "$CONF_FAILED_MIPS32R2" ]; then
    unset CONF_DO_MIPS32R2
    add_to_config "unset CONF_DO_MIPS32R2"
  fi

  if [ -n "$CONF_FAILED_MIPS32R6" ]; then
    unset CONF_DO_MIPS32R6
    add_to_config "unset CONF_DO_MIPS32R6"
  fi

  if [ -n "$CONF_FAILED_MIPS64R2" ]; then
    unset CONF_DO_MIPS64R2
    add_to_config "unset CONF_DO_MIPS64R2"
  fi

  if [ -n "$CONF_FAILED_MIPS64R6" ]; then
    unset CONF_DO_MIPS64R6
    add_to_config "unset CONF_DO_MIPS64R6"
  fi
}

check_cc()
{
  if [ -n "$1" ]; then
    if echo 'int main(void) { return 0; }' | $1 $2 -c -x c - -o /dev/null; then
      return 0
    fi
  else
    echo "Invalid compiler command given"
  fi
  return 1
}

check_eabi_gcc()
{
  # probably half-hearted approach but well
  [ -z "$1" ] && return 1
  $1 -E -dD -x c /dev/null | grep -qw __ARM_EABI__
}

check_tool()
{
  command -v $1 > /dev/null
  if ! command -v $1 > /dev/null;  then
    return 1
  fi

  case "$1" in
    *gcc|*g++)
      check_cc "$1" "$2"
      return $?
    ;;
    make|*ld)
      $1 -v > /dev/null 2>&1
      return $?
    ;;
    *cpp|*nm)
      $1 --help > /dev/null 2>&1
      return $?
    ;;
    gawk)
      $1 --help > /dev/null 2>&1
      return $?
    ;;
    perl)
      $1 -V > /dev/null 2>&1
      return $?
    ;;
    doxygen)
      doxygen | grep "Doxygen ver" > /dev/null 2>&1
      return $?
    ;;
    qemu-system-arm)
      $1 -h > /dev/null 2>&1
      return $?
    ;;
    *)
      echo "Unknown tool $1"
      return 1
    ;;
  esac
}

#exchange_kconfig_choice()
#{
#  kconfigfile=$1
#  disablesym=$2
#  enablesym=$3
#
#  perl -p -i \
#       -e "s/$disablesym=y/# $disablesym is not set/; s/# $enablesym is not set/$enablesym=y/" \
#       $kconfigfile
#}

#switch_to_kconfig_setup_arm()
#{
#  exchange_kconfig_choice $1 CONFIG_PLATFORM_TYPE_rv $2
#  exchange_kconfig_choice $1 CONFIG_CPU_ARM_ARMV5TE $3
#}

declare -A Makeconf_added_gen
declare -A Makeconf_added_qemu_std

add_gen()
{
  if [ -z "${Makeconf_added_gen[$1]}" ]; then
    if [ -z "$REMOTE" ]; then
      echo "QEMU_OPTIONS += -vnc :4" >> $1
    fi

    echo 'QEMU_OPTIONS += $(QEMU_OPTIONS-$(PLATFORM_TYPE))' >> $1
    echo 'QEMU_OPTIONS += $(QEMU_OPTIONS-$(PLATFORM_TYPE)-$(PLATFORM_CFG))' >> $1
    echo 'QEMU_OPTIONS += $(QEMU_OPTIONS-ENTRY-$(ENTRY))' >> $1
    echo 'MODULE_SEARCH_PATH += $(MODULE_SEARCH_PATH-$(PLATFORM_TYPE))' >> $1
    Makeconf_added_gen[$1]=1
  fi


}

add_std_qemu_options()
{
  if [ -z "${Makeconf_added_qemu_std[$1]}" ]; then
    echo "QEMU_OPTIONS += -serial stdio" >> $1
    Makeconf_added_qemu_std[$1]=1
  fi

  add_gen "$1"
}

add_nonx86_qemu_options()
{
  add_gen "$1"
}

check_cross_tools()
{
  name=$1
  confvar=$2
  confvarfailed=$3
  cross_compile=$4

  if [ -n "$confvar" ]; then
    echo "Checking for needed cross programs and tools for $name"
    tools_needed="${cross_compile}gcc ${cross_compile}cpp ${cross_compile}nm ${cross_compile}g++ ${cross_compile}ld"
    unset failed
    for t in $tools_needed; do
      result="ok"
      if ! check_tool $t; then
        result="Not found or FAILED, disabling $name builds"
        eval $confvarfailed=1
        failed=1
      fi
      printf "%15s ... %s\n" $t "$result"
      if [ -n "$failed" ]; then
        break
      fi
    done
  fi
}

check_tools()
{
# Generic tools
  echo "Checking for needed programs and tools"
  tools_needed="make ${CC} ${CXX} ld gawk perl"
  for t in $tools_needed; do
    result="ok"
    if ! check_tool $t; then
      result="NOT DETECTED"
      command_missing="$command_missing $t"
    fi
    printf "%15s ... %s\n" $t "$result"
  done
  echo
  if [ -n "$command_missing" ]; then
    echo "Some command is missing on your system."
    echo "Please install it before continuing with 'make setup':"
    echo "   $command_missing"
    do_clean
    exit 1
  fi

  if [ -n "$CONF_DO_AMD64" ]; then
    if ! check_tool ${CC} -m64; then
      echo "AMD64 build disabled as ${CC} does not support 64bit targets"
      CONF_FAILED_AMD64=1
    fi
  fi

  check_cross_tools "ARM"      "$CONF_DO_ARM"      CONF_FAILED_ARM      "$CROSS_COMPILE_ARM"
  check_cross_tools "ARM64"    "$CONF_DO_ARM64"    CONF_FAILED_ARM64    "$CROSS_COMPILE_ARM64"
  check_cross_tools "MIPS32r2" "$CONF_DO_MIPS32R2" CONF_FAILED_MIPS32R2 "$CROSS_COMPILE_MIPS32R2"
  check_cross_tools "MIPS32r6" "$CONF_DO_MIPS32R6" CONF_FAILED_MIPS32R6 "$CROSS_COMPILE_MIPS32R6"
  check_cross_tools "MIPS64r2" "$CONF_DO_MIPS64R2" CONF_FAILED_MIPS64R2 "$CROSS_COMPILE_MIPS64R2"
  check_cross_tools "MIPS64r6" "$CONF_DO_MIPS64R6" CONF_FAILED_MIPS64R6 "$CROSS_COMPILE_MIPS64R6"

  if [ -n "$CONF_DO_UX" ]; then
    echo "Checking some specific Fiasco-UX build thing on 64bit platforms"
    if ! echo "#include <sys/cdefs.h>" | ${CC} -m32 -x c -c -o /dev/null - > /dev/null 2>&1; then
      result="Failed, disabling Fiasco-UX builds"
      CONF_FAILED_UX=1
    else
      result="ok"
    fi
    printf "%15s ... %s\n" "UX build" "$result"
  fi
  echo

# Optional tools
  echo "Checking optional programs and tools"
  tools_optional="doxygen"
  [ "$CONF_DO_ARM" ] && tools_needed="$tools_needed qemu-system-arm"
  for t in $tools_optional; do
    result="ok"
    if ! check_tool $t; then
      result="NOT DETECTED but optional"
      command_missing="$command_missing $t"
    fi
    printf "%15s ... %s\n" $t "$result"
  done
  echo
  if [ -n "$command_missing" ]; then
    echo "Some optional command is missing on your system, don't worry."
    echo "   $command_missing"
    echo
  fi
}

do_setup()
{
  [ "$CONF_DO_X86_32" ] && fiasco_configs="$fiasco_configs ia32-1"
  [ "$CONF_DO_X86_32" -a "$CONF_DO_UX" ] && fiasco_configs="$fiasco_configs ux-1"

  [ "$CONF_DO_AMD64" ] && fiasco_configs="$fiasco_configs amd64-4"

  [ "$CONF_DO_ARM_VIRT_PL2" ] && fiasco_configs="$fiasco_configs arm-virt-pl2"
  [ "$CONF_DO_ARM_RPIZ" ] && fiasco_configs="$fiasco_configs arm-rpiz"
  [ "$CONF_DO_ARM_RPI3" ] && fiasco_configs="$fiasco_configs arm-rpi3"
  [ "$CONF_DO_ARM_RPI4" ] && fiasco_configs="$fiasco_configs arm-rpi4"
  [ "$CONF_DO_ARM_IMX6UL_PL1" ] && fiasco_configs="$fiasco_configs arm-imx6ul"
  [ "$CONF_DO_ARM_IMX6UL_PL2" ] && fiasco_configs="$fiasco_configs arm-imx6ul-pl2"

  [ "$CONF_DO_ARM64_VIRT" ] && fiasco_configs="$fiasco_configs arm64-virt-el2 arm64-virt-el1-perf arm64-virt-el2-perf"
  [ "$CONF_DO_ARM64_RCAR3" ] && fiasco_configs="$fiasco_configs arm64-rcar3"
  [ "$CONF_DO_ARM64_RPI3" ] && fiasco_configs="$fiasco_configs arm64-rpi3 arm64-rpi3-perf"
  [ "$CONF_DO_ARM64_RPI4" ] && fiasco_configs="$fiasco_configs arm64-rpi4 arm64-rpi4-el1-perf arm64-rpi4-el2-perf"
  [ "$CONF_DO_ARM64_RPI5" ] && fiasco_configs="$fiasco_configs arm64-rpi5 arm64-rpi5-el1-perf arm64-rpi5-el2-perf"
  [ "$CONF_DO_ARM64_SBSA" ] && fiasco_configs="$fiasco_configs arm64-sbsa"
  [ "$CONF_DO_ARM64_S32G" ] && fiasco_configs="$fiasco_configs arm64-s32g arm64-s32g-el1-perf arm64-s32g-el2-perf"
  [ "$CONF_DO_ARM64_ZYNQMP" ] && fiasco_configs="$fiasco_configs arm64-zynqmp"

  [ "$CONF_DO_MIPS32R2" ] && fiasco_configs="$fiasco_configs mips-baikal-mp mips-malta-mp"
  [ "$CONF_DO_MIPS32R6" ] && fiasco_configs="$fiasco_configs mips-malta-32r6-mp"
  [ "$CONF_DO_MIPS64R2" ] && fiasco_configs="$fiasco_configs mips-malta-64r2-mp"
  [ "$CONF_DO_MIPS64R6" ] && fiasco_configs="$fiasco_configs mips-malta-64r6-mp mips-boston-64r6-mp"

  declare -A fiascodirs
  fiascodirs[ia32-1]="ia32"
  fiascodirs[ux-1]="ux"
  fiascodirs[amd64-4]="amd64"
  fiascodirs[arm64-virt-el1-perf]="arm64-virt-el1-perf"
  fiascodirs[arm64-virt-el2]="arm64-virt-el2"
  fiascodirs[arm64-virt-el2-perf]="arm64-virt-el2-perf"
  fiascodirs[arm64-rcar3]="arm64-rcar3"
  fiascodirs[arm64-rpi3]="arm64-rpi3"
  fiascodirs[arm64-rpi3-perf]="arm64-rpi3-perf"
  fiascodirs[arm64-rpi4]="arm64-rpi4"
  fiascodirs[arm64-rpi4-el1-perf]="arm64-rpi4-el1-perf"
  fiascodirs[arm64-rpi4-el2-perf]="arm64-rpi4-el2-perf"
  fiascodirs[arm64-rpi5]="arm64-rpi5"
  fiascodirs[arm64-rpi5-el1-perf]="arm64-rpi5-el1-perf"
  fiascodirs[arm64-rpi5-el2-perf]="arm64-rpi5-el2-perf"
  fiascodirs[arm64-sbsa]="arm64-sbsa"
  fiascodirs[arm64-s32g]="arm64-s32g"
  fiascodirs[arm64-s32g-el1-perf]="arm64-s32g-el1-perf"
  fiascodirs[arm64-s32g-el2-perf]="arm64-s32g-el2-perf"
  fiascodirs[arm64-zynqmp]="arm64-zynqmp"
  fiascodirs[arm-virt-pl2]="arm-virt-pl2"
  fiascodirs[arm-rpiz]="arm-rpiz"
  fiascodirs[arm-rpi3]="arm-rpi3"
  fiascodirs[arm-rpi4]="arm-rpi4"
  fiascodirs[arm-imx6ul]="arm-imx6ul-pl1"
  fiascodirs[arm-imx6ul-pl2]="arm-imx6ul-pl2"
  fiascodirs[mips-malta-mp]="mips32-malta"
  fiascodirs[mips-baikal-mp]="mips32-baikal-mp"
  fiascodirs[mips-malta-32r6-mp]="mips-malta-32r6-mp"
  fiascodirs[mips-malta-64r2-mp]="mips64r2-malta"
  fiascodirs[mips-boston-64r6-mp]="mips-boston-64r6-mp"
  fiascodirs[mips-malta-64r6-mp]="mips-malta-64r6-mp"

  declare -A fiascocrosscomp
  fiascocrosscomp[ia32-1]=$CROSS_COMPILE_X86_32
  fiascocrosscomp[ux-1]=$CROSS_COMPILE_X86_32
  fiascocrosscomp[amd64-4]=$CROSS_COMPILE_AMD64
  fiascocrosscomp[arm64-virt-el1-perf]=$CROSS_COMPILE_ARM64
  fiascocrosscomp[arm64-virt-el2]=$CROSS_COMPILE_ARM64
  fiascocrosscomp[arm64-virt-el2-perf]=$CROSS_COMPILE_ARM64
  fiascocrosscomp[arm64-rcar3]=$CROSS_COMPILE_ARM64
  fiascocrosscomp[arm64-rpi3]=$CROSS_COMPILE_ARM64
  fiascocrosscomp[arm64-rpi3-perf]=$CROSS_COMPILE_ARM64
  fiascocrosscomp[arm64-rpi4]=$CROSS_COMPILE_ARM64
  fiascocrosscomp[arm64-rpi4-el1-perf]=$CROSS_COMPILE_ARM64
  fiascocrosscomp[arm64-rpi4-el2-perf]=$CROSS_COMPILE_ARM64
  fiascocrosscomp[arm64-rpi5]=$CROSS_COMPILE_ARM64
  fiascocrosscomp[arm64-rpi5-el1-perf]=$CROSS_COMPILE_ARM64
  fiascocrosscomp[arm64-rpi5-el2-perf]=$CROSS_COMPILE_ARM64
  fiascocrosscomp[arm64-sbsa]=$CROSS_COMPILE_ARM64
  fiascocrosscomp[arm64-s32g]=$CROSS_COMPILE_ARM64
  fiascocrosscomp[arm64-s32g-el1-perf]=$CROSS_COMPILE_ARM64
  fiascocrosscomp[arm64-s32g-el2-perf]=$CROSS_COMPILE_ARM64
  fiascocrosscomp[arm64-zynqmp]=$CROSS_COMPILE_ARM64
  fiascocrosscomp[arm-virt-pl2]=$CROSS_COMPILE_ARM
  fiascocrosscomp[arm-rpiz]=$CROSS_COMPILE_ARM
  fiascocrosscomp[arm-rpi3]=$CROSS_COMPILE_ARM
  fiascocrosscomp[arm-rpi4]=$CROSS_COMPILE_ARM
  fiascocrosscomp[arm-imx6ul]=$CROSS_COMPILE_ARM
  fiascocrosscomp[arm-imx6ul-pl2]=$CROSS_COMPILE_ARM
  fiascocrosscomp[mips-malta-mp]=$CROSS_COMPILE_MIPS32R2
  fiascocrosscomp[mips-baikal-mp]=$CROSS_COMPILE_MIPS32R2
  fiascocrosscomp[mips-malta-32r6-mp]=$CROSS_COMPILE_MIPS32R6
  fiascocrosscomp[mips-malta-64r2-mp]=$CROSS_COMPILE_MIPS64R2
  fiascocrosscomp[mips-boston-64r6-mp]=$CROSS_COMPILE_MIPS64R6
  fiascocrosscomp[mips-malta-64r6-mp]=$CROSS_COMPILE_MIPS64R6

  echo "Creating build directories..."

  mkdir -p obj/fiasco
  mkdir -p obj/l4
  mkdir -p obj/l4linux

  [ -e src/l4linux ] && l4lx_avail=1

  # Fiasco build dirs
  for b in $fiasco_configs; do
    echo ${fiascodirs[$b]} "->" $b
    if [ -z "${fiascodirs[$b]}" ]; then
      echo "Internal error: No directory given for config '$b'"
      exit 1
    fi
    if [ -z "${fiascocrosscomp[$b]}" -a ! "$b" = ia32-1 -a ! "$b" = ux-1 -a ! "$b" = amd64-4 ]; then
      echo "Internal error: No cross compiler given for config '$b'"
      exit 1
    fi
    (cd src/fiasco && make CROSS_COMPILE=${fiascocrosscomp[$b]} B=../../obj/fiasco/${fiascodirs[$b]} T=$b)
    echo CROSS_COMPILE=${fiascocrosscomp[$b]} >> obj/fiasco/${fiascodirs[$b]}/Makeconf.local
  done

  # some config tweaking
  if [ "$CONF_DO_MIPS32R2" ]; then
    echo '# CONFIG_MP is not set' >> obj/fiasco/mips32-malta/globalconfig.out
  fi




  # L4Re build dirs with default configs
  [ "$CONF_DO_X86_32" ] \
    && make -C src/l4 DEFCONFIG=mk/defconfig/config.x86 B=../../obj/l4/x86

  [ "$CONF_DO_AMD64" ] \
    && make -C src/l4 DEFCONFIG=mk/defconfig/config.amd64 B=../../obj/l4/amd64

  if [ "$CONF_DO_ARM" ]; then
    make -C src/l4 CROSS_COMPILE=$CROSS_COMPILE_ARM \
      DEFCONFIG=mk/defconfig/config.arm-rv-v7a B=../../obj/l4/arm-v7
    make -C obj/l4/arm-v7 CROSS_COMPILE=$CROSS_COMPILE_ARM oldconfig
    ARM_L4_DIR_FOR_LX_MP=obj/l4/arm-v7
    echo CROSS_COMPILE=$CROSS_COMPILE_ARM >> obj/l4/arm-v7/Makeconf.local
  fi

  if [ "$CONF_DO_ARM64" ]; then
    make -C src/l4 CROSS_COMPILE=$CROSS_COMPILE_ARM64 DEFCONFIG=mk/defconfig/config.arm64-rv-v8a B=../../obj/l4/arm64
  fi

  if [ "$CONF_DO_MIPS32R2" ]; then
    cp src/l4/mk/defconfig/config.mips .tmp1
    echo CONFIG_PLATFORM_TYPE_malta=y >> .tmp1
    echo CONFIG_CPU_MIPS_32R2=y >> .tmp1
    make -C src/l4 DEFCONFIG=../../.tmp1 \
      CROSS_COMPILE=$CROSS_COMPILE_MIPS32R2 B=../../obj/l4/mips32r2
    rm .tmp1
    echo CROSS_COMPILE=$CROSS_COMPILE_MIPS32R2 >> obj/l4/mips32r2/Makeconf.local
  fi
  if [ "$CONF_DO_MIPS32R6" ]; then
    cp src/l4/mk/defconfig/config.mips .tmp1
    echo CONFIG_PLATFORM_TYPE_malta=y >> .tmp1
    echo CONFIG_CPU_MIPS_32R6=y >> .tmp1
    make -C src/l4 DEFCONFIG=../../.tmp1 \
      CROSS_COMPILE=$CROSS_COMPILE_MIPS32R6 B=../../obj/l4/mips32r6
    rm .tmp1
    echo CROSS_COMPILE=$CROSS_COMPILE_MIPS32R6 >> obj/l4/mips32r6/Makeconf.local
  fi
  if [ "$CONF_DO_MIPS64R2" ]; then
    cp src/l4/mk/defconfig/config.mips .tmp1
    echo CONFIG_PLATFORM_TYPE_malta=y >> .tmp1
    echo CONFIG_CPU_MIPS_64R2=y >> .tmp1
    make -C src/l4 DEFCONFIG=../../.tmp1 \
      CROSS_COMPILE=$CROSS_COMPILE_MIPS64R2 B=../../obj/l4/mips64r2
    rm .tmp1
    echo CROSS_COMPILE=$CROSS_COMPILE_MIPS64R2 >> obj/l4/mips64r2/Makeconf.local
  fi
  if [ "$CONF_DO_MIPS64R6" ]; then
    cp src/l4/mk/defconfig/config.mips .tmp1
    echo CONFIG_PLATFORM_TYPE_boston=y >> .tmp1
    echo CONFIG_CPU_MIPS_64R6=y >> .tmp1
    make -C src/l4 DEFCONFIG=../../.tmp1 \
      CROSS_COMPILE=$CROSS_COMPILE_MIPS64R6 B=../../obj/l4/mips64r6
    rm .tmp1
    echo CROSS_COMPILE=$CROSS_COMPILE_MIPS64R6 >> obj/l4/mips64r6/Makeconf.local
  fi


  # L4Linux build setup
  if [ "$CONF_DO_X86_32" -a -n "$l4lx_avail" ]; then
    mkdir -p obj/l4linux/ux
  fi

  if [ "$CONF_DO_AMD64" -a -n "$l4lx_avail" ]; then
    mkdir -p obj/l4linux/amd64
  fi

  if [ "$CONF_DO_ARM64" -a -n "$l4lx_avail" ]; then
    mkdir -p obj/l4linux/arm64
  fi

  [ -z "$ARM_L4_DIR_FOR_LX_UP" ] && ARM_L4_DIR_FOR_LX_UP=$ARM_L4_DIR_FOR_LX_MP

  if [ -n "$ARM_L4_DIR_FOR_LX_UP" -a -n "$l4lx_avail" ]; then

    mkdir -p obj/l4linux/arm-up

    if [ "$ARM_L4_DIR_FOR_LX_MP" ]; then
      mkdir -p obj/l4linux/arm-mp
    fi

    if ! check_eabi_gcc ${CROSS_COMPILE_ARM}gcc; then
      echo "WARNING: L4Linux has been disabled due to a detected old OABI compiler"
      echo "WARNING: Please update your compiler to an EABI version"
      add_to_config SKIP_L4LINUX_ARM_BUILD=1
    fi
  fi

  common_paths=$(pwd)/files:$(pwd)/files/cfg:$(pwd)/src/l4/conf:$(pwd)/src/l4/conf/examples


  if [ "$CONF_DO_X86_32" ]; then
    local odir=obj/l4/x86
    local Mboot=$odir/conf/Makeconf.boot
    mkdir -p $odir/conf

    cat<<EOF >> obj/l4/x86/conf/Makeconf.boot
MODULE_SEARCH_PATH=$(pwd)/obj/fiasco/ia32:$(pwd)/obj/l4linux/ux:$common_paths
EOF
    add_std_qemu_options obj/l4/x86/conf/Makeconf.boot

    echo "ENTRY=hello"               >> $odir/.imagebuilds
    echo "ENTRY=hello-cfg"           >> $odir/.imagebuilds
    echo "ENTRY=hello-2"             >> $odir/.imagebuilds
    echo "ENTRY=hello-shared"        >> $odir/.imagebuilds
    echo "ENTRY=framebuffer-example" >> $odir/.imagebuilds
    if [ -n "$l4lx_avail" ]; then
      echo "ENTRY=L4Linux-basic"     >> $odir/.imagebuilds
      echo "ENTRY=L4Linux-mag"       >> $odir/.imagebuilds
    fi
  fi

  if [ "$CONF_DO_AMD64" ]; then
    local odir=obj/l4/amd64
    local Mboot=$odir/conf/Makeconf.boot
    mkdir -p $odir/conf

    cat<<EOF >> obj/l4/amd64/conf/Makeconf.boot
MODULE_SEARCH_PATH=$(pwd)/obj/fiasco/amd64:$(pwd)/obj/l4linux/amd64:$common_paths
QEMU_OPTIONS += -m 1024
QEMU_OPTIONS-ENTRY-vm-basic     += -enable-kvm -M q35 -cpu host,vmx=on
QEMU_OPTIONS-ENTRY-vm-basic-pci += -enable-kvm -M q35 -cpu host,vmx=on -device intel-iommu,intremap=on -M kernel_irqchip=split
QEMU_OPTIONS-ENTRY-vm-multi     += -enable-kvm -M q35 -cpu host,vmx=on
QEMU_OPTIONS-ENTRY-vm-multi-p2p += -enable-kvm -M q35 -cpu host,vmx=on
EOF
    add_std_qemu_options obj/l4/amd64/conf/Makeconf.boot
    echo "ENTRY=hello"               >> $odir/.imagebuilds
    echo "ENTRY=hello-cfg"           >> $odir/.imagebuilds
    echo "ENTRY=hello-2"             >> $odir/.imagebuilds
    echo "ENTRY=hello-shared"        >> $odir/.imagebuilds
    echo "ENTRY=ipcbench"            >> $odir/.imagebuilds
    echo "ENTRY=framebuffer-example" >> $odir/.imagebuilds
    echo "ENTRY=vm-basic"            >> $odir/.imagebuilds
    echo "ENTRY=vm-basic-pci"        >> $odir/.imagebuilds
    echo "ENTRY=vm-multi"            >> $odir/.imagebuilds
    echo "ENTRY=vm-multi-p2p"        >> $odir/.imagebuilds
    if [ -n "$l4lx_avail" ]; then
      echo "ENTRY=L4Linux-basic"     >> $odir/.imagebuilds
      echo "ENTRY=L4Linux-mag"       >> $odir/.imagebuilds
    fi
  fi




  if [ "$CONF_DO_ARM" ]; then
    local odir=obj/l4/arm-v7
    local Mboot=$odir/conf/Makeconf.boot
    mkdir -p $odir/conf

    echo "MODULE_SEARCH_PATH+=\$(PATH_FIASCO):$(pwd)/obj/l4linux/arm-mp:$common_paths" >> $Mboot

    if [ "$CONF_DO_ARM_VIRT_PL2" ]; then
      cat<<EOF >> $Mboot
QEMU_OPTIONS-arm_virt += -M virt,virtualization=true -m 1024 -cpu cortex-a15 -smp 3
EOF
      echo "ENTRY=hello           BOOTSTRAP_IMAGE_SUFFIX=arm_virt PT=arm_virt PATH_FIASCO=$(pwd)/obj/fiasco/arm-virt-pl2" >> $odir/.imagebuilds
      echo "ENTRY=hello-shared    BOOTSTRAP_IMAGE_SUFFIX=arm_virt PT=arm_virt PATH_FIASCO=$(pwd)/obj/fiasco/arm-virt-pl2" >> $odir/.imagebuilds
      echo "ENTRY=hello-cfg       BOOTSTRAP_IMAGE_SUFFIX=arm_virt PT=arm_virt PATH_FIASCO=$(pwd)/obj/fiasco/arm-virt-pl2" >> $odir/.imagebuilds
      echo "ENTRY=hello-2         BOOTSTRAP_IMAGE_SUFFIX=arm_virt PT=arm_virt PATH_FIASCO=$(pwd)/obj/fiasco/arm-virt-pl2" >> $odir/.imagebuilds
      echo "ENTRY=vm-basic        BOOTSTRAP_IMAGE_SUFFIX=arm_virt PT=arm_virt PATH_FIASCO=$(pwd)/obj/fiasco/arm-virt-pl2" >> $odir/.imagebuilds
      echo "ENTRY=vm-multi        BOOTSTRAP_IMAGE_SUFFIX=arm_virt PT=arm_virt PATH_FIASCO=$(pwd)/obj/fiasco/arm-virt-pl2" >> $odir/.imagebuilds
      echo "ENTRY=vm-multi-p2p    BOOTSTRAP_IMAGE_SUFFIX=arm_virt PT=arm_virt PATH_FIASCO=$(pwd)/obj/fiasco/arm-virt-pl2" >> $odir/.imagebuilds
      if [ -n "$l4lx_avail" ]; then
        echo "ENTRY=L4Linux-basic BOOTSTRAP_IMAGE_SUFFIX=arm_virt PT=arm_virt PATH_FIASCO=$(pwd)/obj/fiasco/arm-virt-pl2"     >> $odir/.imagebuilds
      fi
    fi

    if [ "$CONF_DO_ARM_RPIZ" ]; then
      echo "ENTRY=hello        BOOTSTRAP_IMAGE_SUFFIX=rpiz PT=rpi PATH_FIASCO=$(pwd)/obj/fiasco/arm-rpiz" >> $odir/.imagebuilds
      echo "ENTRY=hello-cfg    BOOTSTRAP_IMAGE_SUFFIX=rpiz PT=rpi PATH_FIASCO=$(pwd)/obj/fiasco/arm-rpiz" >> $odir/.imagebuilds
      echo "ENTRY=hello-2      BOOTSTRAP_IMAGE_SUFFIX=rpiz PT=rpi PATH_FIASCO=$(pwd)/obj/fiasco/arm-rpiz" >> $odir/.imagebuilds
      echo "ENTRY=hello-shared BOOTSTRAP_IMAGE_SUFFIX=rpiz PT=rpi PATH_FIASCO=$(pwd)/obj/fiasco/arm-rpiz" >> $odir/.imagebuilds
      if [ -n "$l4lx_avail" ]; then
        echo "ENTRY=L4Linux-basic BOOTSTRAP_IMAGE_SUFFIX=rpi PT=rpi PATH_FIASCO=$(pwd)/obj/fiasco/arm-rpiz"     >> $odir/.imagebuilds
      fi
    fi

    if [ "$CONF_DO_ARM_RPI3" ]; then
      echo "ENTRY=hello        BOOTSTRAP_IMAGE_SUFFIX=rpi3 PT=rpi PATH_FIASCO=$(pwd)/obj/fiasco/arm-rpi3" >> $odir/.imagebuilds
      echo "ENTRY=hello-cfg    BOOTSTRAP_IMAGE_SUFFIX=rpi3 PT=rpi PATH_FIASCO=$(pwd)/obj/fiasco/arm-rpi3" >> $odir/.imagebuilds
      echo "ENTRY=hello-2      BOOTSTRAP_IMAGE_SUFFIX=rpi3 PT=rpi PATH_FIASCO=$(pwd)/obj/fiasco/arm-rpi3" >> $odir/.imagebuilds
      echo "ENTRY=hello-shared BOOTSTRAP_IMAGE_SUFFIX=rpi3 PT=rpi PATH_FIASCO=$(pwd)/obj/fiasco/arm-rpi3" >> $odir/.imagebuilds
      if [ -n "$l4lx_avail" ]; then
        echo "ENTRY=L4Linux-basic BOOTSTRAP_IMAGE_SUFFIX=rpi3 PT=rpi PATH_FIASCO=$(pwd)/obj/fiasco/arm-rpi3"     >> $odir/.imagebuilds
      fi
    fi

    if [ "$CONF_DO_ARM_RPI4" ]; then
      echo "ENTRY=hello           BOOTSTRAP_IMAGE_SUFFIX=rpi4 PT=rpi PATH_FIASCO=$(pwd)/obj/fiasco/arm-rpi4" >> $odir/.imagebuilds
      echo "ENTRY=hello-cfg       BOOTSTRAP_IMAGE_SUFFIX=rpi4 PT=rpi PATH_FIASCO=$(pwd)/obj/fiasco/arm-rpi4" >> $odir/.imagebuilds
      echo "ENTRY=hello-2         BOOTSTRAP_IMAGE_SUFFIX=rpi4 PT=rpi PATH_FIASCO=$(pwd)/obj/fiasco/arm-rpi4" >> $odir/.imagebuilds
      echo "ENTRY=hello-shared    BOOTSTRAP_IMAGE_SUFFIX=rpi4 PT=rpi PATH_FIASCO=$(pwd)/obj/fiasco/arm-rpi4" >> $odir/.imagebuilds
      echo "ENTRY=vm-basic        BOOTSTRAP_IMAGE_SUFFIX=rpi4 PT=rpi PATH_FIASCO=$(pwd)/obj/fiasco/arm-rpi4" >> $odir/.imagebuilds
      echo "ENTRY=vm-multi        BOOTSTRAP_IMAGE_SUFFIX=rpi4 PT=rpi PATH_FIASCO=$(pwd)/obj/fiasco/arm-rpi4" >> $odir/.imagebuilds
      echo "ENTRY=vm-multi-p2p    BOOTSTRAP_IMAGE_SUFFIX=rpi4 PT=rpi PATH_FIASCO=$(pwd)/obj/fiasco/arm-rpi4" >> $odir/.imagebuilds
      if [ -n "$l4lx_avail" ]; then
        echo "ENTRY=L4Linux-basic BOOTSTRAP_IMAGE_SUFFIX=rpi4 PT=rpi PATH_FIASCO=$(pwd)/obj/fiasco/arm-rpi4"     >> $odir/.imagebuilds
      fi
    fi

    if [ "$CONF_DO_ARM_IMX6UL_PL1" ]; then
      echo "ENTRY=hello        BOOTSTRAP_IMAGE_SUFFIX=imx6ul-pl1 PT=imx6ul PATH_FIASCO=$(pwd)/obj/fiasco/arm-imx6ul-pl1" >> $odir/.imagebuilds
      echo "ENTRY=hello-cfg    BOOTSTRAP_IMAGE_SUFFIX=imx6ul-pl1 PT=imx6ul PATH_FIASCO=$(pwd)/obj/fiasco/arm-imx6ul-pl1" >> $odir/.imagebuilds
      echo "ENTRY=hello-2      BOOTSTRAP_IMAGE_SUFFIX=imx6ul-pl1 PT=imx6ul PATH_FIASCO=$(pwd)/obj/fiasco/arm-imx6ul-pl1" >> $odir/.imagebuilds
      echo "ENTRY=hello-shared BOOTSTRAP_IMAGE_SUFFIX=imx6ul-pl1 PT=imx6ul PATH_FIASCO=$(pwd)/obj/fiasco/arm-imx6ul-pl1" >> $odir/.imagebuilds
      if [ -n "$l4lx_avail" ]; then
        echo "ENTRY=L4Linux-basic BOOTSTRAP_IMAGE_SUFFIX=imx6ul-pl1 PT=imx6ul PATH_FIASCO=$(pwd)/obj/fiasco/arm-imx6ul-pl1" >> $odir/.imagebuilds
      fi
    fi

    if [ "$CONF_DO_ARM_IMX6UL_PL2" ]; then
      echo "ENTRY=hello           BOOTSTRAP_IMAGE_SUFFIX=imx6ul-pl2 PT=imx6ul PATH_FIASCO=$(pwd)/obj/fiasco/arm-imx6ul-pl2" >> $odir/.imagebuilds
      echo "ENTRY=hello-cfg       BOOTSTRAP_IMAGE_SUFFIX=imx6ul-pl2 PT=imx6ul PATH_FIASCO=$(pwd)/obj/fiasco/arm-imx6ul-pl2" >> $odir/.imagebuilds
      echo "ENTRY=hello-2         BOOTSTRAP_IMAGE_SUFFIX=imx6ul-pl2 PT=imx6ul PATH_FIASCO=$(pwd)/obj/fiasco/arm-imx6ul-pl2" >> $odir/.imagebuilds
      echo "ENTRY=hello-shared    BOOTSTRAP_IMAGE_SUFFIX=imx6ul-pl2 PT=imx6ul PATH_FIASCO=$(pwd)/obj/fiasco/arm-imx6ul-pl2" >> $odir/.imagebuilds
      echo "ENTRY=vm-basic        BOOTSTRAP_IMAGE_SUFFIX=imx6ul-pl2 PT=imx6ul PATH_FIASCO=$(pwd)/obj/fiasco/arm-imx6ul-pl2" >> $odir/.imagebuilds
      echo "ENTRY=vm-multi        BOOTSTRAP_IMAGE_SUFFIX=imx6ul-pl2 PT=imx6ul PATH_FIASCO=$(pwd)/obj/fiasco/arm-imx6ul-pl2" >> $odir/.imagebuilds
      echo "ENTRY=vm-multi-p2p    BOOTSTRAP_IMAGE_SUFFIX=imx6ul-pl2 PT=imx6ul PATH_FIASCO=$(pwd)/obj/fiasco/arm-imx6ul-pl2" >> $odir/.imagebuilds
      if [ -n "$l4lx_avail" ]; then
        echo "ENTRY=L4Linux-basic BOOTSTRAP_IMAGE_SUFFIX=imx6ul-pl2 PT=imx6ul PATH_FIASCO=$(pwd)/obj/fiasco/arm-imx6ul-pl2" >> $odir/.imagebuilds
      fi
    fi

    add_std_qemu_options $Mboot
    add_nonx86_qemu_options $Mboot
  fi # ARM




  if [ "$CONF_DO_ARM64" ]; then
    local odir=obj/l4/arm64
    local Mboot=$odir/conf/Makeconf.boot
    mkdir -p $odir/conf

    echo "MODULE_SEARCH_PATH+=\$(PATH_FIASCO):$(pwd)/obj/l4linux/arm64:$common_paths" >> $Mboot

    if [ "$CONF_DO_ARM64_VIRT" ]; then
      cat<<EOF >> $Mboot
QEMU_OPTIONS-arm_virt-el1 += -M virt,virtualization=false -m 1024 -cpu cortex-a57 -smp 3
QEMU_OPTIONS-arm_virt-el2 += -M virt,virtualization=true  -m 1024 -cpu cortex-a57 -smp 3
EOF
      echo "ENTRY=hello           TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=arm_virt     PT=arm_virt PLATFORM_CFG=el2 PATH_FIASCO=$(pwd)/obj/fiasco/arm64-virt-el2" >> $odir/.imagebuilds
      echo "ENTRY=hello-cfg       TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=arm_virt     PT=arm_virt PLATFORM_CFG=el2 PATH_FIASCO=$(pwd)/obj/fiasco/arm64-virt-el2" >> $odir/.imagebuilds
      echo "ENTRY=hello-2         TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=arm_virt     PT=arm_virt PLATFORM_CFG=el2 PATH_FIASCO=$(pwd)/obj/fiasco/arm64-virt-el2" >> $odir/.imagebuilds
      echo "ENTRY=hello-shared    TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=arm_virt     PT=arm_virt PLATFORM_CFG=el2 PATH_FIASCO=$(pwd)/obj/fiasco/arm64-virt-el2" >> $odir/.imagebuilds
      echo "ENTRY=ipcbench        TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=arm_virt-el1 PT=arm_virt PLATFORM_CFG=el1 PATH_FIASCO=$(pwd)/obj/fiasco/arm64-virt-el1-perf" >> $odir/.imagebuilds
      echo "ENTRY=ipcbench        TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=arm_virt-el2 PT=arm_virt PLATFORM_CFG=el2 PATH_FIASCO=$(pwd)/obj/fiasco/arm64-virt-el2-perf" >> $odir/.imagebuilds
      echo "ENTRY=vm-basic        TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=arm_virt     PT=arm_virt PLATFORM_CFG=el2 PATH_FIASCO=$(pwd)/obj/fiasco/arm64-virt-el2" >> $odir/.imagebuilds
      echo "ENTRY=vm-multi        TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=arm_virt     PT=arm_virt PLATFORM_CFG=el2 PATH_FIASCO=$(pwd)/obj/fiasco/arm64-virt-el2" >> $odir/.imagebuilds
      echo "ENTRY=vm-multi-p2p    TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=arm_virt     PT=arm_virt PLATFORM_CFG=el2 PATH_FIASCO=$(pwd)/obj/fiasco/arm64-virt-el2" >> $odir/.imagebuilds
      if [ -n "$l4lx_avail" ]; then
        echo "ENTRY=L4Linux-basic TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=arm_virt     PT=arm_virt PLATFORM_CFG=el2 PATH_FIASCO=$(pwd)/obj/fiasco/arm64-virt-el2" >> $odir/.imagebuilds
      fi
    fi

    if [ "$CONF_DO_ARM64_RCAR3" ]; then
      echo "ENTRY=hello           TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=rcar3 PT=rcar3 PATH_FIASCO=$(pwd)/obj/fiasco/arm64-rcar3" >> $odir/.imagebuilds
      echo "ENTRY=hello-cfg       TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=rcar3 PT=rcar3 PATH_FIASCO=$(pwd)/obj/fiasco/arm64-rcar3" >> $odir/.imagebuilds
      echo "ENTRY=hello-2         TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=rcar3 PT=rcar3 PATH_FIASCO=$(pwd)/obj/fiasco/arm64-rcar3" >> $odir/.imagebuilds
      echo "ENTRY=hello-shared    TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=rcar3 PT=rcar3 PATH_FIASCO=$(pwd)/obj/fiasco/arm64-rcar3" >> $odir/.imagebuilds
      echo "ENTRY=vm-basic        TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=rcar3 PT=rcar3 PATH_FIASCO=$(pwd)/obj/fiasco/arm64-rcar3" >> $odir/.imagebuilds
      echo "ENTRY=vm-multi        TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=rcar3 PT=rcar3 PATH_FIASCO=$(pwd)/obj/fiasco/arm64-rcar3" >> $odir/.imagebuilds
      echo "ENTRY=vm-multi-p2p    TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=rcar3 PT=rcar3 PATH_FIASCO=$(pwd)/obj/fiasco/arm64-rcar3" >> $odir/.imagebuilds
    fi

    if [ "$CONF_DO_ARM64_RPI3" ]; then
      echo "ENTRY=hello        TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=rpi3 PT=rpi PATH_FIASCO=$(pwd)/obj/fiasco/arm64-rpi3" >> $odir/.imagebuilds
      echo "ENTRY=hello-cfg    TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=rpi3 PT=rpi PATH_FIASCO=$(pwd)/obj/fiasco/arm64-rpi3" >> $odir/.imagebuilds
      echo "ENTRY=hello-2      TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=rpi3 PT=rpi PATH_FIASCO=$(pwd)/obj/fiasco/arm64-rpi3" >> $odir/.imagebuilds
      echo "ENTRY=hello-shared TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=rpi3 PT=rpi PATH_FIASCO=$(pwd)/obj/fiasco/arm64-rpi3" >> $odir/.imagebuilds
      echo "ENTRY=ipcbench     TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=rpi3 PT=rpi PATH_FIASCO=$(pwd)/obj/fiasco/arm64-rpi3-perf" >> $odir/.imagebuilds
    fi

    if [ "$CONF_DO_ARM64_RPI4" ]; then
      echo "ENTRY=hello           TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=rpi4 PT=rpi PATH_FIASCO=$(pwd)/obj/fiasco/arm64-rpi4" >> $odir/.imagebuilds
      echo "ENTRY=hello-cfg       TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=rpi4 PT=rpi PATH_FIASCO=$(pwd)/obj/fiasco/arm64-rpi4" >> $odir/.imagebuilds
      echo "ENTRY=hello-2         TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=rpi4 PT=rpi PATH_FIASCO=$(pwd)/obj/fiasco/arm64-rpi4" >> $odir/.imagebuilds
      echo "ENTRY=hello-shared    TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=rpi4 PT=rpi PATH_FIASCO=$(pwd)/obj/fiasco/arm64-rpi4" >> $odir/.imagebuilds
      echo "ENTRY=ipcbench        TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=rpi4-el1 PT=rpi PATH_FIASCO=$(pwd)/obj/fiasco/arm64-rpi4-el1-perf" >> $odir/.imagebuilds
      echo "ENTRY=ipcbench        TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=rpi4-el2 PT=rpi PATH_FIASCO=$(pwd)/obj/fiasco/arm64-rpi4-el2-perf" >> $odir/.imagebuilds
      echo "ENTRY=vm-basic        TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=rpi4 PT=rpi PATH_FIASCO=$(pwd)/obj/fiasco/arm64-rpi4" >> $odir/.imagebuilds
      echo "ENTRY=vm-multi        TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=rpi4 PT=rpi PATH_FIASCO=$(pwd)/obj/fiasco/arm64-rpi4" >> $odir/.imagebuilds
      echo "ENTRY=vm-multi-p2p    TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=rpi4 PT=rpi PATH_FIASCO=$(pwd)/obj/fiasco/arm64-rpi4" >> $odir/.imagebuilds
    fi

    if [ "$CONF_DO_ARM64_RPI5" ]; then
      echo "ENTRY=hello           TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=rpi5 PT=rpi PATH_FIASCO=$(pwd)/obj/fiasco/arm64-rpi5" >> $odir/.imagebuilds
      echo "ENTRY=hello-cfg       TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=rpi5 PT=rpi PATH_FIASCO=$(pwd)/obj/fiasco/arm64-rpi5" >> $odir/.imagebuilds
      echo "ENTRY=hello-2         TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=rpi5 PT=rpi PATH_FIASCO=$(pwd)/obj/fiasco/arm64-rpi5" >> $odir/.imagebuilds
      echo "ENTRY=hello-shared    TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=rpi5 PT=rpi PATH_FIASCO=$(pwd)/obj/fiasco/arm64-rpi5" >> $odir/.imagebuilds
      echo "ENTRY=ipcbench        TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=rpi5-el1 PT=rpi PATH_FIASCO=$(pwd)/obj/fiasco/arm64-rpi5-el1-perf" >> $odir/.imagebuilds
      echo "ENTRY=ipcbench        TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=rpi5-el2 PT=rpi PATH_FIASCO=$(pwd)/obj/fiasco/arm64-rpi5-el2-perf" >> $odir/.imagebuilds
      echo "ENTRY=vm-basic        TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=rpi5 PT=rpi PATH_FIASCO=$(pwd)/obj/fiasco/arm64-rpi5" >> $odir/.imagebuilds
      echo "ENTRY=vm-multi        TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=rpi5 PT=rpi PATH_FIASCO=$(pwd)/obj/fiasco/arm64-rpi5" >> $odir/.imagebuilds
      echo "ENTRY=vm-multi-p2p    TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=rpi5 PT=rpi PATH_FIASCO=$(pwd)/obj/fiasco/arm64-rpi5" >> $odir/.imagebuilds
    fi

    if [ "$CONF_DO_ARM64_SBSA" ]; then
      cat<<EOF >> $Mboot
QEMU_OPTIONS-arm_sbsa += -M virt,virtualization=on,gic-version=3,iommu=smmuv3 -cpu neoverse-n2,pauth=off,sve=off -bios /usr/share/qemu-efi-aarch64/QEMU_EFI.fd -net nic,model=e1000e -net user
EOF
      echo "ENTRY=hello           TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=sbsa PT=arm_sbsa PATH_FIASCO=$(pwd)/obj/fiasco/arm64-sbsa" >> $odir/.imagebuilds
      echo "ENTRY=hello-cfg       TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=sbsa PT=arm_sbsa PATH_FIASCO=$(pwd)/obj/fiasco/arm64-sbsa" >> $odir/.imagebuilds
      echo "ENTRY=hello-2         TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=sbsa PT=arm_sbsa PATH_FIASCO=$(pwd)/obj/fiasco/arm64-sbsa" >> $odir/.imagebuilds
      echo "ENTRY=hello-shared    TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=sbsa PT=arm_sbsa PATH_FIASCO=$(pwd)/obj/fiasco/arm64-sbsa" >> $odir/.imagebuilds
      echo "ENTRY=ipcbench        TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=sbsa PT=arm_sbsa PATH_FIASCO=$(pwd)/obj/fiasco/arm64-sbsa" >> $odir/.imagebuilds
      echo "ENTRY=vm-basic        TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=sbsa PT=arm_sbsa PATH_FIASCO=$(pwd)/obj/fiasco/arm64-sbsa" >> $odir/.imagebuilds
      echo "ENTRY=vm-multi        TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=sbsa PT=arm_sbsa PATH_FIASCO=$(pwd)/obj/fiasco/arm64-sbsa" >> $odir/.imagebuilds
      echo "ENTRY=vm-multi-p2p    TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=sbsa PT=arm_sbsa PATH_FIASCO=$(pwd)/obj/fiasco/arm64-sbsa" >> $odir/.imagebuilds
    fi

    if [ "$CONF_DO_ARM64_S32G" ]; then
      echo "ENTRY=hello           TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=s32g PT=s32g PATH_FIASCO=$(pwd)/obj/fiasco/arm64-s32g" >> $odir/.imagebuilds
      echo "ENTRY=hello-cfg       TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=s32g PT=s32g PATH_FIASCO=$(pwd)/obj/fiasco/arm64-s32g" >> $odir/.imagebuilds
      echo "ENTRY=hello-2         TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=s32g PT=s32g PATH_FIASCO=$(pwd)/obj/fiasco/arm64-s32g" >> $odir/.imagebuilds
      echo "ENTRY=hello-shared    TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=s32g PT=s32g PATH_FIASCO=$(pwd)/obj/fiasco/arm64-s32g" >> $odir/.imagebuilds
      echo "ENTRY=ipcbench        TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=s32g-el1 PT=s32g PATH_FIASCO=$(pwd)/obj/fiasco/arm64-s32g-el1-perf" >> $odir/.imagebuilds
      echo "ENTRY=ipcbench        TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=s32g-el2 PT=s32g PATH_FIASCO=$(pwd)/obj/fiasco/arm64-s32g-el2-perf" >> $odir/.imagebuilds
      echo "ENTRY=vm-basic        TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=s32g PT=s32g PATH_FIASCO=$(pwd)/obj/fiasco/arm64-s32g" >> $odir/.imagebuilds
      echo "ENTRY=vm-multi        TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=s32g PT=s32g PATH_FIASCO=$(pwd)/obj/fiasco/arm64-s32g" >> $odir/.imagebuilds
      echo "ENTRY=vm-multi-p2p    TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=s32g PT=s32g PATH_FIASCO=$(pwd)/obj/fiasco/arm64-s32g" >> $odir/.imagebuilds
    fi

    if [ "$CONF_DO_ARM64_ZYNQMP" ]; then
      cat<<EOF >> $Mboot
QEMU_OPTIONS-zynqmp   += -M xlnx-zcu102,virtualization=true -m 2048
EOF
      echo "ENTRY=hello           TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=zynqmp PT=zynqmp PATH_FIASCO=$(pwd)/obj/fiasco/arm64-zynqmp" >> $odir/.imagebuilds
      echo "ENTRY=hello-cfg       TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=zynqmp PT=zynqmp PATH_FIASCO=$(pwd)/obj/fiasco/arm64-zynqmp" >> $odir/.imagebuilds
      echo "ENTRY=hello-2         TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=zynqmp PT=zynqmp PATH_FIASCO=$(pwd)/obj/fiasco/arm64-zynqmp" >> $odir/.imagebuilds
      echo "ENTRY=hello-shared    TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=zynqmp PT=zynqmp PATH_FIASCO=$(pwd)/obj/fiasco/arm64-zynqmp" >> $odir/.imagebuilds
      echo "ENTRY=vm-basic        TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=zynqmp PT=zynqmp PATH_FIASCO=$(pwd)/obj/fiasco/arm64-zynqmp" >> $odir/.imagebuilds
      echo "ENTRY=vm-multi        TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=zynqmp PT=zynqmp PATH_FIASCO=$(pwd)/obj/fiasco/arm64-zynqmp" >> $odir/.imagebuilds
      echo "ENTRY=vm-multi-p2p    TARGET_IMAGE_FILENAME_PLATFORM_TYPE_INFIX=zynqmp PT=zynqmp PATH_FIASCO=$(pwd)/obj/fiasco/arm64-zynqmp" >> $odir/.imagebuilds
    fi

    add_std_qemu_options $Mboot
    add_nonx86_qemu_options $Mboot

  fi # ARM64





  if [ "$CONF_DO_MIPS32R2" ]; then
    mkdir -p obj/l4/mips32r2/conf
    cat<<EOF >> obj/l4/mips32r2/conf/Makeconf.boot
#MODULE_SEARCH_PATH=$(pwd)/obj/fiasco/mips32-baikal-mp:$common_paths
MODULE_SEARCH_PATH=$(pwd)/obj/fiasco/mips32-malta:$common_paths
QEMU_OPTIONS += -M malta
EOF
    add_std_qemu_options obj/l4/mips32r2/conf/Makeconf.boot
    add_nonx86_qemu_options obj/l4/mips32r2/conf/Makeconf.boot
  fi

  if [ "$CONF_DO_MIPS32R6" ]; then
    mkdir -p obj/l4/mips32r6/conf
    cat<<EOF >> obj/l4/mips32r6/conf/Makeconf.boot
MODULE_SEARCH_PATH=$(pwd)/obj/fiasco/mips32-...:$common_paths
QEMU_OPTIONS += -M malta
EOF
    add_std_qemu_options obj/l4/mips32r6/conf/Makeconf.boot
    add_nonx86_qemu_options obj/l4/mips32r2/conf/Makeconf.boot
  fi

  if [ "$CONF_DO_MIPS64R2" ]; then
    mkdir -p obj/l4/mips64r2/conf
    cat<<EOF >> obj/l4/mips64r2/conf/Makeconf.boot
MODULE_SEARCH_PATH=$(pwd)/obj/fiasco/mips-malta-64r2-mp:$common_paths
QEMU_OPTIONS += -M malta
EOF
    add_std_qemu_options obj/l4/mips64r2/conf/Makeconf.boot
    add_nonx86_qemu_options obj/l4/mips64r2/conf/Makeconf.boot
  fi

  if [ "$CONF_DO_MIPS64R6" ]; then
    mkdir -p obj/l4/mips64r6/conf
    cat<<EOF >> obj/l4/mips64r6/conf/Makeconf.boot
MODULE_SEARCH_PATH=$(pwd)/obj/fiasco/mips-boston-64r6-mp:$common_paths
QEMU_OPTIONS    += -M boston
QEMU_KERNEL_TYPE = itb
EOF
    add_std_qemu_options obj/l4/mips64r6/conf/Makeconf.boot
    add_nonx86_qemu_options obj/l4/mips64r6/conf/Makeconf.boot
  fi
}

link_files()
{
  mkdir -p files/cfg
  (cd files/cfg && ln -sf ../../src/l4/pkg/io/io/config/x86-legacy.devs)
}


case "$1" in
  config)
     do_config
     ;;
  setup)
     load_config
     check_tools
     link_files
     redo_config
     do_setup
     ;;
  *)
     echo "Call $0 [config|setup]"
     exit 1
     ;;
esac

exit 0
