Use stretch-backports instead of jessie-backports for stable
[grml-live.git] / grml-live
index 3964cbd..f561355 100755 (executable)
--- a/grml-live
+++ b/grml-live
@@ -64,12 +64,15 @@ Usage: $PN [options, see as follows]
    -q                      skip mksquashfs
    -Q                      skip netboot package build
    -r <release_name>       release name
-   -s <suite>              Debian suite; values: etch, lenny, squeeze, sid
+   -s <suite>              Debian suite/release, like: stable, testing, unstable
+   -S <script_directory>   place of scripts (defaults to /usr/share/grml-live/scripts)
    -t <template_directory> place of the templates
    -u                      update existing chroot instead of rebuilding it from scratch
    -U <username>           arrange output to be owned by specified username
    -v <version_number>     specify version number of the release
    -V                      increase verbosity in the build process
+   -w <date>               wayback machine, build system using Debian archives
+                           from specified date
    -z                      use ZLIB instead of LZMA/XZ compression
 
 Usage examples:
@@ -77,7 +80,7 @@ Usage examples:
     $PN
     $PN -c GRMLBASE,GRML_FULL,AMD64 -o /dev/shm/grml
     $PN -c GRMLBASE,GRML_FULL,AMD64 -i grml_0.0-1.iso -v 0.0-1
-    $PN -c GRMLBASE,GRML_FULL,AMD64 -s sid -V -r 'grml-live rocks'
+    $PN -c GRMLBASE,GRML_FULL,AMD64 -s stable -V -r 'grml-ftw'
 
 More details: man grml-live + /usr/share/doc/grml-live/grml-live.html
               http://grml.org/grml-live/
@@ -146,8 +149,14 @@ else
 fi
 
 # source main configuration file:
-LIVE_CONF=/etc/grml/grml-live.conf
-. $LIVE_CONF
+[ -z "$LIVE_CONF" ] && LIVE_CONF='/etc/grml/grml-live.conf'
+if ! [ -r "$LIVE_CONF" ] ; then
+  ewarn "Configuration file $LIVE_CONF can not be read, ignoring"
+else
+  einfo "Sourcing configuration file $LIVE_CONF"
+  . $LIVE_CONF
+  eend $?
+fi
 # }}}
 
 # umount all directories {{{
@@ -270,12 +279,12 @@ extend_string_end() {
 # This is because:
 #   * We assume that the chroot always has a "good" version of
 #     the file. Also it makes sources handling easier.
-#   * On unstable, we Recommend the Debian packages containing
+#   * On unstable, we recommend the Debian packages containing
 #     these files. The user can override them by putting his
 #     "better" version into the chroot.
-#   * On stable, the Debian packages are probably not available,
-#     or outdated, so we look in TEMPLATE_DIRECTORY/compat first, where
-#     our grml-live-compat package installs current file versions.
+#   * With older releases the Debian packages are probably
+#     not available, so we look in TEMPLATE_DIRECTORY/compat,
+#     where a (custom) package might install current file versions.
 copy_addon_file() {
   DEST="${BUILD_OUTPUT}/boot/$3"
   if [ ! -d "${DEST}/" ]; then
@@ -287,7 +296,7 @@ copy_addon_file() {
     return $?
   fi
   if [ -e "${TEMPLATE_DIRECTORY}/compat/$3/$1" ]; then
-    log   "Copying $1 from grml-live-compat"
+    log   "Copying $1 from ${TEMPLATE_DIRECTORY}/compat"
     cp "${TEMPLATE_DIRECTORY}/compat/$3/$1" "${DEST}/"
     return $?
   fi
@@ -301,10 +310,41 @@ copy_addon_file() {
   ewarn "$msg" ; eend 1
   log "copy_addon_file: $msg"
 }
+
+# replace placeholders in template files with actual information
+adjust_boot_files() {
+  if [ -z "$1" ] ; then
+    echo "Usage: adjust_boot_files <template_file>" >&2
+    exit 1
+  fi
+
+  for file in "$@" ; do
+    if [ -r "${file}" ] && [ -f "${file}" ] ; then
+      sed -i "s/%ARCH%/$ARCH/g"                    "${file}"
+      sed -i "s/%DATE%/$DATE/g"                    "${file}"
+      sed -i "s/%DISTRI_INFO%/$DISTRI_INFO/g"      "${file}"
+      sed -i "s/%DISTRI_NAME%/$DISTRI_NAME/g"      "${file}"
+      sed -i "s/%DISTRI_SPLASH%/$DISTRI_SPLASH/g"  "${file}"
+      sed -i "s/%GRML_NAME%/$GRML_NAME/g"          "${file}"
+      sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/g"  "${file}"
+      sed -i "s/%RELEASE_INFO%/$RELEASE_INFO/g"    "${file}"
+      sed -i "s/%SHORT_NAME%/$SHORT_NAME/g"        "${file}"
+      sed -i "s/%VERSION%/$VERSION/g"              "${file}"
+
+      [ -n "$DEFAULT_BOOTOPTIONS" ] && sed -i "s; boot=live; boot=live $DEFAULT_BOOTOPTIONS;"  "${file}"
+
+      if [ -n "$NO_BOOTID" ] ; then
+        sed -i "s/ bootid=%BOOTID%//g" "${file}" # drop bootid bootoption
+      else
+        sed -i "s/%BOOTID%/$BOOTID/g" "${file}" # adjust bootid=... argument
+      fi
+    fi
+  done
+}
 # }}}
 
 # command line parsing {{{
-while getopts "a:C:c:d:D:e:g:i:I:o:r:s:t:U:v:AbBFhnNqQuVz" opt; do
+while getopts "a:C:c:d:D:e:g:i:I:o:r:s:S:t:U:v:w:AbBFhnNqQuVz" opt; do
   case "$opt" in
     a) ARCH="$OPTARG" ;;
     A) CLEAN_ARTIFACTS=1 ;;
@@ -326,17 +366,24 @@ while getopts "a:C:c:d:D:e:g:i:I:o:r:s:t:U:v:AbBFhnNqQuVz" opt; do
     Q) SKIP_NETBOOT=1 ;;
     r) RELEASENAME="$OPTARG" ;;
     s) SUITE="$OPTARG" ;;
+    S) SCRIPTS_DIRECTORY="$OPTARG";;
     t) TEMPLATE_DIRECTORY="$OPTARG";;
     v) VERSION="$OPTARG" ;;
     F) FORCE=1 ;;
     u) UPDATE=1 ;;
     U) CHOWN_USER="$OPTARG" ;;
     V) VERBOSE="-v" ;;
+    w) export WAYBACK_DATE="$OPTARG" ;;
     z) SQUASHFS_ZLIB=1 ;;
     ?) echo "invalid option -$OPTARG" >&2; usage; bailout 1 ;;
   esac
 done
 shift $(($OPTIND - 1))  # set ARGV to the first not parsed commandline parameter
+
+if [ -n "$1" ] ; then
+  echo "Error: unknown argument '$1' in options. Exiting to avoid possible data loss." >&2
+  bailout 1
+fi
 # }}}
 
 # read local (non-packaged) configuration {{{
@@ -378,14 +425,16 @@ fi
 [ -n "$HOSTNAME" ]                || HOSTNAME='grml'
 [ -n "$HYBRID_METHOD" ]           || HYBRID_METHOD='isohybrid'
 [ -n "$RELEASENAME" ]             || RELEASENAME='grml-live rocks'
+[ -n "$SECURE_BOOT" ]             || SECURE_BOOT='ubuntu'
 [ -n "$SQUASHFS_EXCLUDES_FILE" ]  || SQUASHFS_EXCLUDES_FILE="${GRML_FAI_CONFIG}/config/grml/squashfs-excludes"
 [ -n "$SUITE" ]                   || SUITE='testing'
 [ -n "$TEMPLATE_DIRECTORY" ]      || TEMPLATE_DIRECTORY='/usr/share/grml-live/templates'
+[ -n "$SCRIPTS_DIRECTORY" ]       || SCRIPTS_DIRECTORY='/usr/share/grml-live/scripts'
 [ -n "$USERNAME" ]                || USERNAME='grml'
 [ -n "$VERSION" ]                 || VERSION='0.0.1'
 
 # output specific stuff, depends on $OUTPUT (iff not set):
-[ -n "$OUTPUT" ]           || OUTPUT='/grml/grml-live'
+[ -n "$OUTPUT" ]           || OUTPUT="$PWD/grml/"
 [ -n "$BUILD_OUTPUT" ]     || BUILD_OUTPUT="$OUTPUT/grml_cd"
 [ -n "$CHROOT_OUTPUT" ]    || CHROOT_OUTPUT="$OUTPUT/grml_chroot"
 [ -n "$ISO_OUTPUT" ]       || ISO_OUTPUT="$OUTPUT/grml_isos"
@@ -617,11 +666,15 @@ fi
 
 # generate nfsroot configuration for FAI on the fly
 if [ -z "$FAI_DEBOOTSTRAP" ] ; then
-  FAI_DEBOOTSTRAP="$SUITE http://cdn.debian.net/debian"
+  if [ -n "$WAYBACK_DATE" ] ; then
+    FAI_DEBOOTSTRAP="$SUITE http://snapshot.debian.org/archive/debian/$WAYBACK_DATE/"
+  else
+    FAI_DEBOOTSTRAP="$SUITE http://ftp.debian.org/debian"
+  fi
 fi
 
 if [ -z "$FAI_DEBOOTSTRAP_OPTS" ] ; then
-  FAI_DEBOOTSTRAP_OPTS="--exclude=info,tasksel,tasksel-data --arch $ARCH"
+  FAI_DEBOOTSTRAP_OPTS="--exclude=info,tasksel,tasksel-data --include=aptitude --arch $ARCH"
 fi
 
 # create backup of old (not yet automatically generated) config file
@@ -679,12 +732,18 @@ else
       mount --bind "${OUTPUT}/grml_sources/" "${CHROOT_OUTPUT}/grml-live/sources/"
 
       log "Executed FAI command line:"
-      log "BUILD_ONLY=$BUILD_ONLY BOOTSTRAP_ONLY=$BOOTSTRAP_ONLY GRML_LIVE_CONFIG=$CONFIGDUMP fai $VERBOSE -C $GRML_FAI_CONFIG -s file:///$GRML_FAI_CONFIG/config -c$CLASSES -u $HOSTNAME $FAI_ACTION $CHROOT_OUTPUT $FAI_ARGS"
+      log "BUILD_ONLY=$BUILD_ONLY BOOTSTRAP_ONLY=$BOOTSTRAP_ONLY GRML_LIVE_CONFIG=$CONFIGDUMP WAYBACK_DATE=$WAYBACK_DATE fai $VERBOSE -C $GRML_FAI_CONFIG -s file:///$GRML_FAI_CONFIG/config -c$CLASSES -u $HOSTNAME $FAI_ACTION $CHROOT_OUTPUT $FAI_ARGS"
       BUILD_ONLY="$BUILD_ONLY" BOOTSTRAP_ONLY="$BOOTSTRAP_ONLY" GRML_LIVE_CONFIG="$CONFIGDUMP" fai $VERBOSE \
                   -C "$GRML_FAI_CONFIG" -s "file:///$GRML_FAI_CONFIG/config" -c"$CLASSES" \
                   -u "$HOSTNAME" "$FAI_ACTION" "$CHROOT_OUTPUT" $FAI_ARGS | tee -a $LOGFILE
       RC="$PIPESTATUS" # notice: bash-only
 
+      if [ "$RC" != 0 ] ; then
+         log    "Error: critical error while executing fai [exit code ${RC}]. Exiting."
+         eerror "Error: critical error while executing fai [exit code ${RC}]. Exiting." ; eend 1
+         bailout 1
+      fi
+
       # provide inform fai about the ISO we build, needs to be provided
       # *after* FAI stage, otherwise FAI skips the debootstrap stage if
       # there is not BASEFILE (as it checks for presence of /etc) :(
@@ -694,12 +753,6 @@ else
 
       FORCE_ISO_REBUILD=true
 
-      if [ "$RC" != 0 ] ; then
-         log    "Error: critical error while executing fai [exit code ${RC}]. Exiting."
-         eerror "Error: critical error while executing fai [exit code ${RC}]. Exiting." ; eend 1
-         bailout 1
-      fi
-
       # move fai logs into grml_logs directory
       mkdir -p "$LOG_OUTPUT"/fai/
       cp -r "$CHROOT_OUTPUT"/var/log/fai/"$HOSTNAME"/last/* "$LOG_OUTPUT"/fai/
@@ -732,6 +785,11 @@ else
          grep 'FAILED with exit code' $CHECKLOG/shell.log >> $LOGFILE && ERROR=6
       fi
 
+      if [ -r "$CHECKLOG/fai.log" ] ; then
+        grep 'updatebase.*FAILED with exit code' "$CHECKLOG/fai.log" >> "$LOGFILE" && ERROR=7
+        grep 'instsoft.*FAILED with exit code'   "$CHECKLOG/fai.log" >> "$LOGFILE" && ERROR=8
+      fi
+
       if [ -n "$ERROR" ] ; then
          log    "Error: there was a critical error [${ERROR}] during execution of stage 'fai dirinstall' [$(date)]"
          eerror "Error: there was a critical error during execution of stage 'fai dirinstall'"
@@ -790,7 +848,7 @@ else
 <testsuite name="grml-live-missing-packages" tests="${package_count}" time="1" failures="${package_errors}" errors="${package_errors}" skipped="0" assertions="0">
 EOF
 
-  for package in $(awk '{print $1}' "${CHECKLOG}/package_errors.log") ; do
+  for package in $(awk '{print $1}' "${CHECKLOG}/package_errors.log" | sed 's;/;\\/;') ; do
     failure_reason="$(awk "/$package/ {print \$2}" "${CHECKLOG}/package_errors.log")"
     cat >> "${REPORT_MISSING_PACKAGES}" << EOF
   <testcase name="test_missing_packages_${package}" time="0" assertions="0">
@@ -824,6 +882,86 @@ EOF
 fi
 # }}}
 
+# grub boot {{{
+grub_setup() {
+  BOOTX64="/boot/bootx64.efi"
+  BOOTX32="/boot/bootia32.efi"
+  EFI_IMG="/boot/efi.img"
+
+  if [[ "$ARCH" == "amd64" ]] ; then
+    # important: this depends on execution of ${GRML_FAI_CONFIG}/config/scripts/GRMLBASE/45-grub-images
+    if ! [ -r "${CHROOT_OUTPUT}/${BOOTX64}" ] ; then
+      log    "Can not access GRUB efi image ${CHROOT_OUTPUT}/${BOOTX64}, required for Secure Boot support"
+      eerror "Can not access GRUB efi image ${CHROOT_OUTPUT}/${BOOTX64}, required for Secure Boot support" ; eend 1
+      log    "Possible reason is failure to run ${GRML_FAI_CONFIG}/config/scripts/GRMLBASE/45-grub-images"
+      ewarn  "Possible reason is failure to run ${GRML_FAI_CONFIG}/config/scripts/GRMLBASE/45-grub-images"
+      bailout 50
+    fi
+
+    dd if=/dev/zero of="${CHROOT_OUTPUT}/${EFI_IMG}" bs=4M count=1 2>/dev/null || bailout 50
+    mkfs.vfat -n GRML "${CHROOT_OUTPUT}/${EFI_IMG}" >/dev/null || bailout 51
+    mmd -i "${CHROOT_OUTPUT}/${EFI_IMG}" ::EFI || bailout 52
+    mmd -i "${CHROOT_OUTPUT}/${EFI_IMG}" ::EFI/BOOT || bailout 52
+
+    if [ "${SECURE_BOOT:-}" = "disable" ] ; then
+      log   "Secure Boot is disabled."
+      einfo "Secure Boot is disabled." ; eend 0
+
+      # install "$BOOTX64" as ::EFI/BOOT/bootx64.efi inside image file "$EFI_IMG":
+      mcopy -i "${CHROOT_OUTPUT}/${EFI_IMG}" "${CHROOT_OUTPUT}/${BOOTX64}" ::EFI/BOOT/bootx64.efi >/dev/null || bailout 53
+
+      log   "Generated 64-bit EFI image $BOOTX64"
+      einfo "Generated 64-bit EFI image $BOOTX64" ; eend 0
+    else
+      log   "Secure Boot is enabled [mode: $SECURE_BOOT]"
+      einfo "Secure Boot is enabled [mode: $SECURE_BOOT]" ; eend 0
+
+      if [ "${SECURE_BOOT}" = "ubuntu" ] ; then
+        local GRUBCFG_TEMPLATE="${TEMPLATE_DIRECTORY}/secureboot/grub.cfg"
+        local GRUBCFG_TMP=$(mktemp)
+
+        if ! [ -r "${GRUBCFG_TEMPLATE}" ] ; then
+          log    "Secure Boot template for GRUB [${GRUBCFG_TEMPLATE}] not found."
+          eerror "Secure Boot template for GRUB [${GRUBCFG_TEMPLATE}] not found." ; eend 1
+          bailout 54
+        fi
+
+        cp "${GRUBCFG_TEMPLATE}" "${GRUBCFG_TMP}"
+        adjust_boot_files "${GRUBCFG_TMP}"
+
+        mmd -i "${CHROOT_OUTPUT}/${EFI_IMG}" ::EFI/ubuntu || bailout 55
+        mcopy -i "${CHROOT_OUTPUT}/${EFI_IMG}" "${GRUBCFG_TMP}" ::EFI/ubuntu/grub.cfg || bailout 56
+        rm "${GRUBCFG_TMP}"
+
+        mcopy -i "${CHROOT_OUTPUT}/${EFI_IMG}" "${TEMPLATE_DIRECTORY}"/EFI/BOOT/grubx64.efi.signed ::EFI/BOOT/grubx64.efi >/dev/null || bailout 57
+        mcopy -i "${CHROOT_OUTPUT}/${EFI_IMG}" "${TEMPLATE_DIRECTORY}"/EFI/BOOT/shimx64.efi.signed ::EFI/BOOT/bootx64.efi >/dev/null || bailout 58
+
+        log   "Generated 64-bit Secure Boot (ubuntu) EFI image ${CHROOT_OUTPUT}/${EFI_IMG}"
+        einfo "Generated 64-bit Secure Boot (ubuntu) EFI image ${CHROOT_OUTPUT}/${EFI_IMG}" ; eend 0
+      fi
+    fi
+  fi
+
+  if [[ "$ARCH" == "i386" ]] ; then
+    if ! [ -r "${CHROOT_OUTPUT}/${BOOTX32}" ] ; then
+      log    "Can not access GRUB efi image ${CHROOT_OUTPUT}/${BOOTX32}."
+      eerror "Can not access GRUB efi image ${CHROOT_OUTPUT}/${BOOTX32}." ; eend 1
+      log    "Possible reason is failure to run ${GRML_FAI_CONFIG}/config/scripts/GRMLBASE/45-grub-images"
+      ewarn "Possible reason is failure to run ${GRML_FAI_CONFIG}/config/scripts/GRMLBASE/45-grub-images"
+      bailout 50
+    fi
+
+    dd if=/dev/zero of="${CHROOT_OUTPUT}/${EFI_IMG}" bs=4M count=1 2>/dev/null || bailout 50
+    mkfs.vfat -n GRML "${CHROOT_OUTPUT}/${EFI_IMG}" >/dev/null || bailout 51
+    mmd -i "${CHROOT_OUTPUT}/${EFI_IMG}" ::EFI || bailout 52
+    mmd -i "${CHROOT_OUTPUT}/${EFI_IMG}" ::EFI/BOOT || bailout 52
+    mcopy -i "${CHROOT_OUTPUT}/${EFI_IMG}" "${CHROOT_OUTPUT}/${BOOTX32}" ::EFI/BOOT/bootia32.efi >/dev/null || bailout 53
+    log   "Generated 32-bit EFI image $BOOTX32"
+    einfo "Generated 32-bit EFI image $BOOTX32" ; eend 0
+  fi
+}
+# }}}
+
 # BUILD_OUTPUT - execute arch specific stuff and squashfs {{{
 [ -n "$BUILD_OUTPUT" ] || BUILD_OUTPUT="$OUTPUT/grml_cd"
 mkdir -p "$BUILD_OUTPUT" || bailout 6 "Problem with creating $BUILD_OUTPUT for stage ARCH"
@@ -831,296 +969,315 @@ mkdir -p "$BUILD_OUTPUT" || bailout 6 "Problem with creating $BUILD_OUTPUT for s
 # prepare ISO
 if [ "$ARCH" = i386 ] || [ "$ARCH" = amd64 ] ; then
   if [ -n "$BOOTSTRAP_ONLY" ] ; then
-     log   "Skipping stage 'boot' as building with bootstrap only."
-     ewarn "Skipping stage 'boot' as building with bootstrap only." ; eend 0
+    log   "Skipping stage 'boot' as building with bootstrap only."
+    ewarn "Skipping stage 'boot' as building with bootstrap only." ; eend 0
   else
-    if [ -d "$BUILD_OUTPUT"/boot/isolinux -a -z "$UPDATE" -a -z "$BUILD_ONLY" ] ; then
-       log   "Skipping stage 'boot' as $BUILD_OUTPUT/boot/isolinux exists already."
-       ewarn "Skipping stage 'boot' as $BUILD_OUTPUT/boot/isolinux exists already." ; eend 0
+    # booting stuff:
+    mkdir -p "$BUILD_OUTPUT"/boot/isolinux
+    mkdir -p "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"
+
+    # if we don't have an initrd we a) can't boot and b) there was an error
+    # during build, so check for the file:
+    INITRD="$(ls $CHROOT_OUTPUT/boot/initrd* 2>/dev/null| grep -v '.bak$' | sort -r | head -1)"
+    if [ -n "$INITRD" ] ; then
+      cp $INITRD "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"/initrd.img
+      find $CHROOT_OUTPUT/boot/ -name initrd\*.bak -exec rm {} \;
     else
-       # booting stuff:
-       [ -d "$BUILD_OUTPUT"/boot/isolinux ] || mkdir -p "$BUILD_OUTPUT"/boot/isolinux
-       [ -d "$BUILD_OUTPUT"/boot/"${SHORT_NAME}" ] || mkdir -p "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"
-
-       # if we don't have an initrd we a) can't boot and b) there was an error
-       # during build, so check for the file:
-       INITRD="$(ls $CHROOT_OUTPUT/boot/initrd* 2>/dev/null| grep -v '.bak$' | sort -r | head -1)"
-       if [ -n "$INITRD" ] ; then
-          cp $INITRD "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"/initrd.img
-          find $CHROOT_OUTPUT/boot/ -name initrd\*.bak -exec rm {} \;
-       else
-          log    "Error: No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting"
-          eerror "Error: No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1
-          bailout 10
-       fi
-
-       KERNEL_IMAGE="$(ls $CHROOT_OUTPUT/boot/vmlinuz* 2>/dev/null | sort -r | head -1)"
-       if [ -n "$KERNEL_IMAGE" ] ; then
-          cp "$KERNEL_IMAGE" "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"/vmlinuz
-       else
-          log    "Error: No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting"
-          eerror "Error: No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1
-          bailout 11
-       fi
+      log    "Error: No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting"
+      eerror "Error: No initrd found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1
+      bailout 10
+    fi
 
-       # EFI boot files
-       if [ -r "${CHROOT_OUTPUT}/boot/efi.img" -a -r "${CHROOT_OUTPUT}/boot/bootx64.efi" ] ; then
-          einfo "Moving EFI boot files into ISO path."
-          log "Moving EFI boot files into ISO path."
-          RC=$0
-          mv "${CHROOT_OUTPUT}/boot/efi.img" "${BUILD_OUTPUT}/boot/" || RC=$?
-          mkdir -p "${BUILD_OUTPUT}/efi/boot/" || RC=$?
-          mv "${CHROOT_OUTPUT}/boot/bootx64.efi" "${BUILD_OUTPUT}/efi/boot/bootx64.efi" || RC=$?
-          eend $?
-       fi
+    KERNEL_IMAGE="$(ls $CHROOT_OUTPUT/boot/vmlinuz* 2>/dev/null | sort -r | head -1)"
+    if [ -n "$KERNEL_IMAGE" ] ; then
+      cp "$KERNEL_IMAGE" "$BUILD_OUTPUT"/boot/"${SHORT_NAME}"/vmlinuz
+    else
+      log    "Error: No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting"
+      eerror "Error: No kernel found inside $CHROOT_OUTPUT/boot/ - Exiting" ; eend 1
+      bailout 11
+    fi
 
-       [ -n "$TEMPLATE_DIRECTORY" ] || TEMPLATE_DIRECTORY='/usr/share/grml-live/templates'
-       if ! [ -d "${TEMPLATE_DIRECTORY}"/boot ] ; then
-          log    "Error: ${TEMPLATE_DIRECTORY}/boot does not exist. Exiting."
-          eerror "Error: ${TEMPLATE_DIRECTORY}/boot does not exist. Exiting." ; eend 1
-          bailout 8
-       fi
+    # we need to set "$BOOTID" before we invoke adjust_boot_files for the
+    # first time, being inside grub_setup below
+    if [ -n "$NO_BOOTID" ] ; then
+      log   'Skipping bootid feature as requested via $NO_BOOTID.'
+      einfo 'Skipping bootid feature as requested via $NO_BOOTID.'
+    else
+      [ -n "$BOOTID" ] || BOOTID="$(echo ${GRML_NAME}${VERSION} | tr -d ',./;\- ')"
+      mkdir -p "$BUILD_OUTPUT"/conf
+      einfo "Generating /conf/bootid.txt with entry ${BOOTID}."
+      log   "Generating /conf/bootid.txt with entry ${BOOTID}."
+      echo "$BOOTID" > "$BUILD_OUTPUT"/conf/bootid.txt
+      eend $?
+    fi
 
-       # copy _required_ isolinux files
-       for file in ifcpu64.c32 isolinux.bin vesamenu.c32; do
-         copy_addon_file "${file}" /usr/lib/syslinux isolinux
-       done
+    grub_setup
+
+    # EFI boot files
+    if [ -r "${CHROOT_OUTPUT}/boot/efi.img" -a -r "${CHROOT_OUTPUT}/boot/bootx64.efi" ] ; then
+      einfo "Copying 64-bit EFI boot files into ISO path."
+      log   "Copying 64-bit EFI boot files into ISO path."
+      RC=$0
+      cp "${CHROOT_OUTPUT}/boot/efi.img" "${BUILD_OUTPUT}/boot/" || RC=$?
+      mkdir -p "${BUILD_OUTPUT}/EFI/BOOT/" || RC=$?
+      cp "${CHROOT_OUTPUT}/boot/bootx64.efi" "${BUILD_OUTPUT}/EFI/BOOT/bootx64.efi" || RC=$?
+      eend $?
+    elif [ -r "${CHROOT_OUTPUT}/boot/efi.img" -a -r "${CHROOT_OUTPUT}/boot/bootia32.efi" ] ; then
+      einfo "Copying 32-bit EFI boot files into ISO path."
+      log "Copying 32-bit EFI boot files into ISO path."
+      RC=$0
+      cp "${CHROOT_OUTPUT}/boot/efi.img" "${BUILD_OUTPUT}/boot/" || RC=$?
+      mkdir -p "${BUILD_OUTPUT}/EFI/BOOT/" || RC=$?
+      cp "${CHROOT_OUTPUT}/boot/bootia32.efi" "${BUILD_OUTPUT}/EFI/BOOT/bootia32.efi" || RC=$?
+      eend $?
+    else
+      ewarn "No EFI boot files found, skipping." ; eend 0
+    fi
 
-       # *always* copy files to output directory so the variables
-       # get adjusted according to the build.
-       cp ${TEMPLATE_DIRECTORY}/boot/isolinux/*  "$BUILD_OUTPUT"/boot/isolinux/
+    [ -n "$TEMPLATE_DIRECTORY" ] || TEMPLATE_DIRECTORY='/usr/share/grml-live/templates'
+    if ! [ -d "${TEMPLATE_DIRECTORY}"/boot ] ; then
+      log    "Error: ${TEMPLATE_DIRECTORY}/boot does not exist. Exiting."
+      eerror "Error: ${TEMPLATE_DIRECTORY}/boot does not exist. Exiting." ; eend 1
+      bailout 8
+    fi
 
-       if [ -n "$NO_ADDONS" ] ; then
-          log   "Skipping installation of boot addons as requested via \$NO_ADDONS."
-          einfo "Skipping installation of boot addons as requested via \$NO_ADDONS."; eend 0
-       else
-          if ! [ -d "$TEMPLATE_DIRECTORY"/boot/addons ] ; then
-            log   "Boot addons not found, skipping therefore. (Consider installing package grml-live-addons)"
-            ewarn "Boot addons not found, skipping therefore. (Consider installing package grml-live-addons)" ; eend 0
-          else
-            # copy addons from system packages or grml-live-compat
-            copy_addon_file ipxe.lkrn /usr/lib/ipxe addons
-            copy_addon_file pci.ids /usr/share/misc addons
-            copy_addon_file memtest86+.bin /boot addons
-            for file in memdisk chain.c32 hdt.c32 mboot.c32 menu.c32; do
-              copy_addon_file "${file}" /usr/lib/syslinux addons
-            done
-
-            # make memtest filename FAT16/8.3 compatible
-            mv "${BUILD_OUTPUT}/boot/addons/memtest86+.bin" \
-              "${BUILD_OUTPUT}/boot/addons/memtest"
-
-            # copy only files so we can handle bsd4grml on its own
-            for file in ${TEMPLATE_DIRECTORY}/boot/addons/* ; do
-              test -f $file && cp $file "$BUILD_OUTPUT"/boot/addons/
-            done
-
-            if [ -n "$NO_ADDONS_BSD4GRML" ] ; then
-               log   "Skipping installation of bsd4grml as requested via \$NO_ADDONS_BSD4GRML."
-               einfo "Skipping installation of bsd4grml as requested via \$NO_ADDONS_BSD4GRML."; eend 0
-            else
-               if [ -d "$TEMPLATE_DIRECTORY"/boot/addons/bsd4grml ] ; then
-                 cp -a ${TEMPLATE_DIRECTORY}/boot/addons/bsd4grml "$BUILD_OUTPUT"/boot/addons/
-               else
-                 log   "Missing addon file: bsd4grml"
-                 ewarn "Missing addon file: bsd4grml" ; eend 0
-               fi
-            fi
-
-          fi # no "$TEMPLATE_DIRECTORY"/boot/addons
-       fi # NO_ADDONS
-
-       if ! [ -d "${BUILD_OUTPUT}/boot/grub" ] ; then
-         mkdir -p "${BUILD_OUTPUT}/boot/grub"
-       fi
-       cp -a ${TEMPLATE_DIRECTORY}/boot/grub/* "$BUILD_OUTPUT"/boot/grub/
-
-       # generate loopback.cfg config file without depending on grub's regexp module
-       # which isn't available in Debian/squeeze
-       echo "## grub2 loopback configuration" > "${BUILD_OUTPUT}"/boot/grub/loopback.cfg
-       echo "source /boot/grub/header.cfg" >> "${BUILD_OUTPUT}"/boot/grub/loopback.cfg
-       for config in "${BUILD_OUTPUT}"/boot/grub/*_default.cfg "${BUILD_OUTPUT}"/boot/grub/*_options.cfg ; do
-         [ -r "$config" ] || continue
-         echo "source ${config##$BUILD_OUTPUT}" >> "${BUILD_OUTPUT}"/boot/grub/loopback.cfg
-       done
-       echo "source /boot/grub/addons.cfg" >> "${BUILD_OUTPUT}"/boot/grub/loopback.cfg
-       echo "source /boot/grub/footer.cfg" >> "${BUILD_OUTPUT}"/boot/grub/loopback.cfg
-
-       # copy grub files from target
-       cp -a "${CHROOT_OUTPUT}"/usr/lib/grub/*-pc/*.mod "${BUILD_OUTPUT}"/boot/grub/
-       cp -a "${CHROOT_OUTPUT}"/usr/lib/grub/*-pc/*.o "${BUILD_OUTPUT}"/boot/grub/
-       cp -a "${CHROOT_OUTPUT}"/usr/lib/grub/*-pc/*.lst "${BUILD_OUTPUT}"/boot/grub/
-       cp -a "${CHROOT_OUTPUT}"/usr/share/grub/ascii.pf2 "${BUILD_OUTPUT}"/boot/grub/
-       cp -a "${CHROOT_OUTPUT}"/boot/grub/core.img "${BUILD_OUTPUT}"/boot/grub/
-       cp -a "${CHROOT_OUTPUT}"/boot/grub/grub.img "${BUILD_OUTPUT}"/boot/grub/
-
-       if ! [ -d "${TEMPLATE_DIRECTORY}"/GRML ] ; then
-          log    "Error: ${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting."
-          eerror "Error: ${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting." ; eend 1
-          bailout 9
-       fi
+    # copy _required_ isolinux files
+    if [ -d "${CHROOT_OUTPUT}/usr/lib/ISOLINUX" ] ; then
+      copy_addon_file isolinux.bin /usr/lib/ISOLINUX isolinux
+      for file in ${CHROOT_OUTPUT}/usr/lib/syslinux/modules/bios/*.c32 ; do
+        copy_addon_file "$(basename "$file")"  /usr/lib/syslinux/modules/bios/ isolinux
+      done
+    else # syslinux versions <= 3:4.05+dfsg-6+deb8u1
+      copy_addon_file isolinux.bin /usr/lib/syslinux isolinux
+      copy_addon_file ifcpu64.c32  /usr/lib/syslinux isolinux
+      copy_addon_file vesamenu.c32 /usr/lib/syslinux isolinux
+    fi
 
-       mkdir -p "$BUILD_OUTPUT"/GRML/"${GRML_NAME}"/
-       cp -a ${TEMPLATE_DIRECTORY}/GRML/* "$BUILD_OUTPUT"/GRML/"${GRML_NAME}"/
+    # *always* copy files to output directory so the variables
+    # get adjusted according to the build.
+    cp ${TEMPLATE_DIRECTORY}/boot/isolinux/*  "$BUILD_OUTPUT"/boot/isolinux/
 
-       # adjust boot splash information:
-       RELEASE_INFO="$GRML_NAME $VERSION - Release Codename $RELEASENAME"
-       RELEASE_INFO="$(cut_string 68 "$RELEASE_INFO")"
-       RELEASE_INFO="$(extend_string_end 68 "$RELEASE_INFO")"
+    mkdir -p "${BUILD_OUTPUT}/boot/grub"
+    cp -a ${TEMPLATE_DIRECTORY}/boot/grub/* "$BUILD_OUTPUT"/boot/grub/
 
-       if [ -r "$BUILD_OUTPUT"/GRML/"${GRML_NAME}"/grml-version ] ; then
-          sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/GRML/"${GRML_NAME}"/grml-version
-          sed -i "s/%DATE%/$DATE/"                                      "$BUILD_OUTPUT"/GRML/"${GRML_NAME}"/grml-version
-       fi
+    if [ -n "$NO_ADDONS" ] ; then
+      rm -f "$BUILD_OUTPUT"/boot/grub/addons.cfg
+      log   "Skipping installation of boot addons as requested via \$NO_ADDONS."
+      einfo "Skipping installation of boot addons as requested via \$NO_ADDONS."; eend 0
+    else
+      if ! [ -d "$TEMPLATE_DIRECTORY"/boot/addons ] ; then
+        log   "Boot addons not found, skipping therefore. (Consider installing package grml-live-addons)"
+        ewarn "Boot addons not found, skipping therefore. (Consider installing package grml-live-addons)" ; eend 0
+      else
+        # copy addons from system packages or grml-live-addons
+        copy_addon_file ipxe.lkrn /usr/lib/ipxe addons
+        copy_addon_file pci.ids /usr/share/misc addons
+        copy_addon_file memtest86+.bin /boot addons
+
+        # since syslinux(-common) v3:6.03~pre1+dfsg-4 the files are in a
+        # different directory :(
+        if [ -d "${CHROOT_OUTPUT}/usr/lib/syslinux/modules/bios/" ] ; then
+          syslinux_modules_dir=/usr/lib/syslinux/modules/bios/
+        else
+          syslinux_modules_dir=/usr/lib/syslinux
+        fi
+        for file in chain.c32 hdt.c32 mboot.c32 menu.c32; do
+          copy_addon_file "${file}" "${syslinux_modules_dir}" addons
+        done
 
-       # make sure the squashfs filename is set accordingly:
-       SQUASHFS_NAME="$GRML_NAME.squashfs"
+        copy_addon_file memdisk /usr/lib/syslinux addons
 
-       if [ -n "$NO_BOOTID" ] ; then
-          log   'Skipping bootid feature as requested via $NO_BOOTID.'
-          einfo 'Skipping bootid feature as requested via $NO_BOOTID.'
-       else
-          [ -n "$BOOTID" ] || BOOTID="$(echo ${GRML_NAME}${VERSION} | tr -d ',./;\- ')"
-          [ -d "$BUILD_OUTPUT"/conf ] || mkdir "$BUILD_OUTPUT"/conf
-          einfo "Generating /conf/bootid.txt with entry ${BOOTID}."
-          log   "Generating /conf/bootid.txt with entry ${BOOTID}."
-          echo "$BOOTID" > "$BUILD_OUTPUT"/conf/bootid.txt
-          eend $?
-       fi
+        # make memtest filename FAT16/8.3 compatible
+        mv "${BUILD_OUTPUT}/boot/addons/memtest86+.bin" \
+          "${BUILD_OUTPUT}/boot/addons/memtest"
 
-       # adjust all variables in the templates with the according distribution information
-       for file in "${BUILD_OUTPUT}"/boot/isolinux/*.cfg "${BUILD_OUTPUT}"/boot/isolinux/*.msg \
-                   "${BUILD_OUTPUT}"/boot/grub/* ; do
-         if [ -r "${file}" ] && [ -f "${file}" ] ; then
-           sed -i "s/%ARCH%/$ARCH/g"                    "${file}"
-           sed -i "s/%DATE%/$DATE/g"                    "${file}"
-           sed -i "s/%DISTRI_INFO%/$DISTRI_INFO/g"      "${file}"
-           sed -i "s/%DISTRI_NAME%/$DISTRI_NAME/g"      "${file}"
-           sed -i "s/%DISTRI_SPLASH%/$DISTRI_SPLASH/g"  "${file}"
-           sed -i "s/%GRML_NAME%/$GRML_NAME/g"          "${file}"
-           sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/g"  "${file}"
-           sed -i "s/%RELEASE_INFO%/$RELEASE_INFO/g"    "${file}"
-           sed -i "s/%SHORT_NAME%/$SHORT_NAME/g"        "${file}"
-           sed -i "s/%VERSION%/$VERSION/g"              "${file}"
-
-           [ -n "$DEFAULT_BOOTOPTIONS" ] && sed -i "s; boot=live; boot=live $DEFAULT_BOOTOPTIONS;"  "${file}"
-
-           if [ -n "$NO_BOOTID" ] ; then
-              sed -i "s/ bootid=%BOOTID%//g" "${file}" # drop bootid bootoption
-           else
-              sed -i "s/%BOOTID%/$BOOTID/g" "${file}" # adjust bootid=... argument
-           fi
-         fi
-       done
-
-       for param in ARCH DATE DISTRI_INFO DISTRI_NAME DISTRI_SPLASH GRML_NAME SQUASHFS_NAME \
-           RELEASE_INFO SHORT_NAME VERSION ; do
-           for file in $(find "${BUILD_OUTPUT}" -name "*%$param%*") ; do
-               value="$(eval echo '$'"$param")"
-               mv ${file} ${file/\%${param}\%/$value}
-           done
-       done
-
-       # adjust bootsplash accordingly but make sure the string has the according lenght
-       SQUASHFS_NAME="$(cut_string 20 "$SQUASHFS_NAME")"
-       SQUASHFS_NAME="$(extend_string_end 20 "$SQUASHFS_NAME")"
-       for file in f4 f5 ; do
-          if [ -r "${BUILD_OUTPUT}/boot/isolinux/${file}" ] ; then
-             sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/" "${BUILD_OUTPUT}/boot/isolinux/${file}"
-             sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/" "${BUILD_OUTPUT}/boot/isolinux/${file}"
-          fi
-       done
-
-       # generate addon list
-       rm -f "${BUILD_OUTPUT}/${ADDONS_LIST_FILE}"
-       for name in "${BUILD_OUTPUT}"/boot/isolinux/addon_*.cfg ; do
-         include_name=$(basename "$name")
-         echo "include $include_name"  >> "${BUILD_OUTPUT}/${ADDONS_LIST_FILE}"
-       done
-
-       if ! [ -r "${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg" ] || [ "$DISTRI_NAME" = "grml" ] ; then
-          log "including grmlmain.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
-          echo "include grmlmain.cfg"    >  "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
-          echo "include default.cfg"     >  "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
-          echo "include menuoptions.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
-          echo "include grml.cfg"        >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
-
-          for f in "${BUILD_OUTPUT}"/boot/isolinux/submenu*.cfg ; do
-            echo "include $(basename $f)"     >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
-          done
-
-          echo "include options.cfg"     >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
-          if [ ! -n "$NO_ADDONS" ] ; then
-            echo "include addons.cfg"    >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
-          fi
-          echo "include isoprompt.cfg"   >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
-          echo "include hd.cfg"          >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
-          echo "include hidden.cfg"      >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
-       else # assume we are building a custom distribution:
-          log "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it."
-          einfo "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it."
-          if grep -q "^include ${DISTRI_NAME}.cfg" "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then
-            log "include for ${DISTRI_NAME}.cfg already present, nothing to do."
-            eindent
-            einfo "include for ${DISTRI_NAME}.cfg already present, nothing to do."
-            eoutdent
-            eend $?
-         else
-            log "including ${DISTRI_NAME}.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
-            echo "include ${DISTRI_NAME}.cfg" > "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
-            [ -n "$NO_ADDONS" ] || echo "include addons.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
-          fi
-       fi
+        # copy only files so we can handle bsd4grml on its own
+        for file in ${TEMPLATE_DIRECTORY}/boot/addons/* ; do
+          test -f $file && cp $file "$BUILD_OUTPUT"/boot/addons/
+        done
 
-       # use old style console based isolinux method only if requested:
-       if [[ "${ISOLINUX_METHOD}" == "console" ]] ; then
-          log 'Using console based isolinux method as requested via $ISOLINUX_METHOD.'
-          einfo 'Using console based isolinux method as requested via $ISOLINUX_METHOD.'
-          if grep -q '^include console.cfg' "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then
-            einfo "include for console.cfg already found, nothing to do."
-            eend 0
-          else
-            log "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
-            einfo "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
-            echo "include console.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
-            eend $?
-          fi
-       else
-          log 'Using graphical boot menu.'
-          if grep -q '^include vesamenu.cfg' "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg" ; then
-            log "include for vesamenu.cfg already found, nothing to do."
+        if [ -n "$NO_ADDONS_BSD4GRML" ] ; then
+          log   "Skipping installation of bsd4grml as requested via \$NO_ADDONS_BSD4GRML."
+          einfo "Skipping installation of bsd4grml as requested via \$NO_ADDONS_BSD4GRML."; eend 0
+        else
+          if [ -d "$TEMPLATE_DIRECTORY"/boot/addons/bsd4grml ] ; then
+            cp -a ${TEMPLATE_DIRECTORY}/boot/addons/bsd4grml "$BUILD_OUTPUT"/boot/addons/
           else
-            log "including vesamenu.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
-            echo "include vesamenu.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
+            log   "Missing addon file: bsd4grml"
+            ewarn "Missing addon file: bsd4grml" ; eend 0
           fi
-       fi
+        fi
 
-       if [ -e "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6 ]; then
-          sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6
-       fi
+      fi # no "$TEMPLATE_DIRECTORY"/boot/addons
+    fi # NO_ADDONS
+
+    # generate loopback.cfg config file without depending on grub's regexp module
+    # which isn't available in Debian/squeeze
+    echo "## grub2 loopback configuration" > "${BUILD_OUTPUT}"/boot/grub/loopback.cfg
+    echo "source /boot/grub/header.cfg" >> "${BUILD_OUTPUT}"/boot/grub/loopback.cfg
+    for config in "${BUILD_OUTPUT}"/boot/grub/*_default.cfg "${BUILD_OUTPUT}"/boot/grub/*_options.cfg ; do
+      [ -r "$config" ] || continue
+      echo "source ${config##$BUILD_OUTPUT}" >> "${BUILD_OUTPUT}"/boot/grub/loopback.cfg
+    done
+    if [ -z "$NO_ADDONS" ] ; then
+      echo "source /boot/grub/addons.cfg" >> "${BUILD_OUTPUT}"/boot/grub/loopback.cfg
+    fi
+    echo "source /boot/grub/footer.cfg" >> "${BUILD_OUTPUT}"/boot/grub/loopback.cfg
+
+    # copy grub files from target
+    mkdir -p "${BUILD_OUTPUT}"/boot/grub/i386-pc/
+    cp -a "${CHROOT_OUTPUT}"/usr/lib/grub/*-pc/*.mod "${BUILD_OUTPUT}"/boot/grub/i386-pc/
+    cp -a "${CHROOT_OUTPUT}"/usr/lib/grub/*-pc/*.o "${BUILD_OUTPUT}"/boot/grub/i386-pc/
+    cp -a "${CHROOT_OUTPUT}"/usr/lib/grub/*-pc/*.lst "${BUILD_OUTPUT}"/boot/grub/i386-pc/
+    cp -a "${CHROOT_OUTPUT}"/usr/share/grub/ascii.pf2 "${BUILD_OUTPUT}"/boot/grub/
+    cp -a "${CHROOT_OUTPUT}"/boot/grub/core.img "${BUILD_OUTPUT}"/boot/grub/
+    cp -a "${CHROOT_OUTPUT}"/boot/grub/grub.img "${BUILD_OUTPUT}"/boot/grub/
+
+    # copy modules for UEFI grub, 64-bit
+    mkdir -p "${BUILD_OUTPUT}"/boot/grub/x86_64-efi/
+    cp -a "${CHROOT_OUTPUT}"/usr/lib/grub/x86_64-efi/*.{mod,lst} "${BUILD_OUTPUT}"/boot/grub/x86_64-efi/
+
+    # copy modules for UEFI grub, 32-bit
+    mkdir -p "${BUILD_OUTPUT}"/boot/grub/i386-efi/
+    cp -a "${CHROOT_OUTPUT}"/usr/lib/grub/i386-efi/*.{mod,lst} "${BUILD_OUTPUT}"/boot/grub/i386-efi/
+
+    if ! [ -d "${TEMPLATE_DIRECTORY}"/GRML ] ; then
+      log    "Error: ${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting."
+      eerror "Error: ${TEMPLATE_DIRECTORY}/GRML does not exist. Exiting." ; eend 1
+      bailout 9
+    fi
 
-       DPKG_LIST="/var/log/fai/$HOSTNAME/last/dpkg.list" # the dpkg --list output of the chroot
-       if ! [ -r "$DPKG_LIST" ] ; then
-          ewarn "$DPKG_LIST could not be read, ignoring to store package information on ISO therefore."
-       else
-          einfo "Storing package list information as /GRML/${GRML_NAME}/packages.txt on ISO."
-          cp "$DPKG_LIST" "${BUILD_OUTPUT}"/GRML/"${GRML_NAME}"/packages.txt
-          eend $?
-       fi
+    mkdir -p "$BUILD_OUTPUT"/GRML/"${GRML_NAME}"/
+    cp -a ${TEMPLATE_DIRECTORY}/GRML/* "$BUILD_OUTPUT"/GRML/"${GRML_NAME}"/
 
-       # autostart for Windows:
-       if [ -d "${TEMPLATE_DIRECTORY}/windows/autostart/" ] ; then
-          cp ${TEMPLATE_DIRECTORY}/windows/autostart/* "$BUILD_OUTPUT"/
-       fi
+    # adjust boot splash information:
+    RELEASE_INFO="$GRML_NAME $VERSION - Release Codename $RELEASENAME"
+    RELEASE_INFO="$(cut_string 68 "$RELEASE_INFO")"
+    RELEASE_INFO="$(extend_string_end 68 "$RELEASE_INFO")"
+
+    if [ -r "$BUILD_OUTPUT"/GRML/"${GRML_NAME}"/grml-version ] ; then
+      sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/GRML/"${GRML_NAME}"/grml-version
+      sed -i "s/%DATE%/$DATE/"                                      "$BUILD_OUTPUT"/GRML/"${GRML_NAME}"/grml-version
+    fi
+
+    # make sure the squashfs filename is set accordingly:
+    SQUASHFS_NAME="$GRML_NAME.squashfs"
+
+    # adjust all variables in the templates with the according distribution information
+    adjust_boot_files "${BUILD_OUTPUT}"/boot/isolinux/*.cfg \
+      "${BUILD_OUTPUT}"/boot/isolinux/*.msg \
+      "${BUILD_OUTPUT}"/boot/grub/* \
+      "${BUILD_OUTPUT}"/boot/ubuntu/*
+
+    for param in ARCH DATE DISTRI_INFO DISTRI_NAME DISTRI_SPLASH GRML_NAME SQUASHFS_NAME \
+      RELEASE_INFO SHORT_NAME VERSION ; do
+      for file in $(find "${BUILD_OUTPUT}" -name "*%$param%*") ; do
+        value="$(eval echo '$'"$param")"
+        mv ${file} ${file/\%${param}\%/$value}
+      done
+    done
+
+    # adjust bootsplash accordingly but make sure the string has the according length
+    SQUASHFS_NAME="$(cut_string 20 "$SQUASHFS_NAME")"
+    SQUASHFS_NAME="$(extend_string_end 20 "$SQUASHFS_NAME")"
+    for file in f4 f5 ; do
+      if [ -r "${BUILD_OUTPUT}/boot/isolinux/${file}" ] ; then
+        sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/" "${BUILD_OUTPUT}/boot/isolinux/${file}"
+        sed -i "s/%SQUASHFS_NAME%/$SQUASHFS_NAME/" "${BUILD_OUTPUT}/boot/isolinux/${file}"
+      fi
+    done
+
+    # generate addon list
+    rm -f "${BUILD_OUTPUT}/${ADDONS_LIST_FILE}"
+    for name in "${BUILD_OUTPUT}"/boot/isolinux/addon_*.cfg ; do
+      include_name=$(basename "$name")
+      echo "include $include_name"  >> "${BUILD_OUTPUT}/${ADDONS_LIST_FILE}"
+    done
+
+    if ! [ -r "${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg" ] || [ "$DISTRI_NAME" = "grml" ] ; then
+      log "including grmlmain.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
+      echo "include grmlmain.cfg"    >  "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
+      echo "include default.cfg"     >  "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
+      echo "include menuoptions.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
+      echo "include grml.cfg"        >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
+
+      for f in "${BUILD_OUTPUT}"/boot/isolinux/submenu*.cfg ; do
+        echo "include $(basename $f)"     >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
+      done
+
+      echo "include options.cfg"     >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
+      if [ -z "$NO_ADDONS" ] ; then
+        echo "include addons.cfg"    >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
+      fi
+      echo "include isoprompt.cfg"   >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
+      echo "include hd.cfg"          >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
+      echo "include hidden.cfg"      >> "${BUILD_OUTPUT}/boot/isolinux/grmlmain.cfg"
+    else # assume we are building a custom distribution:
+      log "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it."
+      einfo "File ${BUILD_OUTPUT}/boot/isolinux/${DISTRI_NAME}.cfg found, using it."
+      if grep -q "^include ${DISTRI_NAME}.cfg" "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then
+        log "include for ${DISTRI_NAME}.cfg already present, nothing to do."
+        eindent
+        einfo "include for ${DISTRI_NAME}.cfg already present, nothing to do."
+        eoutdent
+        eend $?
+      else
+        log "including ${DISTRI_NAME}.cfg in ${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
+        echo "include ${DISTRI_NAME}.cfg" > "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
+        if [ -z "$NO_ADDONS" ] ; then
+          echo "include addons.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/distri.cfg"
+        fi
+      fi
+    fi
+
+    # use old style console based isolinux method only if requested:
+    if [[ "${ISOLINUX_METHOD}" == "console" ]] ; then
+      log 'Using console based isolinux method as requested via $ISOLINUX_METHOD.'
+      einfo 'Using console based isolinux method as requested via $ISOLINUX_METHOD.'
+      if grep -q '^include console.cfg' "${BUILD_OUTPUT}/boot/isolinux/distri.cfg" ; then
+        einfo "include for console.cfg already found, nothing to do."
+        eend 0
+      else
+        log "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
+        einfo "including console.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
+        echo "include console.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
+        eend $?
+      fi
+    else
+      log 'Using graphical boot menu.'
+      if grep -q '^include vesamenu.cfg' "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg" ; then
+        log "include for vesamenu.cfg already found, nothing to do."
+      else
+        log "including vesamenu.cfg in ${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
+        echo "include vesamenu.cfg" >> "${BUILD_OUTPUT}/boot/isolinux/isolinux.cfg"
+      fi
+    fi
+
+    if [ -e "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6 ]; then
+      sed -i "s/%RELEASE_INFO%/$GRML_NAME $VERSION - $RELEASENAME/" "$BUILD_OUTPUT"/boot/addons/bsd4grml/boot.6
+    fi
+
+    DPKG_LIST="/var/log/fai/$HOSTNAME/last/dpkg.list" # the dpkg --list output of the chroot
+    if ! [ -r "$DPKG_LIST" ] ; then
+      ewarn "$DPKG_LIST could not be read, ignoring to store package information on ISO therefore."
+    else
+      einfo "Storing package list information as /GRML/${GRML_NAME}/packages.txt on ISO."
+      cp "$DPKG_LIST" "${BUILD_OUTPUT}"/GRML/"${GRML_NAME}"/packages.txt
+      eend $?
+    fi
+
+    # autostart for Windows:
+    if [ -d "${TEMPLATE_DIRECTORY}/windows/autostart/" ] ; then
+      cp ${TEMPLATE_DIRECTORY}/windows/autostart/* "$BUILD_OUTPUT"/
+    fi
 
     FORCE_ISO_REBUILD=true
     einfo "Finished execution of stage 'boot'" ; eend 0
-    fi
   fi # BOOTSTRAP_ONLY
 else
-   log    'Error: Unsupported ARCH, sorry. Want to support it? Contribute!'
-   eerror 'Error: Unsupported ARCH, sorry. Want to support it? Contribute!' ; eend 1
-   bailout
+  log    'Error: Unsupported ARCH, sorry. Want to support it? Contribute!'
+  eerror 'Error: Unsupported ARCH, sorry. Want to support it? Contribute!' ; eend 1
+  bailout
 fi
 
 # support installation of local files into the chroot/ISO
@@ -1216,7 +1373,7 @@ fi
 # create md5sum file:
 if [ -z "$BOOTSTRAP_ONLY" ] ; then
   ( cd $BUILD_OUTPUT/GRML/"${GRML_NAME}" &&
-  find .. -type f -not -name md5sums -not -name isolinux.bin -exec md5sum {} \; > md5sums )
+  find ../.. -type f -not -name md5sums -not -name isolinux.bin -exec md5sum {} \; > md5sums )
 fi
 # }}}
 
@@ -1226,6 +1383,9 @@ fi
 
 if [ "$BOOT_METHOD" = "isolinux" ] ; then
    BOOT_ARGS="-no-emul-boot -boot-load-size 4 -boot-info-table -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat"
+   if [ "$HYBRID_METHOD" = "isohybrid" ] ; then
+     EFI_ARGS="-isohybrid-mbr /usr/lib/ISOLINUX/isohdpfx.bin -eltorito-alt-boot -e boot/efi.img -no-emul-boot -isohybrid-gpt-basdat"
+   fi
 elif [ "$BOOT_METHOD" = "grub2" ] ; then
    BOOT_ARGS="-no-emul-boot -boot-load-size 4 -b boot/grub/toriboot.bin"
 fi
@@ -1296,12 +1456,12 @@ else
          # make a 2048-byte bootsector for El Torito
          dd if=/dev/zero of=boot/grub/toriboot.bin bs=512 count=4 2>/dev/null
          # those are in 2048-byte sectors, so 1 16 matches 4 63 below
-         echo 1 16 | mksh /usr/share/grml-live/scripts/bootgrub.mksh -B 11 | \
+         echo 1 16 | mksh "${SCRIPTS_DIRECTORY}/bootgrub.mksh" -B 11 | \
             dd of=boot/grub/toriboot.bin conv=notrunc 2>/dev/null
       fi
-      log "$MKISOFS -V '${GRML_NAME} ${VERSION}' -publisher 'grml-live | grml.org' -l -r -J $BOOT_ARGS -o ${ISO_OUTPUT}/${ISO_NAME} ."
+      log "$MKISOFS -V '${GRML_NAME} ${VERSION}' -publisher 'grml-live | grml.org' -l -r -J $BOOT_ARGS $EFI_ARGS -no-pad -o ${ISO_OUTPUT}/${ISO_NAME} ."
       $MKISOFS -V "${GRML_NAME} ${VERSION}" -publisher 'grml-live | grml.org' \
-              -l -r -J $BOOT_ARGS -no-pad \
+              -l -r -J $BOOT_ARGS $EFI_ARGS -no-pad \
               -o "${ISO_OUTPUT}/${ISO_NAME}" . ; RC=$?
       # both of these need core.img there, so it’s easier to write it here
       if [ "$BOOT_METHOD" = "grub2" ] || [ "$HYBRID_METHOD" = "grub2" ]; then
@@ -1338,49 +1498,23 @@ else
             log   "Creating hybrid ISO file with manifold/grub2 method"
             einfo "Creating hybrid ISO file with manifold/grub2 method"
             # 512 bytes: MBR, partition table, load GRUB 2
-            echo 4 63 | mksh /usr/share/grml-live/scripts/bootgrub.mksh -A -M 4:0x96 -g $cyls:16:32
+            echo 4 63 | mksh "${SCRIPTS_DIRECTORY}/bootgrub.mksh" -A -M 4:0x96 -g $cyls:16:32
           else
             log   "Creating hybrid ISO file with manifold method"
             einfo "Creating hybrid ISO file with manifold method"
             # read only one but 2048-byte sized (scale: << 2) sector
             echo $bootoff $bootoff | \
-              mksh /usr/share/grml-live/scripts/bootilnx.mksh -A -M 4:0x96 -g $cyls:16:32 -S 2
+              mksh ${SCRIPTS_DIRECTORY}/bootilnx.mksh -A -M 4:0x96 -g $cyls:16:32 -S 2
           fi | dd of="${ISO_OUTPUT}/${ISO_NAME}" conv=notrunc 2>/dev/null
           eend $?
         fi
       elif [ "$HYBRID_METHOD" = "isohybrid" ] ; then
-        if ! which isohybrid >/dev/null 2>&1 ; then
-          bailout 12 "isohybrid binary not found - please install syslinux/syslinux-common"
-        else
-          log   "Creating hybrid ISO file with isohybrid method"
-          einfo "Creating hybrid ISO file with isohybrid method"
-          # Notes for consideration:
-          # "-entry 4 -type 1c"
-          # * using 4 as the partition number is supposed to help with BIOSes
-          #   that only support USB-Zip boot
-          # * using 1c (i.e. hidden FAT32 LBA), instead of the default 0x17
-          #   (hidden NTFS, IIRC), as the partition type is sometimes needed
-          #   to get the BIOS even look at the partition created by isohybrid
-          if isohybrid --help | grep -q -- --uefi ; then
-            if echo $CLASSES | grep -qw I386 ; then
-              log   "Detected uefi support for isohybrid but 32bit systems do not support it, ignoring."
-              einfo "Detected uefi support for isohybrid but 32bit systems do not support it, ignoring."
-            else
-              log   "Detected uefi support for isohybrid, enabling"
-              einfo "Detected uefi support for isohybrid, enabling"
-              ISOHYBRID_OPTIONS=--uefi
-            fi
-          fi
-
-          log "isohybrid $ISOHYBRID_OPTIONS ${ISO_OUTPUT}/${ISO_NAME}"
-          isohybrid $ISOHYBRID_OPTIONS "${ISO_OUTPUT}/${ISO_NAME}"
-          eend $?
-        fi
+        : # nothing to do, handled via $MKISOFS $EFI_ARGS already
       else
         bailout 12 "Unknown HYBRID_METHOD [${HYBRID_METHOD}]. Supported values: disable, isohybrid, grub2, manifold"
       fi
 
-      # generate md5sum and sha1sum of ISO if we are using class 'RELEASE':
+      # generate ISO checksums if we are using class 'RELEASE':
       case $CLASSES in *RELEASE*)
          [ "$RC" = 0 ] && \
          (
@@ -1389,6 +1523,10 @@ else
              touch -r ${ISO_NAME} ${ISO_NAME}.md5
              sha1sum ${ISO_NAME} > ${ISO_NAME}.sha1 && \
              touch -r ${ISO_NAME} ${ISO_NAME}.sha1
+             sha256sum ${ISO_NAME} > ${ISO_NAME}.sha256 && \
+             touch -r ${ISO_NAME} ${ISO_NAME}.sha256
+             sha512sum ${ISO_NAME} > ${ISO_NAME}.sha512 && \
+             touch -r ${ISO_NAME} ${ISO_NAME}.sha512
            fi
          )
          ;;
@@ -1424,10 +1562,18 @@ create_netbootpackage() {
 
   mkdir -p "$NETBOOT"
 
-  if ! [ -r "${CHROOT}/usr/lib/syslinux/pxelinux.0" ] ; then
-    ewarn "File /usr/lib/syslinux/pxelinux.0 not found in build chroot." ; eend 0
+  # since syslinux v3:6.03~pre1+dfsg-4 the pxelinux.0 has been split into a
+  # separate pxelinux package
+  if [ -d "${CHROOT_OUTPUT}/usr/lib/PXELINUX/" ] ; then
+    local pxelinux_dir=/usr/lib/PXELINUX
+  else
+    local pxelinux_dir=/usr/lib/syslinux
+  fi
+
+  if ! [ -r "${CHROOT_OUTPUT}/${pxelinux_dir}/pxelinux.0" ] ; then
+    ewarn "File ${pxelinux_dir}/pxelinux.0 not found in build chroot." ; eend 0
     eindent
-    einfo "Install syslinux[-common] package in chroot to get a netboot package."
+    einfo "Install syslinux[-common]/pxelinux package in chroot to get a netboot package."
     eoutdent
     return 0
   fi
@@ -1439,7 +1585,11 @@ create_netbootpackage() {
 
   cp "${CHROOT_OUTPUT}"/boot/vmlinuz-*    "$WORKING_DIR"/vmlinuz
   cp "${CHROOT_OUTPUT}"/boot/initrd.img-* "$WORKING_DIR"/initrd.img
-  cp "${CHROOT_OUTPUT}"/usr/lib/syslinux/pxelinux.0 "${WORKING_DIR}/pxelinux.0"
+  cp "${CHROOT_OUTPUT}/${pxelinux_dir}/pxelinux.0" "${WORKING_DIR}/pxelinux.0"
+
+  if [ -r "${CHROOT_OUTPUT}"/usr/lib/syslinux/modules/bios/ldlinux.c32 ] ; then
+    cp "${CHROOT_OUTPUT}"/usr/lib/syslinux/modules/bios/ldlinux.c32 "${WORKING_DIR}"/
+  fi
 
   mkdir -p "${WORKING_DIR}/pxelinux.cfg"
   if [ -r "${BUILD_OUTPUT}/boot/isolinux/netboot.cfg" ] ; then
@@ -1457,6 +1607,8 @@ create_netbootpackage() {
     (
       cd $(dirname "${OUTPUT_FILE}")
       sha1sum $(basename "${OUTPUT_FILE}") > "${OUTPUT_FILE}.sha1"
+      sha256sum $(basename "${OUTPUT_FILE}") > "${OUTPUT_FILE}.sha256"
+      sha512sum $(basename "${OUTPUT_FILE}") > "${OUTPUT_FILE}.sha512"
     )
     einfo "Generated netboot package ${OUTPUT_FILE}" ; eend 0
     rm -rf "${OUTPUTDIR}"